Errors with types and values

xuanbao · · 422 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>So I was thinking if you could easily annotate error values with types and I came up with this proof-of-concept library: <a href="https://github.com/adamjedlicka/terror" rel="nofollow">https://github.com/adamjedlicka/terror</a></p> <p>My thoughts behind it was that return errors.New(...) or return fmt.Errorf(...) is really easy to do and gives you nice messages but in code you basically can&#39;t check what that error means (comparing strings is bad idea). So why not add types them and check for them with type assertion? It could be really useful if syntax is easy (and I think it is).</p> <p>Unfortunately I had to use reflection (only way I managed to make it work without reflection is not using types but pointers to type which is kinda ugly), but benchmarks show its fast enough to be usable in real code.</p> <p>I would really appreciate any type of feedback. I&#39;m suprised nothing similar is in use already so maybe I&#39;m missing something which makes this unusable.</p> <hr/>**评论:**<br/><br/>chewxy: <pre><p>I highly agree with Dave Cheny&#39;s way: check for behaviours, not types.</p> <p>For example, let&#39;s say I have a VM struct which caused an error. I want to pass the value that caused the error back, so I define an error type like so:</p> <pre><code>type valueErr struct { v Value } func (err *valueErr) Error() string { return &#34;Value Error&#34; } func (err *valueErr) Value() Value { return v } </code></pre> <p>when I want to check for errors, I define this:</p> <pre><code>type Valuer interface { Value() Value } ... if err = vm.RunAll(); err != nil { if ver, ok := err.(Valuer); ok { handle(ver) } } </code></pre> <p>The whole point of errors in Go is to either inform (of which the <code>.Error()</code> method is more than enough), or to handle. To handle errors, you shouldn&#39;t be inspecting the errors for its type. Instead you should be checking for what behaviours the error fulfils as that provides you with more context anyway</p> <p>I checked out your code - providing stack traces is a thing that many error packages provide (I personally prefer pkg/errors). I don&#39;t understand the need to reflect on the type of <code>Terror</code>. Is there a reason why?</p></pre>chronokitsune3233: <pre><p>Relevant blog post by Dave Cheney for more information: <a href="https://dave.cheney.net/2014/12/24/inspecting-errors" rel="nofollow">Inspecting errors</a></p></pre>smasher164: <pre><p>While <a href="/u/chewxy" rel="nofollow">/u/chewxy</a> makes a very good point about checking for behaviors rather than types, I do think that the answer depends on your specific use case. There was a previous discussion about custom error types <a href="https://www.reddit.com/r/golang/comments/680s4j/using_custom_error_types_for_testing/" rel="nofollow">here</a>, where I presented a scenario in which you are processing a lot of input, and cared about distinguishing between different error messages.</p> <p>Recently after working on that parser, I realized that comparing strings isn&#39;t that bad when it&#39;s just done in internal tests. Here is an example from the <a href="https://github.com/golang/go/blob/master/src/net/http/requestwrite_test.go" rel="nofollow">net/http</a> package which compares an error message to the wanted error message.</p> <p>Regarding your package, besides preserving stack traces, I don&#39;t see what additional functionality it provides that someone couldn&#39;t do by embedding an error:</p> <pre><code>type FormatErr struct { error } // return FormatErr{errors.New(...)} // switch err.(type) { // case FormatErr: // fmt.Println(&#34;Format error: &#34;, err) // } </code></pre></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

422 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传