替换接口的值

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

Replace value of interface

问题

我想要替换一个接口的值,像这样:

package main
import "fmt"

type Fooer interface {Foo(string)}

type Foo struct {foo string}

func (f *Foo) Foo(bar string) {f.foo = bar}

var z = &Foo{foo : "new"}

func swap(fooer Fooer) {fooer = z}

func main() {
    f :=  &Foo{foo: "old"}
    fmt.Printf("%s (want &{old})\n", f)
    swap(f)
    fmt.Printf("%s (want &{new})", f)
}

但是我得到的结果是:

&{old}
&{old}

我尝试了各种调用(fooer *= z*fooer = *z,..),但是我似乎无法弄对。

你可以在 play.golang 上尝试这个例子:http://play.golang.org/p/EZEh3X8yHC


好的,我认为可以这样实现:

func swap(fooer Fooer) {
    foo, _ := fooer.(*Foo)
    *foo = *z
}
英文:

I want to replace an interface's value like this:

package main
import "fmt"

type Fooer interface {Foo(string)}

type Foo struct {foo string}

func (f *Foo) Foo(bar string) {f.foo = bar}

var z = &Foo{foo : "new"}

func swap(fooer Fooer) {fooer = z}

func main() {
	f :=  &Foo{foo: "old"}
	fmt.Printf("%s (want &{old})\n", f)
	swap(f)
	fmt.Printf("%s (want &{new})", f)
}

But i get:

&{old}
&{old}

I tried around with various calls (fooer *= z, *fooer = *z, ..) but I cant seem to get it right.

You can try this example at play.golang: http://play.golang.org/p/EZEh3X8yHC


Okay, I think it works like this:

func swap(fooer Fooer) {
    foo, _ := fooer.(*Foo)
	*foo = *z
}

答案1

得分: 10

与Go语言中的大多数内容一样,接口(interface)只是值。在函数内部分配一个新值并不会改变复制到函数参数中的值。

因为你想要替换接口值,所以你需要一个指向该值的指针,就像你对其他值一样。使用指向接口的指针是非常罕见的情况:http://play.golang.org/p/EZEh3X8yHC

func swap(fooer *Fooer) {
    z := Fooer(&Foo{foo: "new"})
    *fooer = z
}

func main() {
    var f Fooer = &Foo{foo: "old"}
    fmt.Printf("%s (want &{old})\n", f)
    swap(&f)
    fmt.Printf("%s (want &{new})", f)
}

但是,由于指向接口的指针几乎总是一个错误(你可以看到我们必须非常明确地使其工作),你应该真的有一个很好的理由以这种方式实现,并且要对其进行良好的文档记录。

你最有可能想要的是从接口中提取指针,并在其中分配一个新值(这是你在问题末尾添加的内容)。这是一个更好的构造,但类型必须匹配,所以接口是不需要的。

英文:

Like most things in Go, interfaces are simply values. Assigning a new value within a function isn't going to change the value copied into the function arguments.

Because you want to replace the interface value, you need a pointer to the value just like you would any other. It's a very rare case where you could use a pointer to an interface: http://play.golang.org/p/EZEh3X8yHC

func swap(fooer *Fooer) {
	z := Fooer(&Foo{foo: "new"})
	*fooer = z
}

func main() {
	var f Fooer = &Foo{foo: "old"}
	fmt.Printf("%s (want &{old})\n", f)
	swap(&f)
	fmt.Printf("%s (want &{new})", f)
}

But, since a pointer to an interface is almost always a mistake (you can see we have to be very explicit to make this work), you should really have a good reason for implementing something this way, and document it well.

What you most likely want is to extract the pointer from the interface, and assign a new value in there (which is what you added to end of your question). This is a much better construct, but the type must match, so the interface isn't needed.

huangapple
  • 本文由 发表于 2016年1月16日 02:09:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/34817188.html
匿名

发表评论

匿名网友

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

确定