替换接口的值

mac*_*ete 1 pointers go

我想替换一个接口的值,如下所示:

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)
}
Run Code Online (Sandbox Code Playgroud)

但我得到:

&{old}
&{old}
Run Code Online (Sandbox Code Playgroud)

我尝试了各种各样的电话(fooer *= z,*fooer = *z...),但我似乎无法把它弄好.

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


好的,我认为它的工作原理如下:

func swap(fooer Fooer) {
    foo, _ := fooer.(*Foo)
    *foo = *z
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*imB 7

像Go中的大多数东西一样,接口只是值.在函数中分配新值不会更改复制到函数参数中的值.

因为要替换接口值,所以需要一个指向该值的指针,就像使用其他任何值一样.这是一个非常罕见的情况,您可以使用指向界面的指针: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)
}
Run Code Online (Sandbox Code Playgroud)

但是,因为一个指向接口几乎总是错误的(你可以看到,我们必须非常明确,使这项工作),你应该真的有一个很好的理由实现的东西这种方式,并记录它做好.

你最想要的是从界面中提取指针,并在那里指定一个新值(这是你在问题的末尾添加的).这是一个更好的构造,但类型必须匹配,因此不需要接口.

  • 好吧,那么还有一个问题,“json.Encode(interface{})”或“gob.Encode(interface{})”使用接口作为参数但仍然能够以某种方式写入值是如何工作的 (2认同)
  • @machete:那些使用反射和类型断言,您必须传入要分配的指针。你仍然不能改变接口的动态类型,即如果你传入一个`*string`,你不能用`*int` 替换它。通过反射的类似功能:http://play.golang.org/p/u_lBBPeRfz (2认同)