2516 字
13 分钟
01、字符串

01、字符串#

func main() {
// 1. 判断字符串中汉字的数量
// 难点是判断一个字符是汉字
// s1 := "Hello沙河안녕하세요こんにちは"
// // 1. 依次拿到字符串中的字符
// var count int
// for _, c := range s1 {
// // 2. 判断当前这个字符是不是汉字
// if unicode.Is(unicode.Javanese, c) {
// count++
// }
// }
// 3. 把汉字出现的次数累加得到最终结果
// fmt.Println(count)
// 2. how do you do 单词出现的次数
// s2 := "how do you do"
// // 2.1 把字符串按照空格切割得到切片
// s3 := strings.Split(s2, " ")
// // 2.2 遍历切片存储到一个map
// m1 := make(map[string]int, 10)
// for _, w := range s3 {
// // 1. 如果原来map中不存在w这个key那么出现次数=1
// if _, ok := m1[w]; !ok {
// m1[w] = 1
// } else {
// m1[w]++
// }
// // 2. 如果map中存在w这个key,那么出现次数+1
// }
// // 2.3 累加出现的次数
// for key, value := range m1 {
// fmt.Println(key, value)
// }
// 回文判断
// 字符串从左往右读和从右往左读是一样的,那么就是回文。
// 上海自来水来自海上 s[0] s[len(s)-1]
// 山西运煤车煤运西山
// 黄山落叶松叶落山黄
ss := "a山西运煤车煤运西山a"
// 解题思路:
// 把字符串中的字符拿出来放到一个[]rune中
// []int []string []bool []float64 []byte []rune []map[string]int
r := make([]rune, 0, len(ss))
for _, c := range ss {
r = append(r, c)
}
fmt.Println("[]rune:", r)
for i := 0; i < len(r)/2; i++ {
// 山 ss[0] ss[len(ss)-1]
// 西 ss[1] ss[len(ss)-1-1]
// 运 ss[2] ss[len(ss)-1-2]
// 煤 ss[3] ss[len(ss)-1-3]
// ...
// c ss[i] ss[len(ss)-1-i]
if r[i] != r[len(r)-1-i] {
fmt.Println("不是回文")
return
}
}
fmt.Println("是回文")
}

02、函数使用技巧#

