<p><a href="https://play.golang.org/p/cFP1BhjLWa" rel="nofollow">Code here</a></p>
<p>Basically I want to accept JSON "commands" over a websocket connection, and I want to get these commands into structs as soon as possible so I'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), &result); err != nil {
log.Fatal(err)
return nil, err
} else {
return result, nil
}
</code></pre>
<p>It'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's because the factored out function returns interface{} instead of the actual command type. Is there something obvious I'm missing? I'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'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'll only quit on invalid input, right?</p></pre>Femaref: <pre><p>yes, it does, but the method doesn'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 "result". I'm curious if that's possible, sorry if I wasn'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'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's nice not to be forced into it.</p>
<p>Go doesn't support class methods, except of course it does; a class method is just a method that doesn'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 "class methods". If you register a "class library" using nil pointers you'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't quite get it right. Then I went down a rabbithole of "reflect" calls and decided to scrap that whole thing. Thanks for this!</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传