Can I reduce the boilerplate in this code?

blov · · 343 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p><a href="https://play.golang.org/p/cFP1BhjLWa" rel="nofollow">Code here</a></p> <p>Basically I want to accept JSON &#34;commands&#34; over a websocket connection, and I want to get these commands into structs as soon as possible so I&#39;m not working with strings and interface{} and all that.</p> <p>The part that bothers me is this:</p> <pre><code>if err := json.Unmarshal([]byte(rawCommand.Payload), &amp;result); err != nil { log.Fatal(err) return nil, err } else { return result, nil } </code></pre> <p>It&#39;s the same for each command type, but if I try to factor that out into a function then the type switch in main fails. I suspect it&#39;s because the factored out function returns interface{} instead of the actual command type. Is there something obvious I&#39;m missing? I&#39;m pretty new to Go.</p> <hr/>**评论:**<br/><br/>jmatosp: <pre><p>either return or log an error, not both.</p> <p>GetCommand is doing 2 things, Unmarshaling and Creating an object (factory), separate those, and you will get less boilerplate code</p></pre>nappy-doo: <pre><p>It seems to me, the real problem is the log.Fatal calls in GetCommand. I think the whole thing reads better as <a href="https://play.golang.org/p/AJF32BxLg5" rel="nofollow">this code</a>.</p></pre>bschwind: <pre><p>Ahh, that&#39;s a lot nicer, thanks! What does the log.fatal have to do with it though? I did mean to remove that though, forgot I left it in.</p></pre>Femaref: <pre><p>log.Fatal will quit the program.</p></pre>bschwind: <pre><p>Right, but why does that mean the type switch in main fails? It&#39;ll only quit on invalid input, right?</p></pre>Femaref: <pre><p>yes, it does, but the method doesn&#39;t really have a business killing the program. You might want to just skip that particular command in the future. As somebody else said, either return an err or log it, but not both.</p></pre>bschwind: <pre><p>Totally agree with that, but I was concerned with trying to abstract the unmarshal call into a function because the only variant in that block of code is the type of &#34;result&#34;. I&#39;m curious if that&#39;s possible, sorry if I wasn&#39;t clear about that.</p></pre>jerf: <pre><p>Use <a href="https://play.golang.org/p/EZEMWnX0aE" rel="nofollow">class methods</a>. Superficially that may initially appear to be more code, but overall you&#39;ll find that as you tune in on the real types you want and the real code you want that that structure will be a real help. For instance, it will help you avoid a big type switch to Do All The Things. Now, in Go I still sometimes end up with one of those for various reasons, but it&#39;s nice not to be forced into it.</p> <p>Go doesn&#39;t support class methods, except of course it does; a class method is just a method that doesn&#39;t refer to anything specific to the instance it is being called on. Syntax support may be nice, but is not necessary. And interfaces are also free to support &#34;class methods&#34;. If you register a &#34;class library&#34; using nil pointers you&#39;re only paying one word per registered class overhead.</p></pre>bschwind: <pre><p>Ahhh, very interesting!</p> <p><code> toParse := commands[rawCommand.EventName].New() </code></p> <p>This line in particular was the kind of thing I was looking for. I tried an idea similar to this but I couldn&#39;t quite get it right. Then I went down a rabbithole of &#34;reflect&#34; calls and decided to scrap that whole thing. Thanks for this!</p></pre>

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

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