golang 和 python 字符串地址对比

python:

In [1]: a = "AB"                                                                                                                                              

In [2]: id(a)                                                                                                                                                 
Out[2]: 4564190912

In [3]: a = "CD"                                                                                                                                              

In [4]: id(a)                                                                                                                                                 
Out[4]: 4567124992

# 不同的内存地址

 

golang:

package main

import "fmt"

func main() {
    ch := make(chan string, 3)
    ch <- "A"
    ch <- "B"
    ch <- "C"

    fmt.Println(<-ch)
    fmt.Println(<-ch)
    fmt.Println(<-ch)

    a := "AB"
    fmt.Printf("a1 %p | %v\n", &a, a)
    a = "无产阶级大团结万岁"
    fmt.Printf("a2 %p | %v\n", &a, a)

    // a1 和 a2 相同的内存地址

    intSlice := []int{1, 2, 3, 4, 5}
    for i := range intSlice {
        fmt.Printf("i%v %p\n", i, &i)
    }
    fmt.Println("-------------------")
    for s := range "hello, world" {
        fmt.Println("=========")
        fmt.Printf("old s%v %p\n", s, &s)
        s := s
        fmt.Printf("new s%v %p\n", s, &s)
    }
}

运行结果:

/*
NEOdeMacBook-Pro:buffered_channels zhenxink$ go run bf_ch_order_spe_28.go 
A
B
C
a1 0xc000108070 | AB
a2 0xc000108070 | 无产阶级大团结万岁
i0 0xc00010c020
i1 0xc00010c020
i2 0xc00010c020
i3 0xc00010c020
i4 0xc00010c020
-------------------
=========
old s0 0xc00010c048
new s0 0xc00010c050
=========
old s1 0xc00010c048
new s1 0xc00010c060
=========
old s2 0xc00010c048
new s2 0xc00010c078
=========
old s3 0xc00010c048
new s3 0xc00010c090
=========
old s4 0xc00010c048
new s4 0xc00010c0a8
=========
*/

 

所以,需要注意 golang 中的基于 for range 循环的变量捕获问题,如下:

错误写法:

var rmdirs []func()
for _, dir := range tempDirs() {
    os.MkdirAll(dir, 0755)
    rmdirs = append(rmdirs, func() {
        os.RemoveAll(dir)    // NOTE: 错误,dir 持有的值是遍历的最后一个值
    })
}

正确写法:

var rmdirs []func()
for _, d := range tempDirs() {
    dir := d      // NOTE: 一定要有这一句
    os.MkdirAll(dir, 0755) // creates parent directories too
    rmdirs = append(rmdirs, func() {
        os.RemoveAll(dir)
    })
}
// ...do some work…
for _, rmdir := range rmdirs {
    rmdir() // clean up
}

 

The problem of iteration variable capture is most often encountered when using the go statement or with defer since both may delay the execution of a function value until after the loop has finished. But the problem is not inherent to go or defer. (这不是go或defer本身导致的,而是因为它们都会等待循环结束后,再执行函数值。)

 

posted @ 2020-10-08 00:53  neozheng  阅读(213)  评论(0编辑  收藏  举报