美文网首页
Go 进阶 2 值、指针的小坑

Go 进阶 2 值、指针的小坑

作者: 听海吹牛逼的声音 | 来源:发表于2019-03-24 03:58 被阅读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

相关文章

  • Go 进阶 2 值、指针的小坑

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

  • Go语言学习笔记(三)

    指针 Go的指针不能运算 参数传递 Go的参数传递是值传递(值传递:开辟新的空间,拷贝传递参数的值,引用传递:引用...

  • GO语言基础(三)

    指针 Go 拥有指针。指针保存了值的内存地址。 类型 *T 是指向 T 类型值的指针。其零值为 nil。 & 操作...

  • 【技术】Golang初探——指针、数组、map、函数

    指针 Go 具有指针。 指针保存了变量的内存地址。类型 *T 是指向类型 T 的值的指针。其零值是 nil。 '*...

  • Go 指南 复杂类型

    一、指针 Go 具有指针。 指针保存了变量的内存地址。 类型 *T 是指向类型 T 的值的指针。其零值是 nil ...

  • go 语言指针

    go 语言指针 go 语言的参数传递全部都是 值传递 用一个交换的例子学习指针

  • 指针、数组、分片

    1、指针 Go 拥有指针。指针保存了值的内存地址。类型*T是指向T类型值的指针。其零值为nil。&操作符会生成一个...

  • GO 一文搞懂指针和地址值的区别

    GO 语言的指针和地址值 go语言中的指针和地址值,在使用上常常具有迷惑性,主要是其特殊的*、&符号的使用,可能会...

  • Go 指针声明后赋值,出现 panic: runtime err

    指针基础知识 在 Go 中 * 代表取指针地址中存的值即指针的值(这个值是一个内存地址),& 代表取一个值的内存地...

  • 六、Go指针

    六、Go语言指针 1.使用&访问变量在内存中地址 2.指针 一个指针变量指向一个值的内存地址。 与变量和常量相同,...

网友评论

      本文标题:Go 进阶 2 值、指针的小坑

      本文链接:https://www.haomeiwen.com/subject/ziryvqtx.html