我目前正处于编写实用程序库的设计阶段,该库将使与 x-go-binding 的交互变得更容易。 (我之前使用 Python 和 xpyb 完成过此操作。)例如,它将有助于查询 EWMH 规范 中定义的信息并将键绑定到回调函数。 (还有更多。)因此,作为我对包装布局的最初想法,请考虑:
每个都是它自己的包。 (与标准库的镜像包设置类似。)
我的情况的独特之处在于,几乎每个 x-go-binding 调用都需要 xgb 连接对象或根窗口标识符的某种组合。因此,对我来说,将这些信息存储在如下结构中是有意义的:
type XUtilConnection struct {
conn xgb.Conn
root xgb.Id
// a few other things, like a mapping of events to callbacks
}
这样我就有一个可以像这样使用的工厂:
xconn = xutil.NewXUtilConnection(blah blah)
它可以这样使用:
xconn.get_active_window()
xconn.bind_key("Shift-a", my_callback_fun)
还可能有这样的功能:
keybind.get_keycode("a")
ewmh.get_atom("_NET_ACTIVE_WINDOW")
我的问题当然是,据我所知,接收器只能是在同一个包中声明的类型。如果我分离我的包,我就无法在任何子包中使用我的 XUtilConnection 类型作为接收器。
我怀疑我的答案是将这个大包分成不同的逻辑文件,但我担心这可能会导致命名空间混乱。 (例如,实现 EWMH 规范可能需要 100 多个函数。)
我还知道我可以在 XUtilConnection 对象的每个子包中定义一个新的容器类型。 (我听说这应该是一个包含单个成员 XUtilConnection 的结构,以避免强制转换。)但这对我来说似乎是一个非常混乱的情况,并且会阻止我想要的那种语义。 (即,使用 XUtilConnection 结构调用多个不同模块中的方法。)
我建议使用嵌入。
包装内
xutil
:
type XUtilConnection struct {
*ewmh.EWMH // Embed all methods of *ewmh.EWMH
*keybind.KeyBind // Embed all methods of *keybind.KeyBind
}
包装内
xutil/ewmh
:
type EWMH struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some EWMH methods:
func (e *EWMH) GetAtom(name string) { ... }
func (e *EWMH) ...
包装内
xutil/keybind
:
type KeyBind struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some keybind methods:
func (k *KeyBind) GetKeyCode(s string) { ... }
func (k *KeyBind) ...
这将使您能够直接对
EWMH
类型的值调用 KeyBind
和 *XUtilConnection
的方法:
var c *XUtilConnection = ...
c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string)
c.GetKeyCode("a") // Call (*keybind.KeyBind).GetKeyCode(string)
我不确定我是否正确理解了这个问题(我对看到包名称感到困惑,它们似乎被讨论为方法接收者?),但我想传递一个接口而不是 [*] 结构将能够满足它来自任何包内。人们也可以总是做类似的事情(完全未经测试的代码):
package foo
type Foo interface { Bar(); Baz() }
----
package qux
import "foo"
type qux struct { foo.Foo; myStuff t }
func Foo(f foo.Foo) foo.Foo {
return qux{f, &t{}}
}
func (q qux) Bar() {
// smthg
}
例如包
f.Bar
中的“覆盖”qux
和“继承”f.Baz()
不变。