Go语法陷阱
字符串遍历
Go语言的字符有以下两种:
- 一种是 uint8 类型,等价于 byte 型,代表了 ASCII 码的一个字符。
- 另一种是 rune 类型,等价于 int32 类型。代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。
下面两种不同遍历方式,导致取出的值的类型不同
当把字符作为map的key时,需要注意类型的一致
func main() { byteArr := "Hi,世界" // int32 rune遍历,支持中文 for i, v := range byteArr { fmt.Println(i, v, reflect.TypeOf(v)) } // uint8 遍历,仅支持英文字母 for i := 0; i < len(byteArr); i++ { v := byteArr[i] fmt.Println(i, v, reflect.TypeOf(v)) } // 以字符形式打印 int32 for i, v := range byteArr { fmt.Println(i, string(v), reflect.TypeOf(v)) } }
切片陷阱
func fun1(a [2]int) { a[0] = 100 } func fun2(a []int) { a[0] = 100 } func fun3(a []int) { a = append(a, 3) } func main() { a1 := [2]int{1, 2} fun1(a1) fmt.Println("fun1 结果:", a1) // 1 2 a2 := []int{1, 2} fun2(a2) fmt.Println("fun2 结果:", a2) // 100 2 a3 := []int{1, 2} fun3(a3) fmt.Println("fun3 结果:", a3) // 1 2 }
递归函数
函数内的递归函数得先声明再定义,不能直接:=
func findTarget(root *TreeNode, k int) bool { // 因为是递归函数,所以先声明这个函数 而不是直接 dfs:=func(){} ok := false //var mp map[int]bool mp := make(map[int]bool) var dfs func(rt *TreeNode, k int) dfs = func(rt *TreeNode, k int) { if rt == nil || ok { return } dfs(rt.Left, k) if _, v := mp[k-rt.Val]; v { ok = true } mp[rt.Val] = true dfs(rt.Right, k) } dfs(root, k) return ok }
:= 的问题
// 函数外不能使用:= // 错误 b := 1 // 正确 var b int = 1 var b = 1 // b := a 错误 func fun1(a int) (b int) { b := a return } // b = a 正确 func fun1(a int) (b int) { b = a return } // b := a 正确 func fun2(a int) int { b := a return b }
strconv问题
// "1 2 3" 字符串转整数切片 1 2 3 func tran(str string) []int { // 一定要判空 if str == "" { return make([]int, 0) } // 如果str=="",会返回含有一个0元素的切片,"" -> 0 // strs: len:1, cap:1, strs[0]: "" // 导致 strconv.Atoi(v) v为“” 转换成0添加进去 strs := strings.Split(str, " ") ans := make([]int, 0) for _, v := range strs { v, _ := strconv.Atoi(v) ans = append(ans, v) } return ans }
自增运算符
i++ 正确 ++i 错误 a += i++ 错误