// 函数:一段代码的封装
func f1() {
fmt.Println("Hello 沙河!")
}
func f2(name string) {
fmt.Println("Hello", name)
}
// 带参数和返回值的函数
func f3(x int, y int) int {
sum := x + y
return sum
}
// 参数类型简写
func f4(x, y int) int {
return x + y
}
// 可变参数
func f5(title string, y ...int) int {
fmt.Println(y) // y是一个int类型的切片
return 1
}
// 命名返回值
func f6(x, y int) (sum int) {
sum = x + y // 如果使用命名的返回值,那么在函数中可以直接使用返回值变量
return // 如果使用命名的返回值,return后面可以省略返回值变量
}
// Go语言中支持多个返回值
func f7(x, y int) (sum int, sub int) {
sum = x + y
sub = x - y
return
}
func main() {
f1()
f2("理想")
f2("姬无命")
fmt.Println(f3(100, 200)) // 调用函数
ret := f3(100, 200)
fmt.Println(ret)
f5("lixiang", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 在一个命名的函数中不能够再声明命名函数
// func f8(){
// }
}

03、defer_func#

// defer
// defer多用于函数结束之前释放资源(文件句柄、数据库连接、socket连接)
func deferDemo() {
fmt.Println("start")
defer fmt.Println("嘿嘿嘿") // defer把它后面的语句延迟到函数即将返回的时候再执行
defer fmt.Println("呵呵呵") // 一个函数中可以有多个defer语句
defer fmt.Println("哈哈哈") // 多个defer语言按照先进后出(后进先出)的顺序延迟执行
fmt.Println("end")
}
func main() {
deferDemo()
}

04、defer_return#

// Go语言中函数的return不是原子操作,在底层是分为两步来执行
// 第一步:返回值赋值
// defer
// 第二步:真正的RET返回
// 函数中如果存在defer,那么defer执行的时机是在第一步和第二步之间
func f1() int {
x := 5
defer func() {
x++ // 修改的是x不是返回值
}()
return x // 1. 返回值赋值 2. defer 3. 真正的RET指令
}
func f2() (x int) {
defer func() {
x++
}()
return 5 // 返回值=x
}
func f3() (y int) {
x := 5
defer func() {
x++ // 修改的是x
}()
return x // 1. 返回值 = y = x = 5 2. defer修改的是x 3. 真正的返回
}
func f4() (x int) {
defer func(x int) {
x++ // 改变的是函数中x的副本
}(x)
return 5 // 返回值 = x = 5
}
func f5() (x int) {
defer func(x int) int {
x++
return x
}(x)
return 5
}
// 传一个x的指针到匿名函数中
func f6() (x int) {
defer func(x *int) {
(*x)++
}(&x)
return 5 // 1. 返回值=x=5 2. defer x=6 3. RET返回
}
func main() {
fmt.Println(f1()) // 5
fmt.Println(f2()) // 6
fmt.Println(f3()) // 5
fmt.Println(f4()) // 5
fmt.Println(f5()) // 5
fmt.Println(f6()) // 6
}

05、global_var#

// 变量的作用域
var x = 100 // 定义一个全局变量
// 定义一个函数
func f1() {
// x := 10
name := "理想"
// 函数中查找变量的顺序
// 1. 先在函数内部查找
// 2. 找不到就往函数的外面查找,一直找到全局
fmt.Println(x, name)
}
func main() {
f1()
// fmt.Println(name) // 函数内部定义的变脸只能在该函数内部使用
// 语句块作用域
if i := 10; i < 18 {
fmt.Println("乖乖上学")
}
// fmt.Println(i) // 不存在i
for j := 0; j < 5; j++ {
fmt.Println(j)
}
// fmt.Println(j) // 不存在j
}

06、func_type#

// 函数类型
func f1() {
fmt.Println("Hello 沙河")
}
func f2() int {
return 10
}
func f4(x, y int) int {
return x + y
}
// 函数也可以作为参数的类型
func f3(x func() int) {
ret := x()
fmt.Println(ret)
}
func ff(a, b int) int {
return a + b
}
// 函数还可以作为返回值
func f5(x func() int) func(int, int) int {
return ff
}
func main() {
a := f1
fmt.Printf("%T\n", a)
b := f2
fmt.Printf("%T\n", b)
f3(f2)
f3(b)
fmt.Printf("%T\n", f4)
// f3(f4)
f7 := f5(f2)
fmt.Printf("%T\n", f7)
}

07、匿名函数#

// 匿名函数
// var f1 = func(x, y int) {
// fmt.Println(x + y)
// }
func main() {
// 函数内部没有办法声明带名字的函数
// 匿名函数
f1 := func(x, y int) {
fmt.Println(x + y)
}
f1(10, 20)
// 如果只是调用一次的函数,还可以简写成立即执行函数
func(x, y int) {
fmt.Println(x + y)
fmt.Println("Hello world!")
}(100, 200)
}

08、闭包#

// 闭包
func f1(f func()) {
fmt.Println("this is f1")
f()
}
func f2(x, y int) {
fmt.Println("this is f2")
fmt.Println(x + y)
}
// 要求:
// f1(f2)
func f3(f func(int, int), x, y int) func() {
tmp := func() {
f(x, y)
}
return tmp
}
func main() {
ret := f3(f2, 100, 200) // 把原来需要传递两个int类型的参数包装成一个不需要传参的函数
fmt.Printf("%T\n", ret)
// ret()
f1(ret)
}

09、闭包2#

// 闭包是什么?
// 闭包是一个函数,这个函数包含了他外部作用域的一个变量
// 底层的原理:
// 1. 函数可以作为返回值
// 2. 函数内部查找变量的顺序,先在自己内部找,找不到往外层找
func adder1() func(int) int {
var x int = 100
return func(y int) int {
x += y
return x
}
}
func adder2(x int) func(int) int {
return func(y int) int {
x += y
return x
}
}
func main() {
ret := adder2(100)
ret2 := ret(200)
fmt.Println(ret2)
}

10、闭包3#

// 闭包
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
jpgFunc := makeSuffixFunc(".jpg")
txtFunc := makeSuffixFunc(".txt")
fmt.Println(jpgFunc("test")) //test.jpg
fmt.Println(jpgFunc("呵呵.jpg"))
fmt.Println(txtFunc("test")) //test.txt
fmt.Println(txtFunc("呵呵.txt"))
}

11、闭包4#

// 关键字 函数名(参数)(返回值){}
func calc(base int) (func(int) int, func(int) int) {
add := func(i int) int {
base += i
return base
}
sub := func(i int) int {
base -= i
return base
}
return add, sub
}
func main() {
f1, f2 := calc(10)
fmt.Println(f1(1), f2(2)) // 11 9
fmt.Println(f1(3), f2(4)) // 12 8;13 9
fmt.Println(f1(5), f2(6)) // 13 7
}

