英文:
Storing state in Go
问题
我正在使用Go语言编写一个简单的程序,作为学习该语言的练习。这个程序是一个游戏玩家:它通过exec.Command
执行一个基于文本的游戏,然后通过StdinPipe
/StdoutPipe
与游戏进行通信。经过一些尝试和阅读大量的在线文档,我成功地让程序的框架工作了,相当于Hello World,我已经建立了双向通信,并且可以处理程序终止等错误。
现在我正在尝试编写实际的游戏AI代码。由于我的目的是学习这门语言,我试图非常谨慎地处理代码风格,我不只是想在Go中编写C(或其他语言)。
程序的明显分工(一旦完成所有的设置)分为两部分。首先,程序查看当前状态并决定应该向游戏发出什么命令。其次,程序查看返回的数据并相应地更新状态。(是的,这是一个简单的游戏——它等待输入然后做出响应,没有时间问题。)
我不确定这些状态信息应该放在哪里。把它们全部倒入全局范围感觉不对,而创建一个庞大的单例对象似乎更糟糕(而且Go并不特别支持面向对象)。无论如何,我不想让函数传递和返回20多个变量。
一般的建议很好,但我最感兴趣的是Go中惯用的做法。如果需要,我可以分享代码,但我不认为这会有帮助。
英文:
I'm writing a simple program in Go as an exercise to learn the language. The program is a game player: it exec.Command
s a text-based game, then communicates with it via StdinPipe
/StdoutPipe
. After some fooling around and reading a lot of online docs I managed to get the skeleton working -- the equivalent of Hello World, where I've established two-way communication and can handle errors like the program terminating.
Now I'm trying to write the actual game-playing AI code. Since my purpose is learning the language, I'm trying to be very careful with style -- I don't just want to write C (or some other language) in Go.
The obvious division of labor in the program (once all the setup is done) is into two parts. First, the program looks at the current state and decides what command should be issued to the game. Second, the program looks at the data returned and updates the state accordingly. (Yes, it's a simple game -- it waits for input and then responds, there are no timing issues.)
I'm not sure where this state information should go. Dumping it all into the global scope feels wrong, and making a massive singleton object seems even worse (and Go isn't particularly OO). In any case I don't want to have the functions pass and return 20+ variables.
General advice is fine, but I'm most interested in what is idiomatically appropriate for Go. On request I can share code but I don't think it would be helpful.
答案1
得分: 5
我喜欢使用一个包来实现这个目的。
简单的例子:
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的状态,并且它被很好地封装起来。
英文:
I like using a package for this purpose.
trivial example:
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{}
This package can be imported into any other package and maintain state. I added the sync.RWMutex to prevent any race conditions. This gives you complete control of how foo's state is accessed and is nicely contained.
答案2
得分: 2
Go确实支持一种面向对象编程的风格。
为游戏状态创建一个结构体类型。在程序中传递该类型的值的指针,或者将指针存储在包级别的变量中(如果这样做不会对你造成困扰的话)。根据需要在该类型上实现方法。考虑将其放在自己的包中以实现更好的封装性。
英文:
Go does enable a style of OO programming.
Create a struct type for the game state. Pass a pointer to a value of this type around in your program or store the pointer in a package level variable if that sort of thing does not bother you. Implement methods on this type as needed. Consider putting it in its own package for greater encapsulation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论