下面一段普通代码, 我们希望scan方法替换掉原始数据:
package main
import(
"fmt"
"encoding/json"
)
type a []int
func main(){
b := &a{0}
b.Scan()
fmt.Printf("%v\n",*b)
b.Scan2()
fmt.Printf("%v\n",*b)
}
func (i *a) Scan(){
fmt.Printf("%p\n", i)
i = &a{1}
fmt.Printf("%p\n", i)
}
func (i *a) Scan2(){
fmt.Printf("%p\n", i)
json.Unmarshal([]byte{'[','2',']'},i)
fmt.Printf("%p\n", i)
}
我们最得到的结果是:
[0]
0xc0000b4000
0xc0000b4040
[0]
0xc0000b4000
0xc0000b4000
[2]
出乎预料的结果,为什么会这样呢?
go语言内的参数传递都是值传递, 为什么叫
*x
为引用传递呢, 其实*x
作为参数的时候只是传递一个指向原始数据的副本(即形参不代表数据本身,而是一个指向数据的变量).
所以 当试图修改形参
本身的时候,其实是影响的形参自身数据,不会影响其指向的数据.
拿别人回答答案总结:
当修改一个指针参数所指的值的时候,此指针可以被看做是一个引用值。
但是当此指针参数本身被修改的时候,此此指针应该被看做是一个非引用值。
简单说来,在一个函数内部对一个形参本身进行的任何修改都不会体现到相应传递的实参上。
因为此形参只不过是相应实参的一个副本。
所以如果要用函数scan
修改数据就需要使用 *i = a{1}
来表达, 即: 修改 i
指向的数据为a{1}
.
在实际项目的时候一定要注意这个问题!!!