在Go语言中,接口类型是由一组方法定义的集合。
一个类型是否实现了一个接口,就看这个类型是否实现了接口中定义的所有方法。在go语言中,无需特别的指明。
定义一个接口
type Abser interface {Abs() float64}
定义一个结构体
type Vertex struct {X, Y float64}
定义两个方法,一个是结构体指针,一个是结构体
func (v *Vertex) Abs() float64 {return v.X * v.X + v.Y * v.Y}func (v Vertex) Scale() float64 {return v.X + v.Y}
声明一个接口变量
var a Abser
结构体实例化
f := Vertex(3, 4)
指针也是Vertex结构体的指针,所以可以用f来实例化。
a = &f
分别看一下a和f都能实现什么方法。
fmt.Println(f.Abs())fmt.Println(f.Scale())fmt.Println(a.Abs())fmt.Println(a.Scale())
仔细测试,你会发现 fmt.Println(a.Scale()) 是会报错的“a.Scale undefined (type Abser has no field or method Scale)”。是的,a 没有 Scale() 这个方法。
为什么呢?因为 func (v Vertex) Scale() float64 里的是 Vertex 而不是 Vertex 。
如果你加上 符号,那么,a.Scale() 就可以实现了。
完整例子
package mainimport ("fmt")type Abser interface {Abs() float64}type Vertex struct {X, Y float64}func (v *Vertex) Abs() float64 {return v.X * v.X + v.Y * v.Y}func (v Vertex) Scale() float64 {return v.X + v.Y}func main() {var a Abserf := Vertex{3, 4}a = &ffmt.Println(f.Abs())fmt.Println(f.Scale())fmt.Println(a.Abs())//fmt.Println(a.Scale())}
运行结果
25725
结合上边的例子,我们可以发现,类型通过实现方法来实现接口,却不必要显示的声明。所有没有关键字implements。这是隐式接口。
隐式接口解耦了实现接口的包和定义接口的包,实现包和定义包”互不依赖”。
Stringers一个普遍存在的接口,在fmt中定义。
type Stringer interface{String() string}
我们给它在包内依附一个结构体,定义一个String()方法
type Cofox struct {name string}func (c *Cofox) String() string {return "Joel " + c.name}
为了区别原始的值,我们在 Strings() 内的返回值前加了一个字符串 Joel ,以作区别。
完整代码
package mainimport ("fmt")type Stringer interface {String() string}type Cofox struct {name string}func (c *Cofox) String() string {return "Joel " + c.name}func main() {var S Stringerc := Cofox{"Smith"}S = &cfmt.Println(S.String())fmt.Println(c.String())fmt.Println(c.name)}
运行结果如下
Joel SmithJoel SmithSmith
接口和结构体都可以使用 String() 函数方法。
你可是试着把 String() 方法里的返回值写成
return fmt.Sprintf("full name is Joel %v", c.name)
运行自己看看结果有无不同。
再写一个例子,这次结构体多加一个字段,看看如何应用。
package mainimport "fmt"type Person struct {Name stringAge int}func (p Person) String() string {return fmt.Sprintf("%v (%v years)", p.Name, p.Age)}func main() {a := Person{"Joel", 31}z := Person{"Smith", 45}fmt.Println(a, z)}
运行结果
Joel (31 years) Smith (45 years)

