该问题与Golang function to return an Interface有关,并在此问题上进行了扩展。
我的设置如下:
我正在创建游戏的服务器端,客户端可以在其中选择不同的游戏模式。这些模式是通过不同的结构以及它们自己对某些方法的实现而实现的,所有这些方法都是它们在package engines
中的文件,例如:
package engines
import "fmt"
type Square struct {
tiles []int
players []bool
}
func NewSquare() *Square {
return &Square{
[25]int{}[:],
[]bool{false, false},
}
}
func (e *Square) AddPlayer() (int, error) {
for id := range e.players {
if !e.players[id] {
e.players[id] = true
return id, nil
}
}
return -1, fmt.Printf("game already full")
}
在主程序包中,当创建一个新游戏时,我正在使用地图来调用相应游戏模式的newSomething
函数。每个引擎都满足界面gameEngine
:
package main
import "engines"
type gameEngine interface {
AddPlayer() (int, error)
}
type GameMode int
const (
SQUARE GameMode = 0
TRIANGLE GameMode = 1
)
在主软件包中定义此接口的原因主要有两个:
package engines
内,就像回到类明确声明其实现的接口的情况一样,其中一件事情是设计不需要的。这意味着在引擎实现的文件中,例如Square.go
和Triangle.go
,我无权访问该接口,并且相应的newFunction必须返回其各自的类型,这使得它们分别为func() *Square
和func() *Triangle
类型(请参见上文)。
现在我不能在map[GameMode]func() gameEngine
中直接使用这些新功能,因为它们的类型是错误的。我当前的解决方案是使用相当冗长的内联函数(由链接的问题中的答案之一启发)来转换它们:
var engine gameEngine
var newGameFuncs = map[GameMode]func() gameEngine {
SQUARE: func() gameEngine { return engines.NewSquare() },
TRIANGLE: func() gameEngine { return engines.NewTriangle() },
}
func JoinGame(mode GameMode) (int, error) {
engine = newGameFuncs[mode]()
id, err := engine.AddPlayer()
// Some other stuff, too
return id, nil
}
这张地图感觉非常笨拙和虚假,但是据我所知,这是使用这种地图方法的唯一方法。
是否有更好的方法或设计模式可以实现我的目标?
func JoinGame(mode GameMode) (int, error)
是我的客户端界面的一部分,它是整件事的起点,必须保留其签名。type gameEngine interface
应该保留在主程序包中。Hexagon.go
)时,唯一必要的步骤应该是制作文件并将newHexagon
函数注册在一个位置。答案 0 :(得分:0)
您宁愿定义一个新的类型(函数的别名),而不是一个接口。
type AddPlayer func() (GameMode, error)
并使用engine
包中的函数封装此映射,您可以在其中使用init()
在单独的文件中添加新的句柄功能(按需)。喜欢:
engine/main.go
:
package engins
type GameMode int
const (
SQUARE = iota
TRIANGLE
)
type AddPlayer func() (GameMode, error)
var newGameFuncs = make(map[GameMode]AddPlayer)
func GetAddPlayerFuncByGameMode(gm GameMode) AddPlayer {
return newGameFuncs[gm]
}
engine/square.go
:
package engins
func init() {
newGameFuncs[SQUARE] = engineSquare{}.NewSquare
}
type engineSquare struct{}
func (engineSquare) NewSquare() (GameMode, error) {
return SQUARE, nil
}
从main.go
开始,您将可以像这样使用它:
package main
import e "./engins"
func main() {
e.GetAddPlayerFuncByGameMode(e.SQUARE)
}