Architecture 在Go中存储状态
我正在用围棋写一个简单的程序,作为学习围棋语言的练习。该程序是一个游戏玩家:它Architecture 在Go中存储状态,architecture,go,coding-style,global-variables,information-hiding,Architecture,Go,Coding Style,Global Variables,Information Hiding,我正在用围棋写一个简单的程序,作为学习围棋语言的练习。该程序是一个游戏玩家:它exec.Commands是一个基于文本的游戏,然后通过StdinPipe/StdoutPipe与之通信。经过一番胡闹和阅读大量在线文档后,我成功地使框架工作起来——相当于Hello World,在那里我建立了双向通信,可以处理程序终止等错误 现在我正在尝试编写实际的游戏AI代码。因为我的目的是学习这门语言,所以我在风格上非常谨慎——我不想只想用围棋写C(或其他语言) 程序中明显的分工(一旦所有设置完成)分为两部分。首
exec.Command
s是一个基于文本的游戏,然后通过StdinPipe
/StdoutPipe
与之通信。经过一番胡闹和阅读大量在线文档后,我成功地使框架工作起来——相当于Hello World,在那里我建立了双向通信,可以处理程序终止等错误
现在我正在尝试编写实际的游戏AI代码。因为我的目的是学习这门语言,所以我在风格上非常谨慎——我不想只想用围棋写C(或其他语言)
程序中明显的分工(一旦所有设置完成)分为两部分。首先,程序查看当前状态并决定应该向游戏发出什么命令。其次,程序查看返回的数据并相应地更新状态。(是的,这是一个简单的游戏——它等待输入,然后响应,没有时间问题。)
我不确定这些州信息应该放在哪里。将其全部转储到全局范围感觉是错误的,而创建一个庞大的单例对象似乎更糟糕(Go并不是特别的OO)。在任何情况下,我都不想让函数传递并返回20多个变量
一般的建议很好,但我最感兴趣的是什么在习惯上适合围棋。根据请求,我可以共享代码,但我认为这不会有什么帮助。Go确实启用了一个
为游戏状态创建结构类型。在程序中传递一个指向这种类型的值的指针,或者将指针存储在包级别变量中(如果这类事情不困扰您的话)。根据需要在此类型上实现方法。考虑将它放入自己的包中进行更大的封装。 < P>我喜欢使用这个程序包。 简单的例子:
package foo
func Incr() {
f.incr()
}
func Count() int {
return f.count()
}
type foo struct {
sync.RWMutex
count int
}
func (f *foo) incr() {
f.Lock()
f.count++
f.Unlock()
}
func (f *foo) count() int {
f.RLock()
defer f.RUnlock()
return f.count
}
var f = &foo{}
此包可以导入到任何其他包并保持状态。我添加了sync.RWMutex以防止任何竞争条件。这使您能够完全控制如何访问foo的状态,并且可以很好地控制它。谢谢您的回答。如果你不介意的话,我会等到明天再接受答案——我还在考虑什么样的解决方案最好。(+1)谢谢。让我确保我理解你的建议:我创建一个
struct
,它保存所有状态变量,然后将其实例化为一个全局对象,以便在更新函数中检查和修改状态。对的(当然,我对你也是一样。)@Charles,没错。您可以在结构上存储所需的任何状态,如果愿意,还可以向该结构添加方法。这种方法的优点是,您可以完全控制访问并轻松地将状态导入其他包。Go的net/http包采用与HandlerFunc和Handler方法类似的方法,允许您在多个包中添加http处理程序。@tommywild您能详细说明一下吗?添加foo_测试和测试包中的任何内容都非常容易。您还可以使用导出的方法轻松测试上述功能。@tommywild我明白您的意思。我编辑了答案,所以foo有一个incr和count方法,这将允许对foo进行独立于f状态的测试。@tommywild我简单地删除了这个答案,考虑了一会儿,现在正在取消删除它。我的理性:在游戏(或大多数程序)中,你需要某种方式来维持状态。上述方法允许线程安全地访问游戏状态,并允许程序的任何部分轻松访问所述状态,而无需将状态传递给每个函数。我认为这种方法应该谨慎使用,但一定程度的实用主义会起到很大作用。