go语言容易踩的坑

切片

range 取地址

1
2
3
4
5
6
7
8
9
10
11
func main() {
arr := []int{1, 2, 3}
myMap := make(map[int]*int)
for i, v := range arr {
myMap[i] = &v
}
for _, v := range myMap {
fmt.Println(*v)
}
}
//输出 3 3 3
1
2
3
4
5
6
7
8
9
10
11
//正确写法
func main() {
arr := []int{1, 2, 3}
myMap := make(map[int]*int)
for i, v := range arr {
myMap[i] = &arr[i]
}
for _, v := range myMap {
fmt.Println(*v)
}
}

死循环?

1
2
3
4
5
6
7
8
9
10
func main() {
arr := []int{1, 2, 3}
for _, v := range arr {
arr = append(arr, v)
}
fmt.Println(arr)
}

//输出 [1 2 3 1 2 3]
//range 的arr是一个copy

切片传参

1
2
3
4
5
6
7
8
9
10
11
func test(arr []int) {
arr[0] = 4
arr = append(arr, 1)
}

func main() {
arr := []int{1, 2, 3}
test(arr)
fmt.Println(arr)
}
//输出 4 2 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//切片底层结构
type SliceHeader struct{
Data uintptr
Len int
Cap int
}

//正确写法
func test(arr []int) []int {
arr[0] = 4
arr = append(arr, 1)
return arr
}

func main() {
arr := []int{1, 2, 3}
arr = test(arr)
fmt.Println(arr)
}

切片copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func main() {
a := []int{1, 2, 3, 4, 5}
b := a
b[0] = 9
fmt.Println(a)
}

func main() {
a := []int{1, 2, 3, 4, 5}
b := make([]int, 3)
b = a[:3]
b[0] = 9
b = append(b, 10)
fmt.Println(a)
}

//输出
// [9 2 3 4 5]
// [9 2 3 10 5]


func main() {
a := []int{1, 2, 3, 4, 5}
b := make([]int, len(a))
copy(b, a)
b[0] = 10
fmt.Println(a)
}

json.Unmarshal

null

1
2
3
4
5
6
7
8
9
10
11
func main() {
s := "null"
m := make(map[string]interface{})
if err := json.Unmarshal([]byte(s), &m); err != nil {
fmt.Println(err.Error())
}
m["test"] = 1
fmt.Println(m)
}

//panic: assignment to entry in nil map
1
2
3
4
5
6
7
8
9
10
11
12
13
//正确写法
func main() {
s := "null"
m := make(map[string]interface{})
if err := json.Unmarshal([]byte(s), &m); err != nil {
fmt.Println(err.Error())
}
if m==nil{
return
}
m["test"] = 1
fmt.Println(m)
}

interface{}接收数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func main() {
str := `{"name": "张三", "age": 20}`
var mp map[string]interface{}
err := json.Unmarshal([]byte(str), &mp)
if err != nil {
return
}
var age int
age = mp["age"].(int)
fmt.Println(age)
}

//使用 Golang 解析 json 格式数据时,若以 interface{} 接收数据,则会按照下列规则进行解析:
bool for JSON booleans
float64 for JSON numbers
string for JSON strings
[]interface{} for JSON arrays
map[string]interface{} for JSON objects
nil for JSON null

defer

defer和return的执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
func test() (b int) {
defer func() {
b += 10
}()
return b
}
func test1() (b int) {
b = 10
defer func() {
b += 10
}()
return
}

func test2() int {
b := 10
defer func() {
b += 10
}()
return b
}

func test3() *int {
b := 10
defer func() {
b += 10
}()
return &b
}

func main() {
fmt.Println(test1())
fmt.Println(test2())
fmt.Println(*test3())
}
//输出 20 10 20

闭包

闭包是通过指针操作母函数中的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
func myPrint(x int) {
fmt.Println("defer", x)
}
func test1() (x int) {
defer myPrint(x)
x = 10
return
}
func test2() (x int) {
defer func() {
myPrint(x)
}()
x = 10
return
}
func test3() (x int) {
defer func(a int) {
myPrint(a)
}(x)
x = 10
return
}
func main() {
var res int
fmt.Println("test1 ")
res = test1()
fmt.Println("main", res)
fmt.Println("test2")
res = test2()
fmt.Println("main", res)
fmt.Println("test3")
res = test3()
fmt.Println("main", res)
}
//输出
test1
defer 0
main 10
test2
defer 10
main 10
test3
defer 0
main 10

注意变量的作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func Foo() (err error) {
if err := Bar(); err != nil {
return
}
return
}

//正确写法
func Foo() (err error) {
if err := Bar(); err != nil {
return err
}
return
}

//或
func Foo() (err error) {
if er := Bar(); er != nil {
err = er
return
}
return
}

map

初始化的时候尽量指定map容量

1
m := make(map[int],100)

range 便利map时,注意map的无序性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func main() {
max := 10
mp := make(map[int]int, max)
for i := 0; i < max; i++ {
mp[i] = i + 1
}

for k, v := range mp {
fmt.Println(k, v)
}
}


func main() {
max := 10
mp := make(map[int]int, max)
arr := make([]int, 0, max)
for i := 0; i < max; i++ {
mp[i] = i + 1
arr = append(arr, i)
}

for _, v := range arr {
fmt.Println(v, mp[v])
}
}

nil map写入会panic

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
var mp map[int]struct{}
mp[1] = struct{}{}
fmt.Println(mp)
}

//panic: assignment to entry in nil map

func main() {
mp := make(map[int]struct{})
mp[1] = struct{}{}
fmt.Println(mp)
}

map不是并发安全的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
func main() {
max := 100
mp := make(map[int]int, max)

wg := sync.WaitGroup{}
wg.Add(max)
for i := 0; i < max; i++ {
tmp := i
go func() {
defer func() {
wg.Done()
}()
mp[tmp] = tmp
}()
}
wg.Wait()
fmt.Println(mp)
}
//fatal error: concurrent map writes

func main() {
max := 100
var mp sync.Map
wg := sync.WaitGroup{}
wg.Add(max)
for i := 0; i < max; i++ {
tmp := i
go func() {
defer func() {
wg.Done()
}()
mp.Store(tmp, tmp)
}()
}
wg.Wait()
mp.Range(func(k, v interface{}) bool {
fmt.Println(k, v)
return true
})
}