2013-07-31 62 views
4

我有兩個關於下面的代碼中的Go接口的問題。轉:接口方法調用

type Color interface { 
    getColor() string 
    setColor(string) 
} 

type Car struct { 
    color string 
} 
func (c Car) getColor() string { 
    return c.color 
} 
func (c Car) setColor(s string) { 
    c.color = s 
} 

func main() { 
    car := Car{"white"} 
    col := Color(car) 

    car = col.(Car)   // L(1) 
    car.setColor("yellow") 
    fmt.Println(col)  // L(2) 
    fmt.Println(car) 
    car.color = "black" 
    fmt.Println(col)  // L(3) 
    fmt.Println(car) 
} 

Q1:它是確定寫L(1) as "car, _ := col.(Car)"?

Q2:L(2)打印 「白」 不 「黃」。

爲什麼? L(3)似乎正確地打印「黑色」。

謝謝。

+1

'setColor'不會做你認爲它做的事。你應該讓'c'(接收器)一個*指針*給一輛車。 – MatrixFrog

回答

2

爲了使setColor對Car對象進行變異,您希望您必須傳遞一個指針,您的代碼通過Car傳遞值並更改該值的顏色,然後在方法的時候立即丟棄Car值的副本返回

Here is your example改變,使得該接口是由一個指針納到汽車

func (c *Car) getColor() string { 
    return c.color 
} 
func (c *Car) setColor(s string) { 
    c.color = s 
} 

上述輸出的鏈接:

&{yellow} 
&{yellow} 
&{black} 
&{black} 
8

Q1:

不,你不能說汽車,_:= col。(汽車)。原因並不明顯。這裏沒關係語句在L1列表:

car,ok := col.(Car) 
car = col.(Car) 
car,_ = col.(Car) 
_,ok := col.(Car) 

「:=」是報關/分配的縮寫形式,因爲汽車在該範圍內已宣佈,:=會給你一個錯誤(「沒有新的變量在= =「的左側)。把「ok」聲明爲一個新變量(「ok」),然而,下劃線/忽略僞變量不會被計算爲一個新的變量:=。

編輯:爲了清楚起見,您可以在此處放置「ok」或下劃線,因爲類型斷言返回類型斷言值和表示斷言是否成功的布爾值。如果問題其實是關於「_」一般情況下,而不是在一個問題「:=」操作符:沒有,在一般情況下,你不能這樣做

a,_ := 5 

由於該語句只返回一個價值,不會讓你忽略任何東西。 (你會得到錯誤:「分配計數不匹配2 = 1」)。

Q2:

在Go中,方法可以是在指針或值/基本類型。我相信你會發現以下將工作正常:

car.setColor("yellow") 
//... 
func (car Car) setColor(s string) { 
    car.color = s 
    fmt.Println(car.color) 
} 

在這段代碼中,它將正確打印「黃色」。這是因爲您通過傳遞方法接收器。事實上,它確實修改了汽車 - 但是與你通過的汽車不同的是,一輛汽車恰好是你稱之爲汽車的完美副本。爲了解決這個問題,你需要一個指針接收器,

func (car *Car) setColor(s string) { 
    car.color = s 
} 

這將使變化可見的電話後,因爲你給的方法,其中汽車所在,而不僅僅是它具有數據的位置。爲了徹底,有一些涉及「參考類型」(地圖,切片,頻道)的案例,您可以在非指針方法之外看到副作用,但這些都是規則的例外情況。

請注意,如果您將此方法指定爲指針接收器,則類型爲Car的變量不再實現接口Color。相反,實現接口的類型是* Car(指向Car的指針)。事實上,由於指針在Go中是透明的,所以即使將getColor與非指針接收器一起使用也是如此,但通常更好的形式是在指針或基類型上實現接口的類型上的所有方法,而不是兩者的混合。

因爲您似乎在學習,所以一個雜注:本身沒有錯,開始時setColor和getColor都帶有小寫字母。但是,請注意,這些方法將不在您正在編寫的即時包中提供。爲了讓他們可見,他們必須以大寫字母開頭。