Best way to handle state in this scenario?

xuanbao · · 468 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I am attempting to build a so called text-based game or MUD (If you know the term) in Go in order to flex my brain with the language. This may or may not be intended to be a toy thing depending on how things go, but for right now it is a good way to put what I&#39;ve learned of the language down into code.</p> <p>In traditional old-school C-like MUDs linked lists of socket connections and player connections were kept globally throughout the whole program so the game could leverage them no matter where in the code you were. However, as we all know in general that is bad practice and I would like to avoid using globals to handle what I consider to be &#39;State like things&#39; which almost everything in the game interacts with.</p> <p>I have toyed with the idea of sticking them in a singular global struct known as World which contains maps of these things I need to store, like so:</p> <pre><code>type World struct { clients map[*Client]bool players map[*Player]bool } </code></pre> <p>This would only be created once in main() and then be present throughout the game as a global. This doesn&#39;t seem right to be though, certainly not very Go-like. Is there a better way to handle the kind of state I need to handle?</p> <p>Also, it seems like doing this would generate a lot of necessary boiler-plate methods to add, remove and retrieve values from the struct using methods. Imagine doing this for quite a few of the slices/maps that a MUD would need to handle. I.e below:</p> <pre><code>//... After accepting a new TCP connection conn, _ := listener.AcceptTCP() client := NewClient(conn) world.Clients().Add(client) //... somewhere else in code to cleanup world.Clients().Remove(client) </code></pre> <p>Is there a better way of doing any of this that doesn&#39;t seem so... clunky? Or am I overthinking things in disfavor of something simple and to the point.</p> <hr/>**评论:**<br/><br/>jerf: <pre><p>I&#39;d suggest</p> <pre><code> type World struct { sync.RWMutex Players map[PlayerID]*Player } </code></pre> <p>Along with other possilbe maps as needed.</p> <p>However, for each Player I&#39;d make it a server goroutine that is communicated with along a channel, as I describe towards <a href="http://www.jerf.org/iri/post/2917" rel="nofollow">the end of this blog post</a>. You shouldn&#39;t let things just send down arbitrary sockets.</p> <p>It may feel like extra boilerplate to write but you&#39;ll be happier in the end. In fact I would do the same sort of thing with C nowadays, because directly accessing sockets some portion of the code doesn&#39;t really &#34;own&#34; is dangerous; the thing just stuffing bytes down the socket is making it so that nothing quite knows the state of the protocol running on the socket. For a text-MUD that&#39;s probably recoverable since it&#39;s all text anyhow, but in general that&#39;s not a scalable design methodology.</p></pre>tmornini: <pre><p>Have you considered keeping the state in an external datastore such as Pg and/or Redis?</p></pre>bettersignup: <pre><p>Move the state to where it belongs: &#34;the world&#34; in this case. Make it a process and let clients communicate with it using a channel. No globals, no explicit locks. Just give clients a reference to the world process.</p></pre>

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

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