我通过引用将结构传递给函数。
我期待如果我在函数中定义和更改结构,我可以在外面获得新值。
但它没有发生。
任何人都可以解释原因吗?
package main
import "fmt"
func intbyRef(i *int) {
*i = 10
}
type ttt struct {
a int
}
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
t = &p
}
func main() {
i := 1
var t *ttt
fmt.Println(i)
fmt.Println(t)
change(t)
intbyRef(&i)
fmt.Println(i)
fmt.Println(t)
}
您可以在此处试用代码:https://play.golang.org/p/I-GIdIZ9c6
答案 0 :(得分:1)
您不是在更改函数内部的结构,而是通过将其设置为不同的内存地址来更改该值。换句话说,您没有更改t
引用的地址中存储的对象,您正在更改t
本身的指针值,这不会更改指针值函数外的t
变量(因为Golang是按值传递的)。
为了做你想做的事,代码应该与你为intbyRef
做的类似,即:
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
*t = p
}
然而,这会因为nil-pointer dereference而引起恐慌。你的主要功能也应该用int:
做你正在做的事情func main() {
i := 1
// var t *ttt
t := new(ttt)
...
}
下面的完整代码(游乐场链接here):
package main
import "fmt"
func intbyRef(i *int) {
*i = 10
}
type ttt struct {
a int
}
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
// t = &p
*t = p
}
func main() {
i := 1
// var t *ttt
t := new(ttt)
fmt.Println(i)
fmt.Println(t)
change(t)
intbyRef(&i)
fmt.Println(i)
fmt.Println(t)
}
此外,您可能希望防范nil值并返回错误,尤其是对于包内部的函数。
答案 1 :(得分:0)
在我们的代码中,您在函数更改中创建ttt的新对象并将其赋值给t,该函数作为参数传递给函数。在go中,参数是按值传递的,因此在函数更改结束时,将值赋值给t仅适用于函数的范围。为了将更改传播到调用函数返回值,并将其更改回来。
对代码进行了更改,请查看播放地点链接 https://play.golang.org/p/S3GK0JLDHn
答案 2 :(得分:0)
您正在将已初始化指针值传递给intByRef
并更改已取消引用的值。
在change
中,您传递的不是初始化的指针值(也就是nil)并为其分配另一个指针。
所以你做了两件事。
您应该知道,当您将指针传递给函数时,您会传递该指针的副本(指向相同的值)。这就是为什么main
t
在将其传递给change
后未发生变化的原因。它指向" old"记忆地址。
如果要更改传递给函数的ttt
指针的值,可以像intByRef
中那样执行,但指针必须初始化(又名。分配)。否则你会尝试取消引用nil。
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
*t = p
}
func main() {
t := new(ttt)
fmt.Println(t)
change(t)
fmt.Println(t)
}