我正在编写一个工具,它公开了一些函数,这些函数将信息从静态数据库中提取到我正在嵌入到工具中的几种脚本语言中。
我想; “嘿听起来像接口的一个很好的用例”。所以我在我的包脚本
中定义了一个这样的界面type ScriptingLang interface {
RunScript(filename string) error
RunString(s string) error
Interpreter() error
Init() error
IsInit() bool
}
然后我存储了它们的地图,以便我可以通过在不同包中定义的字符串来查找它们。
var ScriptingLangs = make(map[string]scripting.ScriptingLang)
和注册它们的功能。还有一些小助手功能,如
func RunString(lang, s string) error {
if v, ok := ScriptingLangs[lang]; ok {
if !v.IsInit() {
v.Init()
}
return v.RunString(s)
} else {
return NoSuchLangErr
}
return nil
}
我遇到的问题是接口不能有带指针接收器的方法。因此,我实现ScriptingLang的Lua结构无法保存它的*状态,因为它存储在ScriptingLangs中。
我已尝试在保存状态的函数末尾更新存储在地图中的值,但未更新该值。
根据我的理解,你不应该使用接口指针,那么我的选择是什么?我想保留接口,这样我就可以用git子模块做一些简洁的东西。
我的问题的一个最小例子:
package main
import (
"fmt"
)
type ScriptingLang interface {
DoString(s string) error
Init() error
}
type Lua struct {
state string
}
func (l Lua) DoString(s string) error {
fmt.Printf("Doing '%v' with state '%v'\n", s, l.state)
return nil
}
func (l Lua) Init() error {
l.state = "Inited"
return nil
}
var lang ScriptingLang
func main() {
lang = Lua{}
lang.Init()
lang.DoString("Stuff")
}
答案 0 :(得分:7)
如果你想改变状态,你需要一个指针接收器,而你的Init
方法没有。您将值存储在接口中的事实没有任何区别。
在最小(-ish)示例中,更改Init
方法(以及任何更新状态的方法)以使用指针接收器,并在接口内指向一个指针并且一切正常:
func (l *Lua) Init() error {
l.state = "Inited"
return nil
}
...
func main() {
lang = &Lua{}
lang.Init()
lang.DoString("Stuff")
}
这篇文章可能有所帮助:http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go