2014-06-28 22 views
1

我一起去遊樂場玩,找到這個代碼:的Structs不能是零,但是這是編譯

package main 

import (
    "fmt" 
    "time" 
) 

type MyError struct { 
    When time.Time 
    What string 
} 

func (e *MyError) Error() string { 
    return fmt.Sprintf("at %v, %s", 
     e.When, e.What) 
} 

func run() error { 
    return &MyError{ 
     time.Now(), 
     "it didn't work", 
    } 
} 

func main() { 
    if err := run(); err != nil { 
     fmt.Println(err) 
    } 
} 

所以我在這裏可以看到,*MyError實現error接口。但是,如果我在error FUNC刪除&並返回MyError相反,我收到編譯時錯誤: prog.go:19: cannot use MyError literal (type MyError) as type error in return argument: MyError does not implement error (Error method has pointer receiver)。好吧,我能理解,所以我可以做的函數Error這樣,這將編譯並運行成功:

func (e MyError) Error() string { 
    return fmt.Sprintf("at %v, %s", 
     e.When, e.What) 
} 

func run() error { 
    return MyError{ 
     time.Now(), 
     "it didn't work", 
    } 
} 

然後我main FUNC看到,有檢查,如果errnil所以如果我正確它理解完全有可能在某些情況下返回nil。所以MyError結構可能取nil值。不過,如果我嘗試編譯如下:

import (
    "fmt" 
    "time" 
) 

type MyError struct { 
    When time.Time 
    What string 
} 

func (e MyError) Error() string { 
    return fmt.Sprintf("at %v, %s", 
     e.When, e.What) 
} 

func run() error { 
    return nil 
    return MyError{ 
     time.Now(), 
     "it didn't work", 
    } 
} 

func main() { 
    var err2 MyError = nil 

    fmt.Println(err2) 
    if err := run(); err != nil { 
     fmt.Println(err) 
    } 
} 

去編譯器說:prog.go:27: cannot use nil as type MyError in assignment [process exited with non-zero status]

爲什麼在大寫編譯成功,在這種情況下,編譯失敗? 是否有可能爲結構是nil(我想不會,但爲什麼run FUNC編譯?)

回答

6

在第一個例子,*MyError實施error接口。正如你所看到的,它是一個指針,並且指針可以具有nil的值。

var err *MyError 
err == nil // true 

var err *MyError = new(MyError) 
err == nil // false 

但是在第二示例中,它是MyError它實現了error接口,而不是指針任何更多。

var err MyError 
err == MyError{} // true 
&err == nil // false 
err == nil // Compilation error 

這是err這個時候ADRESS,可以是nil,不是變量本身。


作爲比較,考慮int類型:var i int。您可以檢查i == 0例如,但它是測試如果i == nil一個錯誤,因爲nil不是整數(正是因爲它不是一個MyError之前)。但是您仍然可以檢查i的地址是否爲nil&i == nil


編輯

注意,這個功能將總是返回nil(執行停止第一return後右):

func run() error { 
    return nil 
    return MyError{ 
     time.Now(), 
     "it didn't work", 
    } 
} 

它編譯,因爲函數的原型告訴它必須返回error,實際上,nil是有效的error,因此是MyError{} variab樂。但嘗試這個函數的變化這一個:

func run() MyError 

您將看到編譯失敗,因爲nil不是MyError變量,即使它是爲error類型的有效值。

+0

我明白這一點,但看看'run' func。它返回MyError,但也可以返回零。 – Marii

+0

我會盡力在我的下一個編輯中更好地解釋;) – julienc

+0

啊哈,現在有道理。謝謝。 :) – Marii

2

nil接口與包含nil值的接口不同。

在你的問題中,你已經看到一個接口(在你的情況下,內置的錯誤接口)可以爲零,並得出一個不正確的結論,即每個可以實現該接口的類型也可以爲零。

相關問題