对结构类型使用setter不能按预期工作 [英] Using a setter for a struct type does not work as anticipated

查看:51
本文介绍了对结构类型使用setter不能按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为结构使用setter函数,但未按预期工作:

 package main

import "fmt"

type T struct { Val string }

// this setter seems not to work
func (t T) SetVal( s string ) {
        t.Val = s
}

// this setter, using ptr to T, seems to work ok
func (t *T) SetVal2( s string ) {
        (*t).Val = s
}

func main() {
        v := T{"abc"}
        fmt.Println( v )        // prints {abc}
        v.SetVal("pdq")
        fmt.Println( v )        // prints {abc}, was expecting {pdq}!
        v.SetVal2("xyz")
        fmt.Println( v )        // prints {xyz}!
}
 

我缺少一些基本的知识-为什么SetVal无法正常工作?

该行为类似于reflect中的设置值,只有在提供了指向对象的指针(相对于对象本身)时,该行为才起作用

解决方案

以下是您所缺少的基本知识:当将结构体作为指针传递给函数时,该函数可以修改原始结构体,因为它具有一个指向它的指针.但是,当通过其值将结构传递给函数时,实际上仅是针对该函数调用创建该结构的NEW副本,并且对该结构新副本的任何修改都不会影响原始结构.

您可以通过打印出有问题的结构的实际地址来证明这是它的工作方式:

package main

import "fmt"

type T struct { Val string }

func (t T) SetVal( s string ) {
        fmt.Printf("Address of copy is %p\n", &t);
}

func (t *T) SetVal2( s string ) {
        fmt.Printf("Pointer argument is %p\n", t);
}

func main() {
        v := T{"abc"}
        fmt.Printf("Address of v is %p\n", &v);
        v.SetVal("pdq")
        v.SetVal2("xyz")
}

当我在Go操场上运行它时,上面的代码将产生以下输出:

Address of v is 0xf840001290
Address of copy is 0xf8400013e0
Pointer argument is 0xf840001290

注意打印出来的第一个和第三个指针是相等的,这意味着它们是相同的结构.但是第二个指针是不同的,因为它是一个副本.

顺便说一下,这似乎与C的结构/函数参数完全相同.

Using a setter function for a struct, but not working as anticipated:

package main

import "fmt"

type T struct { Val string }

// this setter seems not to work
func (t T) SetVal( s string ) {
        t.Val = s
}

// this setter, using ptr to T, seems to work ok
func (t *T) SetVal2( s string ) {
        (*t).Val = s
}

func main() {
        v := T{"abc"}
        fmt.Println( v )        // prints {abc}
        v.SetVal("pdq")
        fmt.Println( v )        // prints {abc}, was expecting {pdq}!
        v.SetVal2("xyz")
        fmt.Println( v )        // prints {xyz}!
}

I am missing some fundamental understanding - why doesn't SetVal work?

the behavior is similar to setting values in reflect which only works if provided a pointer to the object as versus the object itself

解决方案

Here is the fundamental understanding you are missing: when a struct is passed in to a function as a pointer, the function can modify the original struct because it has a pointer to it. However, when a struct is passed in to a function via its value, then a NEW copy of the struct is actually created just for that function call, and any modifications to this new copy of the struct will not affect the original struct.

You can prove that this is the way it works by printing out the actual addresses of the structs in question:

package main

import "fmt"

type T struct { Val string }

func (t T) SetVal( s string ) {
        fmt.Printf("Address of copy is %p\n", &t);
}

func (t *T) SetVal2( s string ) {
        fmt.Printf("Pointer argument is %p\n", t);
}

func main() {
        v := T{"abc"}
        fmt.Printf("Address of v is %p\n", &v);
        v.SetVal("pdq")
        v.SetVal2("xyz")
}

The code above results in this output when I run it in the Go playground:

Address of v is 0xf840001290
Address of copy is 0xf8400013e0
Pointer argument is 0xf840001290

Notice how the first and third pointer printed out are equal, which means they are the same struct. But the second pointer is different because it is a copy.

This seems to be exactly the same way that C structs / function parameters work, by the way.

这篇关于对结构类型使用setter不能按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