我有一个项目使用这样的结构:
type I interface {
GetName() string
DoSomething()
}
//
// A implements I
//
type A struct {
Name string
}
func (a *A) GetName() string {
return a.Name
}
func (a *A) DoSomething() {
...do something
}
//
// B implements I
//
type B struct {
Name string
}
func (b *B) GetName() string {
return b.Name
}
func (b *B) DoSomething() {
...do something
}
func (b *B) DoSomethingElse() {
...do something else
}
//
// Both
//
func UseAorB(T I) {
name := T.GetName()...
}
- 在接受接口I的函数中调用时,使用GetName是从结构A或B获取名称字段的最佳方式吗
- 我是否每次都必须为要实现接口的每件事重新定义DoSomething?或者,如果DoSomething每次都是一样的,而我只能定义一次,那么有更好的方法可以做到这一点吗
- 结构B具有接口未定义的方法(DoSomethingElse(。我是否需要使用反射才能将结构B传递给使用接口I调用DoSomethingElse的函数?或者我应该定义一个包含此方法的新接口吗
我想提高我的代码质量,写一个坚实的库,但我不得不说,我感觉自己在与语言作斗争,让我的生活变得更加困难。
-
是的,
GetName()
是实现的好方法 -
如果你有类似的方法实现,你通常可以把它移到一个公共结构中并嵌入:
type Common struct {} func (c Common) DoSomething() {...} type A struct { Common Stuff } type B struct { Common Other stuff }
上面,
A
和B
都有DoSomething
方法,并且它们共享实现 -
不要使用反射。有两种方式:
-
使用类型断言:
func f(in I) { if b, ok:=in.(B); ok { // b is of type B, so: b.DoSomethingElse() } }
使用接口并键入断言:
type DoesSometingElse interface { DoSomethingElse() } func f(in I) { if x, ok:=in.(DoesSomethingElse); ok{ x.DoSomethingElse() } }
-
如果你觉得自己在与语言作斗争,那么要么你建模错误,要么你不知道用该语言做某事的正确方法。所有语言的做事方式都有好的和坏的,而且很多时候每种语言的做法都不一样。如果你是从另一种语言来围棋的,你应该首先停止尝试用另一种语文思考,翻译成围棋,并尝试单独使用围棋。