先说结论:切片的数据结构在值传递中使得,如果你的改动修改了len, cap,或者是触发了内存的重新分配,改动是带不到外面的,因为是值传递
问题描述:有一个interface类型的变量,把一个struct赋值给了它,类似下面这样
package main
import "fmt"
type ResData struct {
Type string
Srcid string
SearchRes interface{}
}
type Data struct {
name []string
}
func main() {
data := Data{
name: []string{"a", "b"},
}
var res ResData
res.SearchRes = data
if d, ok := res.SearchRes.(Data); ok {
d.name = append(d.name[:1], d.name[2:]...)
//d.name[0] = "d"
fmt.Println(d.name)
//res.SearchRes = d
}
if d, ok := res.SearchRes.(Data); ok {
fmt.Println(d.name)
}
}
将res.SearchRes断言成Data后,使用append修改删除b,发现不生效
结论:golang都是值传递,断言成功后也是值传递,只不过二者的name字段中的Data(切片实现中的Data)指去了一个地方,毕竟这是一根指针,即使Data得到了修改,但是len并没有被修改,所以上面代码的结果是
[a]
[a b]
但是d.name[0] = “d”,这一行的改动是有效的,因为不涉及长度变化
修改方法:
- res.SearchRes = d 注释打开,但是会带来一次拷贝
- res.SearchRes = &data,同时断言成*Data,这样虽然是值传递,但是都指向了一个type Data struct,所以修改会通用,只要不发生内存的再次分配
参考:https://www.zhihu.com/question/533447409
https://blog.youkuaiyun.com/weixin_45963929/article/details/125874039