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 213、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}