2013-03-11 74 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