猜猜会输出什么?
如果有大佬答对了求解释,非常感谢!
package main
import(
"fmt"
"encoding/json"
)
type a []int
func main(){
b := &a{0}
fmt.Printf("%v\n",*b)
b.Scan()
fmt.Printf("%v\n",*b)
b.Scan2()
fmt.Printf("%v\n",*b)
}
func (i *a) Scan(){
i = &a{1}
}
func (i *a) Scan2(){
json.Unmarshal([]byte{'[','2',']'},i)
}
1
f4nyc 2019-10-10 22:39:45 +08:00 via iPhone 1
golang 只有值传递,指针在这里也无关紧要。
重点是你要搞清楚 map slice chan 在内存中存储的方式。 你用 gdb 单步看看 b 的地址就明白了。 |
2
heimeil 2019-10-10 22:40:07 +08:00 2
Scan: 指针也是值类型,改变的只是当前作用域`i`的存的指针值,不是改的`i`指针指向的内存
Scan2: `json.Unmarshal`里面实际是解引用改变原地址的值,等同于`*i = a{2}` |
3
qq316107934 OP |
4
f4nyc 2019-10-10 22:53:08 +08:00 via iPhone
@heimeil 我认为你这是误导。和指针没有关系,是 slice 在内存中的存储方式导致的。去掉所有的&和*这段代码还是一样的结果。但把[]int 换成 struct 马上就能得到所谓的预期输出。
|
6
mornlight 2019-10-11 00:08:13 +08:00 via iPhone 1
@f4nyc 其实楼主没讲清楚他的问题,我估计是说为啥两个 Scan 一个不能改变入参另一个不能改变,2 楼讲的内容应该更能回应楼主的疑惑。核心就在于 i = &a{1} 这个地方 i 本身被重新赋值,这个赋值不影响它指向的那块内存内容。
slice 是一种特殊的 struct,传参的场景可以当 struct 一样理解。 |
8
liulaomo 2019-10-11 06:06:27 +08:00
虽然我非常抵触使用引用来描述一个值这种说法(因为常常引起误解),
这里为了和大家保持一致,暂时还是使用此说法。 当修改一个指针参数所指的值的时候,此指针可以被看做是一个引用值。 但是当此指针参数本身被修改的时候,此此指针应该被看做是一个非引用值。 简单说来,在一个函数内部对一个形参本身进行的任何修改都不会体现到相应传递的实参上。 因为此形参只不过是相应实参的一个副本。 |
9
Leigg 2019-10-11 09:03:02 +08:00 via Android
一楼没说到点子上,二楼讲对了
|