interface和method再java中的概念基本一样。但是go这里不需要显示的说明,只需要默默的实现,有好处也有坏处。
下面是个小例子。只要一个struct实现了interface的所有方法,就可以把这个struct赋值给一个interface。
注意在实现的时候尽量用指针,不然struct内有变量的话,每次调用方法其实是真正你想修改的副本,这个涉及到interface的原理。每次在调用的时候,你的括号里的结构体或者其指针会作为一个参数传递进去,go是基于值传递的,所以传递的是副本,你怎么修改里面的,其实都是修改的副本。
type (
Processer interface {
Set(int)
Get() int
}
ProcesserImpl struct {
val int
}
)
func (p *ProcesserImpl) Set(v int) {
p.val = v
}
func (p *ProcesserImpl) Get() int {
return p.val
}
func main() {
var p Processer
p = new(ProcesserImpl) // or &ProcesserImpl{}
p.Set(1)
fmt.Println(p.Get())
}
另外go提供了比较有意思的embedding的功能,就是简单的处理方法能让另外一个struct具备这个struct的所有方法。
下面的例子中,SuperProcesser直接可以用Set和Get方法了,而不需要再去访问他内部的ProcesserImpl。
type (
Processer interface {
Set(int)
Get() int
}
ProcesserImpl struct {
val int
}
SuperProcesser struct {
*ProcesserImpl
}
)
func (p *ProcesserImpl) Set(v int) {
p.val = v
}
func (p *ProcesserImpl) Get() int {
return p.val
}
func main() {
p := SuperProcesser{&ProcesserImpl{}}
p.Set(10)
fmt.Println(p.Get())
}
interface如果是空的,那你可以传任何值。然后用type assertion和type switch来判断类型。
type Empty interface{
}
func TestType(e Empty) {
if v, ok := e.(int); ok {
fmt.Println(v, ok)
} else {
fmt.Println("not int", e)
}
}
func SwitchType(e interface{}) {
switch v := e.(type) {
case int:
fmt.Println(v, "I am int")
case string:
fmt.Println(v, "I am string")
}
}
func main() {
TestType(1)
TestType("test")
SwitchType(1)
SwitchType("haha")
}
网友评论