为了账号安全,请及时绑定邮箱和手机立即绑定

前进:使用指针可以更改结构的内容。为什么?

前进:使用指针可以更改结构的内容。为什么?

Go
DIEA 2021-05-07 14:53:34
考虑以下示例。我不完全了解“后台”会发生什么,并寻求解释。从主函数Foo调用时,此版本似乎复制了该结构AddToEntry。正确的?如何在代码中“证明”这一点?当go复制该结构时,我只是在操纵该结构的副本,当我返回该main函数时,是否像以前一样看到原始文件?当我希望有一个指针(请参见代码中的注释)时,一切都很好,没有复制我的结构。如何避免这种“错误”?如何确定不复制该结构?是否有可能对此进行编译时/运行时检查,或者我要小心吗?package mainimport (    "fmt")type Foo struct {    Entry []string}func MakeFoo() Foo {    a:=Foo{}    a.Entry = append(a.Entry,"first")    return a}// if I change (f Foo) to (f *Foo), I get // the "desired" resultfunc (f Foo) AddToEntry() {    f.Entry = append(f.Entry,"second")}func main() {    f:=MakeFoo()    fmt.Println(f) // {[first]}    f.AddToEntry()    fmt.Println(f) // {[first]}}
查看完整描述

2 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

您的方法签名为func (f Foo) AddToEntry()。方法的工作方式与以下方式f.AddToEntry()相同:

g := Foo.AddToEntry
g(f)

接收器只是另一个参数。为什么这很重要?当您传递结构并在函数中对其进行修改时会发生什么?在C,Go和其他按值传递语言中,参数中给出的结构仅是副本。因此,您不能修改原始文件。只返回新的结构。

定义时func (f *Foo) AddToEntry(),您正在将接收器(第一个参数)定义为指针。显然,给定一个指针,您可以修改原始结构。隐藏的是您在Go中访问结构时隐式引用。换句话说,(*ptrFoo).EntryptrFoo.EntryGo中的相同。

因此,这里的问题是,对于那些不习惯的人,语法隐藏了一些正在发生的事情。在C语言中,除非传递了指向结构的指针,否则您将永远无法编辑该结构。Go中也会发生同样的情况。您需要使用指针接收器才能修改接收的内容。


查看完整回答
反对 回复 2021-05-17
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

如何确定不复制该结构?是否有可能对此进行编译时/运行时检查,或者我要小心吗?

简短的答案是,,您不能为此进行编译时或运行时(1)检查-您只需要小心。一旦您对go有了一些熟悉,这便成为自然。

(1) 从技术上讲,您的函数可以使用类型开关查询类型是否为指针,但是如果您记得这样做,则还记得将参数设置为指针。


查看完整回答
反对 回复 2021-05-17
?
交互式爱情

TA贡献1712条经验 获得超3个赞

查看完整回答
反对 回复 2021-05-17
  • 2 回答
  • 0 关注
  • 239 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信