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本身导致的,而是因为它们都会等待循环结束后,再执行函数值。)
Code your future.