<p>I understand that <code>error</code> is an interface, and that in theory there are lots of choices for what to satisfy that interface. However, in practice, what tends to be chosen?</p>
<p>When is <code>errors.New</code> or <code>fmt.Errorf</code> preferred? Should those be the default, in the absence of additional requirements? Should values from those be reused, or should those calls be reinvoked every time? What about when there needs to be additional data attached to an error? When is <code>fmt.Errorf</code> sufficient, vs when is something custom like a struct necessary?</p>
<p>Suppose function A calls function B, function B returns an error, and function A is unable to resolve this error and must itself return an error. Should function A return the same error, the same error but wrapped, or a new error entirely? In the case of wrapping, how should this be structured to be more easily handled by further up the call stack?</p>
<p>How should errors be checked? In particular, what if a function needs more complex logic beyond just <code>if err != nil</code>? How is the recommended way to differentiate between error types and potentially destructure error values into their components? Is it considered good practice to use a series of type assertions on the possible types, or would that be too much of an abstraction leak?</p>
<p>Sorry if that was too dense a wall of text. I was just trying to get a train of thought written down.</p>
<p>Thank you in advance for your help.</p>
<hr/>**评论:**<br/><br/>shovelpost: <pre><blockquote>
<p>When is errors.New or fmt.Errorf preferred? Should those be the default, in the absence of additional requirements? Should values from those be reused, or should those calls be reinvoked every time? What about when there needs to be additional data attached to an error?</p>
</blockquote>
<pre><code>var ErrEmailNotValid = errors.New("email not valid")
if err != nil {
return fmt.Errorf("error opening database: %v", err)
}
</code></pre>
<blockquote>
<p>When is fmt.Errorf sufficient, vs when is something custom like a struct necessary?</p>
</blockquote>
<p>If you need your errors to carry more data that you need to inspect later then you define a custom struct that usually satisfies the <code>Error()</code> method. Read <a href="https://blog.golang.org/error-handling-and-go#TOC_2." rel="nofollow">this part</a>.</p>
<blockquote>
<p>Suppose function A calls function B, function B returns an error, and function A is unable to resolve this error and must itself return an error. Should function A return the same error, the same error but wrapped, or a new error entirely? In the case of wrapping, how should this be structured to be more easily handled by further up the call stack?</p>
</blockquote>
<p>It really depends. Does function A know any additional information or context to wrap the error around? If it does then you can wrap the error with <code>fmt.Errorf</code> to provide that additional context. Need more fine grained wrapping? Use a custom error struct.</p>
<blockquote>
<p>How should errors be checked? In particular, what if a function needs more complex logic beyond just if err != nil? How is the recommended way to differentiate between error types and potentially destructure error values into their components? Is it considered good practice to use a series of type assertions on the possible types, or would that be too much of an abstraction leak?</p>
</blockquote>
<p>That's a very broad question and again it depends. A very useful technique is one that uses type assertions in just once place in the code to determine what kind of error it is and handle it appropriately. Read <a href="https://blog.golang.org/error-handling-and-go#TOC_3." rel="nofollow">this part</a>.</p>
<p>If you are writing a library and you are concerned about the surface of error variables you make public (which the clients will have to use), there's another useful technique. Read the "Assert errors for behaviour, not type" part in <a href="https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully" rel="nofollow">this article</a>.</p>
<p>Also check how the Upspin team does <a href="https://github.com/upspin/upspin/blob/master/errors/errors.go" rel="nofollow">error handling</a>. I am not saying you should do that but it shows what the <a href="https://www.youtube.com/watch?v=PAAkCSZUG1c&t=16m13s" rel="nofollow">Go proverb</a> "Errors are values" <a href="https://blog.golang.org/errors-are-values" rel="nofollow">means</a> in practice. Program with your errors to handle your specific case.</p></pre>gopher8: <pre><p>Some thoughts on wrapping errors and more:
<a href="https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package" rel="nofollow">https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package</a></p></pre>kavirajk: <pre><p><a href="https://github.com/mpvl/errd" rel="nofollow">https://github.com/mpvl/errd</a></p>
<p>This pkg looks good. Best practices towards go2</p></pre>
What are best practices on errors with field data, passing errors up, wrapping errors, and checking error values?
blov · · 455 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传