12、defer + 闭包#

// defer
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
a := 1
b := 2
defer calc("1", a, calc("10", a, b))
a = 0
defer calc("2", a, calc("20", a, b))
b = 1
}
// 1. a:=1
// 2. b:=2
// 3. defer calc("1", 1, calc("10", 1, 2))
// 4. calc("10", 1, 2) // "10" 1 2 3
// 5. defer calc("1", 1, 3)
// 6. a = 0
// 7. defer calc("2", 0, calc("20", 0, 2))
// 8. calc("20", 0, 2) // "20" 0 2 2
// 9. defer calc("2", 0, 2)
// 10. b = 1
// calc("2", 0, 2) // "2" 0 2 2
// calc("1", 1, 3) // "1" 1 3 4
// 最终的答案:
// "10" 1 2 3
// "20" 0 2 2
// "2" 0 2 2

13、panic_recover#

// panic 和 recover
// panic和recover其实就类似于其他语言中的throw和catch,方便进行多层嵌套的错误处理
func funcA() {
fmt.Println("a")
}
func funcB() {
// 刚刚打开数据库连接
defer func() {
err := recover()
fmt.Println(err)
fmt.Println("释放数据库连接...")
}()
panic("出现了严重的错误!!!") // 程序崩溃退出
fmt.Println("b")
}
func funcC() {
fmt.Println("c")
}
func main() {
funcA()
funcB()
funcC()
}

14、fmt#

func main() {
// fmt.Print("沙河")
// fmt.Print("娜扎")
// fmt.Println("--------")
// fmt.Println("沙河")
// fmt.Println("娜扎")
// Printf("格式化字符串", 值)
// %T :查看类型
// %d :十进制数
// %b :二进制数
// %o :八进制数
// %x :十六进制数
// %c : 字符
// %s :字符串
// %p: 指针
// %v: 值
// %f:浮点数
// %t :布尔值
// var m1 = make(map[string]int, 1)
// m1["理想"] = 100
// fmt.Printf("%v\n", m1)
// fmt.Printf("%#v\n", m1)
// printBaifenbi(90)
// fmt.Printf("%v\n", 100)
// // 整数->字符
// fmt.Printf("%q\n", 65)
// // 浮点数和复数
// fmt.Printf("%b\n", 3.14159265354697)
// // 字符串
// fmt.Printf("%q\n", "李想有理想")
// fmt.Printf("%7.3s\n", "李想有理想")
// 获取用户输入
// var s string
// fmt.Scan(&s)
// fmt.Println("用户输入的内容是:", s)
// var (
// name string
// age int
// class string
// )
// // fmt.Scanf("%s %d %s\n", &name, &age, &class)
// // fmt.Println(name, age, class)
// fmt.Scanln(&name, &age, &class)
// fmt.Println(name, age, class)
fmt.Printf("%b\n", 1024)
}
func printBaifenbi(num int) {
fmt.Printf("%d%%\n", num)
}

15、homework - 练习#

package main
import "fmt"
/*
你有50枚金币,需要分配给以下几个人:Matthew,Sarah,Augustus,Heidi,Emilie,Peter,Giana,Adriano,Aaron,Elizabeth。
分配规则如下:
a. 名字中每包含1个'e'或'E'分1枚金币
b. 名字中每包含1个'i'或'I'分2枚金币
c. 名字中每包含1个'o'或'O'分3枚金币
d: 名字中每包含1个'u'或'U'分4枚金币
写一个程序,计算每个用户分到多少金币,以及最后剩余多少金币?
程序结构如下,请实现 ‘dispatchCoin’ 函数
*/
var (
coins = 5000
users = []string{
"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
}
distribution = make(map[string]int, len(users))
)
func main() {
left := dispatchCoin()
fmt.Println("剩下:", left)
}
func dispatchCoin() (left int) {
// 1. 依次拿到每个人的名字
// 2. 拿到一个人名根据分金币的规则去分金币,
// 2.1 每个人分的金币数应该保存到 distribution 中
// 2.2 还要记录下剩余的金币数
// 3. 整个第2步执行完就能得到最终每个人分的金币数和剩余金币数
return
}
01、字符串
https://blog.zhequtao.com/posts/golang/go-new/base/base03/
作者
阿俊
发布于
2020-03-30
许可协议
CC BY-NC-SA 4.0

相关阅读