2016-01-15 52 views
1

的價值我想這樣的替換界面的價值:更換接口

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 
} 
+0

你的編輯可能更像你想要的,但是接口沒有意義,因爲你只能指定完全相同的類型。 – JimB

+0

yup絕對正確:D – machete

+0

[在Golang中將接口設置爲零]可能的副本(http://stackoverflow.com/questions/33841630/set-an-interface-to-nil-in-golang) – icza

回答

6

像圍棋大多數事情一樣,界面是簡單的值。在函數中分配新值不會改變複製到函數參數中的值。

因爲您想要替換接口值,您需要一個指向該值的指針,就像其他值一樣。這是一個非常罕見的情況下,你可以使用一個指向接口: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) 
} 

但是,因爲一個指向接口幾乎總是錯誤的(你可以看到,我們必須非常明確,使這項工作),你應該真的有一個很好的理由實現這樣的事情,並記錄下來。

你最可能想要的是從接口中提取指針,並在那裏分配一個新值(這是你添加到你的問題結束)。這是一個更好的構造,但類型必須匹配,所以不需要接口。

+0

Ah'var f Fooer =',當然。謝謝:) – machete

+0

還有一個問題,它是如何工作的:'json.Encode(interface {})'或'gob.Encode(interface {})'使用接口作爲參數,但仍然能夠以某種方式寫入值 – machete

+1

@machete:那些使用反射和類型斷言,你必須傳入一個指針來分配。你仍然不能改變接口的動態類型,也就是說,如果你傳入一個'* string',你不能用'* int'替換它。通過反射類似的功能:http://play.golang.org/p/u_lBBPeRfz – JimB