Go语言入门(17)-接口
接口关注于类型可以做什么,而不是存储了什么。
接口通过列举类型必须满足的一组方法来进行声明。在Go语言中,不需要显式声明接口。
任何类型的任何值,只要满足接口的要求,即定义了一个talk()方法,返回值为string
package mainimport ("fmt""strings"
)var t interface { //接口专用关键字:interfacetalk() string //talk方法,返回值string
}type martian struct{}func (m martian) talk() string {return "nake nake"
}type laser intfunc (l laser) talk() string {return strings.Repeat("pew", int(l))
}func main() {t = martian{}fmt.Println(t.talk())t = laser(3)fmt.Println(t.talk())}
接口类型:
为了复用,通常会把接口声明为类型(按约定,接口名称通常以er结尾)。
package mainimport ("fmt""strings"
)type talker interface {talk() string
}type martian struct{}func (m martian) talk() string {return "nack nack"
}type laser intfunc (l laser) talk() string {return strings.Repeat("pew",int(l))
}func shout(t talker) {louder := strings.ToUpper(t.talk())fmt.Println(louder)
}func main(){shout(martian{})shout(laser(2))
}
同时,Go的接口都是隐式满足的,例子如下,它的目的是:定义一个接口stardater
,要求实现者提供“年内日”(YearDay)和“小时”(Hour)方法。然后,通过stardate
函数计算一个自定义的“星际日期”值:1000 + 年内日 + (小时 / 24)
。
package mainimport ("fmt""time"
)type stardater interface {YearDay() intHour() int
}type sol intfunc (s sol) YearDay() int {return int(s % 668)
}func (s sol) Hour() int {return 0
}func stardate(t stardater) float64 {doy := float64(t.YearDay())h := float64(t.Hour()) / 24.0return 1000 + doy + h
}func main() {day := time.Date(2012,8,6,5,17,0,0,time.UTC)fmt.Printf("%.1f Curiosity has landed\n",stardate(day))s := sol(1422)fmt.Printf("%.1f Happy birthday\n",stardate(s))
}
上述例程展示了Go的接口如何让不同类型(如内置的time.Time
和自定义的sol
)无缝协作,而无需显式继承。
满足接口:
Go标准库导出了很多只有单个方法的接口,Go通过简单的、通常只有单个方法的的接口,来鼓励组合而不是继承,这些接口在各个组件之间形成了简明易懂的界限。
例如fmt包声明的Stringer接口
package mainimport "fmt"type location struct {lat,long float64
}func (l location) string() string {return fmt.Sprintf("%v,%v",l.lat,l.long)
}func main() {curiosity := location{-4.5674,137.4417}fmt.Println(curiosity)
}