<p>Hi. Im quriuous too how people usually setup their api when using websockets. </p>
<p>When using Rest I usually have different URLs to handle CRUD etc, or other backend stuff.
But how does one go about making a good structure with ws? </p>
<p>I am using gorilla/websocket.</p>
<p>Building a chat function is simple, but what if I wanted a Crud?:) </p>
<p>I have some thoughts but dont know which way to go ( been trying to google for websocket apis but my googlefu seems to lack some skills ) </p>
<p>Thoughts:</p>
<p>1) Sending the json Objects with a specific field, say..."task": "remove"
And then using a switch to send the requests to the right function.
This seems inappropriate since the switch could grow pretty big, but manageble..</p>
<p>2) multiple sockets, one for broadcasting user interactions with eachother, one for crud? However this just seems kinda...wrong? </p>
<p>3) using normal http for crud and webspcket for user interaction.</p>
<p>How do you guys setup a websocket api?;)</p>
<hr/>**评论:**<br/><br/>gopherNoodle: <pre><p>Do something like this:</p>
<pre><code>// Message wraps all messages
type Message struct {
Kind string
Data json.RawMessage
}
// FooData is the payload for a "foo" message
type FooData struct {
// foo fields
}
// BarData is the payload for a "bar" message
type BarData struct {
// bar fields
}
</code></pre>
<p>In your read loop, call ReadJSON:</p>
<pre><code> for {
var m Message
if err := c.ReadJSON(&m); err != nil {
// handle error (exit loop and close connection)
}
switch m.Kind {
case "foo":
var d FooData
if err := json.Unmarshal([]byte(m.Data), &d); err != nil {
// handle error
}
// do something with d
case "bar":
...
}
}
</code></pre>
<p>If you are concerned about the size of the switch statement, then use a <code>map[string]func(*websocket.Conn, []byte)error</code> to look up handler code:</p>
<pre><code> for {
var m Message
if err := c.ReadJSON(&m); err != nil {
// handle error (exit loop and close connection)
}
if f := handlers[m.Kind]; f != nil {
if err := f(c, []byte(m.Data)); err != nil {
// handle error
}
}
}
</code></pre>
<p>Move the body of the case statements into individual functions and register the handlers map once.</p></pre>percybolmer: <pre><p>Tried it, you saved me alot of head ache! The map contaning the functions has made my api alot easier and probably more effeciant! Ive gotten rid of two channels one multicast and one broadcast and the api is much more scalable now! Im really greatful for this, that was a neat trick!
Summary:
1) you made my api scalable, instead of changing the code for each new wanted function I now simply modify my func setupHandlers() where the map is initiated with all wanted handlers.
2) efficenty, no longer do I need two global channels (yes, bad i know) that is continously scanned
3) Simplicity, since alot of logic handling is now gone, its much easier ti read and understand
4) the function callback, storing functions inside map, neat trick that I will try to implement more often, meaning alot of code will be more generic.</p>
<p>5) You sir, helped me alot! Many thanks for your time! I wish I had any reddit gold, if I did, id give you! ( Dont even know how to give them tho!:))</p></pre>percybolmer: <pre><p>Whaoh! Thanks ill try this for sure!!:) </p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
0 回复
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传