通过Go中的接口修改结构成员

huangapple go评论83阅读模式
英文:

Modifying struct members through an interface in Go

问题

我在我的Go项目中遇到了一个问题,我想创建一个基类的多个子类,并且能够通过基类/接口变量操作子类的实例(尽管Go中并不存在“类”这个概念)。

为了说明我的意思,这是一个C++的示例代码:

#include

using namespace std;

class Base {
public:
int x,y;
virtual void DoStuff() {};
};

class Thing : public Base {
public:
void DoStuff() { x = 55; y = 99; }
};

Base *gSomething;

int main(int argc, char **argv) {
gSomething = new Thing();
gSomething->DoStuff();

cout << "gSomething = {" << gSomething->x << ", " << gSomething->y << "}" << endl;

return 0;

}

这段代码会输出“gSomething = {55, 99}”。

作为一个对Go不熟悉的人,我希望能够做到类似这样的事情(我觉得这样做相当简洁):

package main

import "fmt"

type IBase interface {
DoStuff()
}

// 基类
type Base struct {
x, y int
}

// 更具体的变体
type Thing struct {
Base
}

func (o Base) DoStuff() {
// 用于满足IBase的存根
}

func (o Thing) DoStuff() {
o.x, o.y = 55, 99
fmt.Println("In Thing.DoStuff, o =", o)
}

var Something IBase

func main() {
Something = new (Thing)

Something.DoStuff()
fmt.Println("Something =", Something)

}

然而,这并不起作用。它可以编译,看起来运行正常,但我没有得到我想要的结果。这是输出结果:

In Thing.DoStuff, o = {{55 99}}
Something = &{{0 0}}

我显然希望最后一行输出为“Something = &{{55 99}}”。

我在设计上完全错了吗(在Go中无法实现这个功能),还是我只是错过了一些细节?

英文:

I've come to a point in a Go project of mine where I'd like to create multiple subclasses of a base class, and be able to operate on instances of the subclasses through a base class/interface variable (I'm using the word "class" even though the concept doesn't really exist in Go).

Here's what it might look like in C++ just to show what I mean:

#include &lt;iostream&gt;

using namespace std;

class Base {
public:
    int x,y;
    virtual void DoStuff() {};
};

class Thing : public Base {
public:
    void DoStuff() { x = 55; y = 99; }
};


Base *gSomething;

int main(int argc, char **argv) {
    gSomething = new Thing();
    gSomething-&gt;DoStuff();

    cout &lt;&lt; &quot;gSomething = {&quot; &lt;&lt; gSomething-&gt;x &lt;&lt; &quot;, &quot; &lt;&lt; gSomething-&gt;y &lt;&lt; &quot;}&quot; &lt;&lt; endl;

    return 0;
}

This would print "gSomething = {55, 99}".
Being new to Go I was hoping I could do something like this (which I felt was fairly clean):

package main

import &quot;fmt&quot;

type IBase interface {
    DoStuff()
}

// The base &quot;class&quot;
type Base struct {
    x, y int
}

// A more specific variant of Base
type Thing struct {
    Base
}


func (o Base) DoStuff() {
    // Stub to satisfy IBase
}

func (o Thing) DoStuff() {
    o.x, o.y = 55, 99
    fmt.Println(&quot;In Thing.DoStuff, o = &quot;, o)
}

var Something IBase

func main() {
     Something = new (Thing)

    Something.DoStuff()
    fmt.Println(&quot;Something = &quot;, Something)
}

Alas, this doesn't work. It compiles, it appears to run properly, but I don't get the result I wanted. Here's the printout:

In Thing.DoStuff, o = {{55 99}}
Something = &{{0 0}}

I was obviously hoping for the last print to say "Something = &{{55 99}}"

Am I completely off on the design here (is this not possible to do in Go), or have I just missed some small detail?

答案1

得分: 5

你的 func (o Thing) DoStuff() 有一个接收者类型为 Thing struct 的接收者,并且在 Go 中结构体是按值传递的。如果你想修改结构体本身(而不是它的副本),你需要通过引用传递它。将这一行改为 func (o *Thing) DoStuff(),你应该能看到预期的输出。

英文:

Your func (o Thing) DoStuff() has a receiver of the type Thing struct and structs are passed by value in Go. If you want to modify the struct (and not a copy of it), you would have to pass it by reference. Change this line to func (o *Thing) DoStuff() and you should see the expected output.

huangapple
  • 本文由 发表于 2012年7月14日 04:04:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/11477577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定