请教一个 Go 的小白问题
( A ) func DoSomething(a *A) {
b = a
}
( B ) func DoSomething(a A) {
b = &a
}
这两个函数调用的区别具体是什么呢
1
xidaduo 2022-01-12 15:32:37 +08:00
A:引用传递
B:值传递 |
2
wunonglin 2022-01-12 15:47:03 +08:00
A:传进来的是那个结构体的内存地址(吧?)
B:通俗来说传入的 a 是 new 了一个一个零值的结构体,然后在把你传的结构赋值上去。 |
3
hejw19970413 2022-01-12 16:23:34 +08:00
例如 a 现在的地址为 0x0000000001 值为 1
( A ) 函数中的 a 地址是 0x0000000002 但是 a 的值是 0x0000000001 ( B ) 函数中的 a 地址是 0x0000000003 但是 a 的值是 1 |
4
Arrowing 2022-01-12 16:53:04 +08:00
*A 是 A 的指针类型
|
5
labulaka521 2022-01-12 17:01:30 +08:00
在函数里面修改 b 的值 然后在此函数外面看看 a 的值是否也被改了
|
6
milk97 2022-01-12 17:30:34 +08:00
(A) 是 point receiver, https://go.dev/tour/methods/4
如果对 b 做修改,外面 a 指向的值也会变。 ( B )这样写意义不大。`b = &a` 中的 a 已经是调用时参数 a 的一个 copy ,再取它的指针没什么意义,因为修改了 b 不是影响到外面的 a 。 |
8
DeWjjj 2022-01-12 22:38:40 +08:00
...
一个传进来的东西是指针类型,一个是传值进来取地址然后给 b 。 这差异够大了吧,一个是标识符取地址,一个是指针本身。 &a = 0x02 &c =0x01 c = 1 *a = 1 a=0x01. 1.b = 0x01 = &c 2.b = &a = 0x02 |
9
DeWjjj 2022-01-12 22:52:30 +08:00
建议点说就是第一种你改*b 他能影响到外面。
第二种你只能改 b 他影响不到外面。 想要不改数据对外传递处理信息用第二种,想要处理信息顺手改外面传指针进去。 |
10
mx8Y3o5w3M70LC4y 2022-01-12 23:25:03 +08:00 via Android
要明白这个问题,先要了解引用数据类型,是怎么在内存中存储的。一个 T 类型的对象 t ,实际上需要开辟两种不同的内存空间来存储,t 在栈内存中,而对应的值是在堆内存中。*T 是指向堆内存地址的指针;而&t ,则是栈内存中 t 的地址。
|
11
voidmnwzp 2022-01-12 23:39:35 +08:00 via iPhone
c 语言没学过?
|
12
chenall 2022-01-13 04:08:58 +08:00 via Android
A 这个原始值后续可能会改变,需要同步变化时用。
后续 b=a B 干净调用,b 是 a 的副本,后续 a 和 b 没有交集。 |
13
xsen 2022-01-13 07:00:20 +08:00
A:指针传递,可修改其值
B:值传递,不可修改 对于 go 来说,若你想修改某个参数的值,就需要拿到其指针 |
14
xsen 2022-01-13 07:01:13 +08:00
与 c/c++中指针与值概念是一样的,只是用起来没有心理负担
|
15
darknoll 2022-01-13 09:45:03 +08:00
go 里面没有引用传参,都是值传递
|
17
NeoZephyr 2022-01-13 14:00:53 +08:00
B 属于脱裤子放屁了
|
18
meiyoumingzi6 2022-01-13 14:23:42 +08:00
0. 先解释 Golang 的值传递, 注意任何情况下都是值传递, 但是这个值可能是一个地址, 举个例子, 某东有卖螃蟹的, 但是很多是卖的螃蟹券, 我买了螃蟹券, 然后送了人, 那是不是可以说买了螃蟹送礼, 可以, 不过最终需要那个人自提而已
1. 有没有办法证明 Golang 是值传递, ```golang package main import "fmt" type demo struct{} func test(arg interface{}) { fmt.Printf("in func test %p\n", &arg) } func main() { d := demo{} fmt.Printf("out of test %p\n", &d) test(d) fmt.Printf("out of test %p\n", &d) test(&d) s := []int{1,2,} fmt.Printf("out of test %p\n", s) test(s) m := map[string]int{"1":1} fmt.Printf("out of test %p\n", m) test(m) } /* out of test 0x116ce80 in func test 0xc000010230 out of test 0x116ce80 in func test 0xc000010240 out of test 0xc0000160c0 in func test 0xc000010250 out of test 0xc000074180 in func test 0xc000010260 */ ``` 2. slice/map 是引用类型, 害, 你就把他当个螃蟹券 3. 题中两个区别 i). 开销不同, a 中值需要赋值一次地址, 开销很小, b 中需要复制一次结构体 ii). 虽然看起来效果一样, 但是 b 中的 a 跟已经跟外面的 a 不是一个东西了, 因为有一次拷贝, 完完全全就是两个东西 |
19
dany813 2022-01-13 14:31:21 +08:00
学习了
|
20
ixiaofeng 2022-01-13 14:43:25 +08:00
目测这个问题是在看完 the way to go 以后发现的吧
|
22
chtcrack 2022-01-13 15:51:08 +08:00
先学习*和&代表了啥.*是指针,&是取地址.学习 go 之前先去学一下 c 的指针那块内容,就不会被这个搞晕.
int var_runoob = 10; int *p; // 定义指针变量 p = &var_runoob;//取出 var_runoob 指向的地址赋值给 p printf("p 的值: %p\n", p); p 的值:0x7ffeeaae08d8 |
24
BryantBa OP 大佬们学习了,大学学 C 的时候就是指针谜,现在还是
|