我正在解决 The Go Programming Language 这本书中的问题,
在练习7.13中,需要向接口添加String
方法。
是否可以向接口添加String()
方法?因为数据类型直到运行时才知道。
我正在解决 The Go Programming Language 这本书中的问题,
在练习7.13中,需要向接口添加String
方法。
是否可以向接口添加String()
方法?因为数据类型直到运行时才知道。
type Fooer interface {
Foo()
}
Foo()
。要将String()
方法添加到此接口中:type Fooer interface {
Foo()
String() string
}
完成。我们已将String()
方法添加到此接口。
这意味着,如果一个具体类型想要实现这个Fooer
接口,以前只需要有一个Foo()
方法就足够了。现在还必须有一个String()
方法。
另外,请注意,在Go语言中,实现接口是隐式的。没有声明意图的过程。如果一个类型拥有接口的所有方法,则它会隐式地满足该接口。
一个具体类型可能有也可能没有String()
方法,与我们的Fooer
接口无关。具体类型甚至可能不知道我们的Fooer
接口,也不需要知道。
下面是一个实现这个Fooer
接口的具体类型:
type fooerImpl int
func (f fooerImpl) Foo() {
fmt.Printf("Foo() called, I'm %d\n", int(f))
}
func (f fooerImpl) String() string {
return fmt.Sprintf("Foo[%d]", int(f))
}
测试它:
var f Fooer = fooerImpl(3)
f.Foo()
fmt.Println(f.String())
fmt.Println(f)
输出(在Go Playground上尝试):
Foo() called, I'm 3
Foo[3]
Foo[3]
如果您随意向接口中添加新方法,可能会导致某些先前实现了该接口的具体类型不再实现它(由于缺少新添加的方法)。
如果这些现有的具体类型被用作接口实例,它们将导致编译时错误,并且在您添加缺失的新方法之前无法正常工作。例如,如果我们从上面的示例中删除fooerImpl.String()
方法,则代码var f Fooer = fooerImpl(3)
会导致编译时错误:
cannot use fooerImpl(3) (type fooerImpl) as type Fooer in assignment:
fooerImpl does not implement Fooer (missing String method)
interface{}
中传递,并使用type assertion提取接口的值,则这些类型断言将不再有效。类型断言的“简单”形式x.(T)
将导致运行时恐慌,特殊形式v, ok := x.(T)
将返回nil
和false
。String()
方法的情况下使用上述的fooerImpl
类型:var f0 interface{} = fooerImpl(3)
f := f0.(Fooer)
运行时恐慌的结果:
panic: interface conversion: main.fooerImpl is not main.Fooer: missing method String
并使用特殊的类型转换形式:
if f, ok := f0.(Fooer); ok {
f.Foo()
} else {
fmt.Println("Not instance of Fooer!", f)
}
结果为:
Not instance of Fooer! <nil>