更改函数内指针参数的值
Change value of pointered argument inside a function
我被卡在了 seems/should 在 Go 中很容易的事情上。
我写了一个小的 go playground 来更容易地解释我的问题 => https://play.golang.org/p/Sm0SzrvEZS_o
package main
import (
"github.com/sirupsen/logrus"
)
type toto struct {
name string
}
func transform (data ...interface{}) {
logrus.Info("data before ", data)
data[0] = "tutu"
logrus.Info("data after ", data)
}
func main() {
var titi toto
logrus.Info("titi before ", titi) // -> empty
transform(&titi)
logrus.Info("titi after ", titi) // -> should have a name but don't
}
目标是将结构传递给函数,在其中进行修改并继续在调用函数中使用它。可悲的是,参数在子函数内部被修改,但没有移动到调用者中。
我是这门语言的初学者,也许我只是漏掉了什么地方...非常感谢您的帮助
听起来你想要一个指针。
在您的示例中,您使用了一个 interface{}
数组,这有什么特别的原因吗?一般来说,你应该在 Go 中明确你的类型,特别是因为你正在处理一个简单的结构。
package main
import (
"log"
)
type toto struct {
Name string
}
// to help with printing
func (t *toto) String() string {
return t.Name
}
// transform takes an array of pointers to the toto struct
func transform(totos ...*toto) {
log.Printf("totos before: %v", totos)
// unsafe array access!
totos[0].Name = "tutu"
log.Printf("totos after: %v", totos)
}
func main() {
// variables in Go are usually defined like this
titi := toto{}
transform(&titi)
}
这似乎可以做到:
package main
type toto struct { name string }
func transform (data ...interface{}) {
t := data[0].(*toto)
t.name = "tutu"
}
func main() {
var titi toto
transform(&titi)
println(titi.name == "tutu")
}
在 Go 中,在函数中作为参数传递的变量实际上是变量的副本,而不是实际变量本身。如果要修改传入的变量,需要将其作为指针传入。
就个人而言,每当我创建接受结构的函数时,我都会将函数设置为接受指向该结构实例的指针。这具有提高内存效率的好处(因为我的程序不必在每次调用函数时都创建变量的副本)并且它允许我修改我传递的结构的实例。
我会这样做:
package main
import (
"github.com/sirupsen/logrus"
)
type toto struct {
name string
}
func transform (t *toto) {
logrus.Info("t before: ", t)
// since t is a pointer to a toto struct,
// I can directly assign "tutu" to the "name" field
// using the "dot" operator
t.name = "tutu"
logrus.Info("t after: ", t)
}
func main() {
// init a pointer to a toto instance
titi := &toto{}
logrus.Info("titi before: ", titi) // -> empty
// this works because transform() accepts a pointer
// to a toto struct and and titi is a pointer to a toto instance
transform(titi)
logrus.Info("titi after (as a pointer): ", titi) // -> not empty
logrus.Info("titi after (as a value): ", *titi) // -> also not empty
}
我被卡在了 seems/should 在 Go 中很容易的事情上。
我写了一个小的 go playground 来更容易地解释我的问题 => https://play.golang.org/p/Sm0SzrvEZS_o
package main
import (
"github.com/sirupsen/logrus"
)
type toto struct {
name string
}
func transform (data ...interface{}) {
logrus.Info("data before ", data)
data[0] = "tutu"
logrus.Info("data after ", data)
}
func main() {
var titi toto
logrus.Info("titi before ", titi) // -> empty
transform(&titi)
logrus.Info("titi after ", titi) // -> should have a name but don't
}
目标是将结构传递给函数,在其中进行修改并继续在调用函数中使用它。可悲的是,参数在子函数内部被修改,但没有移动到调用者中。
我是这门语言的初学者,也许我只是漏掉了什么地方...非常感谢您的帮助
听起来你想要一个指针。
在您的示例中,您使用了一个 interface{}
数组,这有什么特别的原因吗?一般来说,你应该在 Go 中明确你的类型,特别是因为你正在处理一个简单的结构。
package main
import (
"log"
)
type toto struct {
Name string
}
// to help with printing
func (t *toto) String() string {
return t.Name
}
// transform takes an array of pointers to the toto struct
func transform(totos ...*toto) {
log.Printf("totos before: %v", totos)
// unsafe array access!
totos[0].Name = "tutu"
log.Printf("totos after: %v", totos)
}
func main() {
// variables in Go are usually defined like this
titi := toto{}
transform(&titi)
}
这似乎可以做到:
package main
type toto struct { name string }
func transform (data ...interface{}) {
t := data[0].(*toto)
t.name = "tutu"
}
func main() {
var titi toto
transform(&titi)
println(titi.name == "tutu")
}
在 Go 中,在函数中作为参数传递的变量实际上是变量的副本,而不是实际变量本身。如果要修改传入的变量,需要将其作为指针传入。
就个人而言,每当我创建接受结构的函数时,我都会将函数设置为接受指向该结构实例的指针。这具有提高内存效率的好处(因为我的程序不必在每次调用函数时都创建变量的副本)并且它允许我修改我传递的结构的实例。
我会这样做:
package main
import (
"github.com/sirupsen/logrus"
)
type toto struct {
name string
}
func transform (t *toto) {
logrus.Info("t before: ", t)
// since t is a pointer to a toto struct,
// I can directly assign "tutu" to the "name" field
// using the "dot" operator
t.name = "tutu"
logrus.Info("t after: ", t)
}
func main() {
// init a pointer to a toto instance
titi := &toto{}
logrus.Info("titi before: ", titi) // -> empty
// this works because transform() accepts a pointer
// to a toto struct and and titi is a pointer to a toto instance
transform(titi)
logrus.Info("titi after (as a pointer): ", titi) // -> not empty
logrus.Info("titi after (as a value): ", *titi) // -> also not empty
}