我想将一段字符串转换成一段指向字符串的指针
values1 := []string{"a", "b", "c"}
var values2 []*string
for _, v := range values1 {
fmt.Printf("%p | %T\n", v, v)
values2 = append(values2, &v)
}
fmt.Println(values2)
%!p(string=a) => string
%!p(string=b) => string
%!p(string=c) => string
[0xc42000e1d0 0xc42000e1d0 0xc42000e1d0]
据我了解,
我的变量 v
似乎是一个字符串,而不是指向字符串的指针。
因此 v
应该在迭代时从 values1
复制。
显然我错了,因为 v
仍然有相同的地址 0xc42000e1d0
。
如果不是指针,v
值如何改变?
要获得快速解决方案,请使用:
values1 := []string{"a", "b", "c"}
var values2 []*string
for i, _ := range values1 {
values2 = append(values2, &values1[i])
}
最佳答案
第一个版本不起作用,因为只有一个循环变量 v
,它在每次迭代中都有相同的地址。循环变量在每次迭代中分配,这会改变它的值而不是它的地址,并且您在每次迭代中附加这个相同的地址。
一个可能的解决方案是您提出的:附加原始 slice 的正确 slice 元素的地址:
for i := range values1 {
values2 = append(values2, &values1[i])
}
这可行,但请注意 values2
包含指向 values1
的后备数组的地址,因此 values1
的后备数组将被保留在内存中(不会被垃圾收集),直到 values1
和 values2
变量都无法访问。另请注意,修改 values1
的元素将间接影响 values2
,因为 values2
的元素指向 values1
的元素。
另一种解决方案是创建临时局部变量并附加这些变量的地址:
for _, v := range values1 {
v2 := v
values2 = append(values2, &v2)
}
通过这样做,您的 values2
slice 将不会阻止 values1
被垃圾收集,而且修改 values1
中的值也不会反射(reflect)在values2
,它们将是独立的。
查看循环变量的相关问题:
Why do these two for loop variations give me different behavior?
Golang: Register multiple routes using range for loop slices/map
关于string - 将字符串 slice 转换为指向字符串的指针 slice ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48459846/