2013-03-11 78 views
6

我有一個函數返回Card,這是一個struct類型或錯誤。在go中,返回結構或錯誤的慣用方法是什麼?

問題是,如何在發生錯誤時從函數返回? nil對結構無效,我的Card類型沒有有效的零值。

func canFail() (card Card, err error) { 
    // return nil, errors.New("Not yet implemented"); // Fails 
    return Card{Ace, Spades}, errors.New("not yet implemented"); // Works, but very ugly 
} 

我發現的唯一的解決方法是使用一個*Card而非Card,一個讓它無論是nil當有錯誤或它指向一個實際的Card時沒有錯誤發生,但是這是相當笨拙。

func canFail() (card *Card, err error) { 
    return nil, errors.New("not yet implemented"); 
} 

有沒有更好的方法?

編輯:我找到了另一種方式,但不知道這是慣用的甚至是好的風格。

func canFail() (card Card, err error) { 
    return card, errors.New("not yet implemented") 
} 

由於card是一個命名的返回值,我可以使用它沒有對其進行初始化。它以自己的方式歸零,我並不在乎,因爲調用函數不應該使用這個值。

回答

10
func canFail() (card Card, err error) { 
    return card, errors.New("not yet implemented") 
} 

我想這一點,你的第三個exampe,是沒關係。理解的規則是當函數返回錯誤時,除非文檔另有明確說明,否則不能依賴其他返回值來獲得有意義的值。所以在這裏返回一個可能沒有意義的結構值是很好的。

+2

返回一個指針非常地道,所以你可以使用nil。它有助於避免錯誤,並且在不使用命名的返回值時使早期回報更容易完成。 – 2013-03-11 20:52:09

+1

儘管能夠返回nil而不是指針肯定很方便,但我不會僅僅因爲這個原因而使用指針。返回非零錯誤的事實足以告訴您不要使用'卡'中的數據。你應該檢查錯誤而不是價值。否則,根本無法返回錯誤... – weberc2 2013-03-12 13:49:19

5

例如,

type Card struct { 
} 

func canFail() (card Card, err error) { 
    return Card{}, errors.New("not yet implemented") 
} 
+2

在這個例子中,甚至不需要命名返回值。 (你可能仍然希望他們以其他原因命名,或者你可能覺得功能更清晰,沒有名稱混亂) – Sonia 2013-03-11 12:20:39

+0

閱讀問題和我的答案。這是稍後實現的存根函數 - 空的'struct'和'「未實現」消息。由於我們不知道將使用什麼代碼來實現函數,唯一安全的方法是返回定義好的值,無論以後使用什麼代碼。 – peterSO 2013-03-11 13:45:16

5
func canFail() (card Card, err error) { 
     if somethingWrong { 
       err = errors.New("Not yet implemented") 
       return 
     } 

     if foo { 
       card = baz 
       return 
     } 

     ... 

     // or 
     return Card{Ace, Spades}, nil 
} 
+0

謝謝,這在語義上接近我的最後一個解決方案,雖然在語法上有點不同 – Fabien 2013-03-11 13:22:04

2

作爲返回結構的可能替代方案,您可以考慮讓調用方分配它和函數set params。

func canFail(card *Card) (err error) { 
    if someCondition { 
     // set one property 
     card.Suit = Diamond 

     // set all at once 
     *card = Card{Ace, Spade} 
    } else { 
     err = errors.New("something went wrong") 
    } 

    return 
} 

如果您不是去支持C++風格的引用,你也應該檢查card爲是nil舒適假裝。

https://play.golang.org/p/o-2TYwWCTL