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++ 错误