Go 进阶 2 值、指针的小坑

2019-03-24  本文已影响0人  听海吹牛逼的声音

写的时候遇到个小坑。过于想当然,以为用法和java一样写就得了。单测的时候发现问题了。

在for x...:= range (slice/map) 的这种语法中,前面的x...都是临时变量,所以有时会导致一些错误。分3种情况:

  1. 如果就是读一个slice或者map,那无所谓,可以这么写。
  2. 如果想修改这个x,这时候会有问题,因为这个x只是slice/map里面存的数据的副本。
    2.1 如果slice里面就是struct,用range的方式不能修改,所以应该是用slice[index]或者map[key]来修改。
    2.3 如果不想那么写,那slice里面存的得是指针*struct。所以x是副本,但是指向同一个地址,所以修改x有效。
  3. 如果想取x的地址,但是slice/map里面又是struct,那就需要用index/key来搞;如果里面存的是pointer,那就可以直接用x赋值,因为指向的地址一样。
type Student struct {
    Age int
}

func TestForLoop() {
    students := []Student{{1}, {2}, {3}}

    fmt.Println("wrong way:")
    for i, stu := range students {
        fmt.Printf("index: %d, addres:%p\n", i, &stu)
        stu.Age = 100
    }
    fmt.Println(students)

    fmt.Println("\nright way:")
    for i := 0; i < len(students); i++ {
        fmt.Printf("index: %d, addres:%p\n", i, &students[i])
    }

    fmt.Println("\nmap to struct:")
    name2Student := map[string]Student{"1":{1}, "2":{2}, "3":{3}}
    for name, stu := range name2Student {
        fmt.Printf("index: %s, addres:%p\n", name, &stu)
        stu.Age = 100
    }
    fmt.Println(name2Student)

    fmt.Println("\nmap to pointer of struct:")
    var temp *Student
    name2StudentPointer := map[string]*Student{"1":{1}, "2":{2}, "3":{3}}
    for name, stu := range name2StudentPointer {
        fmt.Printf("index: %s, addres:%p\n", name, &stu)
        stu.Age = 100
        if name == "1" {
            temp = stu
        }
    }
    fmt.Printf("%+v\n", name2StudentPointer["1"])

    fmt.Println("\nmodify by temp pointer:")
    fmt.Println(temp.Age)
    temp.Age = 10
    fmt.Printf("%+v\n", name2StudentPointer["1"])
}

func main() {
    TestForLoop()
}

output:

wrong way:
index: 0, addres:0xc42001e4c0
index: 1, addres:0xc42001e4c0
index: 2, addres:0xc42001e4c0
[{1} {2} {3}]

right way:
index: 0, addres:0xc42001c380
index: 1, addres:0xc42001c388
index: 2, addres:0xc42001c390

map to struct:
index: 1, addres:0xc42001e518
index: 2, addres:0xc42001e518
index: 3, addres:0xc42001e518
map[3:{3} 1:{1} 2:{2}]

map to pointer of struct:
index: 1, addres:0xc42000e038
index: 2, addres:0xc42000e038
index: 3, addres:0xc42000e038
&{Age:100}

modify by temp pointer:
100
&{Age:10}

Process finished with exit code 0

上一篇 下一篇

猜你喜欢

热点阅读