Question about error handling

xuanbao · · 342 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>How would you refactor the error handling in this function to not include multiple if err return statements.</p> <pre><code>func (client *APIClient) GetLocationsByDistance() (string, error) { //for now just return straight from server locations, err := client.getLocationsFromServer() if err != nil { return &#34;&#34;, err } data, err := json.Marshal(locations) if err != nil { return &#34;&#34;, err } return string(data), nil } </code></pre> <hr/>**评论:**<br/><br/>venju: <pre><p>I understand why you would want to do this, but an abundance of multiple returns is Go tradition, so it is what you should write if you expect other people to read your code.</p> <p>There are some circumstances where you can abstract away the generation of errors, especially when making lots of calls to the same function which returns an error. <a href="https://blog.golang.org/errors-are-values" rel="nofollow">Here is a blog post Rob Pike wrote about that.</a>.</p> <p>If you are in control of the errors you return, you have a lot more leeway if you design correctly. Errors are values, so you can do some neat stuff.</p> <p>In general gophers write, and expect to read, very explicit possibly redundant concrete code without much abstraction. Think C philosophy not haskell philosophy.</p> <p>To be clear because this a &#34;heated&#34; topic I&#39;m not making a statement about which philosophy is better; I just think recognizing and assimilating to a language&#39;s culture is the correct decision unless there is a <strong>strong</strong> argument for an alternative method.</p></pre>nevyn: <pre><p>Why would you want to?</p> <p>If the answer is &#34;Because it&#39;s my homework and it says to do that&#34; then it should also at least give hints on the way they want you to transform it.</p></pre>caseynashvegas: <pre><p>Not exactly homework, lol. Yes, the code is already pretty clean, but what if there were 3 or 4? I am just wondering what other professionals are doing. I don&#39;t like functions with multiple return statements in general. </p></pre>gbitten: <pre><blockquote> <p>I don&#39;t like functions with multiple return statements in general. </p> </blockquote> <p>Welcome to Go World, we love multiple returns.</p></pre>hgjkghjkhgfhf: <pre><p>So, now you know two issues that you have to work through to be a better Go programmer. Early returns and &#39;if err != nil&#39; are the norm in Go. Those among us might even say &#39;idiomatic&#39; go.</p></pre>iwsbfgl: <pre><p>I believe a lot of the dislike of multiple returns come from an overzealous adherence too Dijkstra&#39;s Single Entry, Single Exit paper. See this <a href="http://softwareengineering.stackexchange.com/a/118793" rel="nofollow">SO question</a> for more on that. I hadn&#39;t even realized it refernecing returning to different locations, not multiple exit points. Either way, this has become an often recited axiom in school. </p> <p>Where did that leave us? Dijkstra was advocating code that was easier to reason about and debug. Applying that to Go and other modern languages gives me my preferred style. I want to easily spot where a function exits. I want a single exit with a value. This allows me to easily add logging with the return value at the end of a function. I want to return early and often for errors. This means I don&#39;t need a lot of nested blocks of code, each of each checking for a other error. But to easily figure out where the function returns, each error must be unique. And no, the line number doesn&#39;t count. Those change to frequently. I want to errors that say failed to open file, then failed to read file, then failed to parse Jason from file, then an error saying a required field is missing. From those errors, I can easily reason about where the function exited.</p></pre>danredux: <pre><p>Adding logging to your return statements even when there are multiple exits is easy.</p> <pre><code>func LogMe() (n string) { defer func(){ fmt.Println(n) }() if 1 &gt; 2 { return &#34;impossible&#34; } return &#34;good&#34; } </code></pre></pre>iwsbfgl: <pre><p>Interesting technique. Thank you. </p></pre>driusan: <pre><pre><code>func (client *APIClient) GetLocationsByDistance() (string, error) { //for now just return straight from server locations, _ := client.getLocationsFromServer() data, _ := json.Marshal(locations) return string(data), nil } </code></pre> <p>(please don&#39;t do this.)</p></pre>danredux: <pre><p>There is a solution to this using what are essentially &#34;maybe monads&#34;.</p> <p>Here is a complete example (the &#34;error&#34; case emulated here is if you pass in a string that is not a valid integer).</p> <p><a href="https://play.golang.org/p/-lOEmguvEk" rel="nofollow">https://play.golang.org/p/-lOEmguvEk</a></p> <p>It ends up looking like this:</p> <pre><code>func (client *APIClient) GetLocationsByDistance() (string, error) { //for now just return straight from server locations := client.getLocationsFromServer() data := locations.Marshal() return data.Unbox() } </code></pre></pre>caseynashvegas: <pre><p>Very interesting example.</p></pre>hgjkghjkhgfhf: <pre><p>I wouldn&#39;t change a thing, this is how error handling is done in Go.</p></pre>

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

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