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