定义
基本语法
type 接口名 interface {method1(参数列表) 返回值列表method2(参数列表) 返回值列表}
例子:多态
type Animal interface {Eat()Drink()}type Dog struct {}func (X Dog) Eat(){fmt.Println("狗爱吃骨头")}func (X Dog) Drink(){fmt.Println("狗爱喝骨头汤" )}type Cat struct {}func (J Cat) Eat(){fmt.Println("猫爱吃鱼")}func (J Cat) Drink(){fmt.Println("猫爱喝鱼汤")}type Person struct {}func (P *Person) Feed(A Animal) {A.Eat()A.Drink()}func main() {p :=Person{}d :=Dog{}c :=Cat{}p.Feed(d)p.Feed(c)}//------------------如果Dog与Cat绑定方法时,用的是指针func (X *Dog) Eat(){fmt.Println("狗爱吃骨头")}那么在main方法中,在调用时p.Feed(d)应改为p.Feed(&d),否则语法不通过原因:一个变量实现了某个接口后,在接口内部不能获取到该变量的地址(不可寻址)所以在p.Feed时,就需要传一个地址过去
注意事项
- 接口只定义方法名,不能有方法体
- 接口中不能有变量
- 接口的实现:一个变量实现了接口所有的方法(当然它还可以有自己的方法),那么称这个变量实现了该接口
- 只要是自定义数据类型都可以实现接口,不一定要是结构体
- 一个自定义类型可以实现多个接口
- 一个接口A,如果继承了其他的接口B,C。在实现A时,必须将B,C中的方法也实现。同时也需要注意,B,C中没有相同的方法,否则A接口的方法重复定义
- 任何类型都实现了空接口
sort.Sort(data Interface)
```goStudent中的Score进行升序排列
type Student struct { Name string Age int Score float64 }
type Students []Student
func (S Students) Len() int{ return len(S) } func (S Students) Less(i, j int) bool{ return S[i].Score<S[j].Score } func (S Students) Swap(i, j int){ S[i],S[j]=S[j],S[i] } func main() { S :=Student{} var SS Students rand.Seed(time.Now().UnixNano()) for i:=1;i<=5;i++{ S.Name=fmt.Sprintf(“小明%v号”,i) S.Age=rand.Intn(30) S.Score=float64(rand.Intn(100)) SS=append(SS,S) } fmt.Println(SS)//[{小明1号 20 44} {小明2号 13 39} {小明3号 3 79} {小明4号 28 18} {小明5号 8 27}] sort.Sort(SS) fmt.Println(SS)//[{小明4号 28 18} {小明5号 8 27} {小明2号 13 39} {小明1号 20 44} {小明3号 3 79}] }
<a name="Tpdl1"></a>#<a name="DSLpY"></a># 断言<a name="EQ4Uw"></a>### 用法```gofunc main() {var a interface{}b :=11.11a=b//空接口类型的值可以接受任意类型的值if c,flag:=a.(float64); flag{fmt.Println(c)}else {fmt.Println("转型失败!!!")}}
断言实践:多态
type Animal interface {Eat()Drink()}type Dog struct {}func (X Dog) Eat(){fmt.Println("狗爱吃骨头")}func (X Dog) Drink(){fmt.Println("狗爱喝骨头汤" )}func (X Dog) Call(){fmt.Println("狗:汪汪汪" )}type Cat struct {}func (J Cat) Eat(){fmt.Println("猫爱吃鱼")}func (J Cat) Drink(){fmt.Println("猫爱喝鱼汤")}type Person struct {}func (P *Person) Feed(A Animal) {A.Eat()A.Drink()if b,flag :=A.(Dog);flag{b.Call()}//如果不检验,由于Cat中没有Call(),会编译不通过}func main() {var arr =[...]Animal{Dog{},Cat{},}P :=Person{}for _,v :=range arr{P.Feed(v)}}
断言实践:类型判断
type Student2 struct {}func Judge(items ...interface{}){for i,v :=range items{i++switch v.(type) {case int,int8,int16,int32,int64:fmt.Printf("第%v个参数的类型是--int\n",i)case float64,float32:fmt.Printf("第%v个参数的类型是--float\n",i)case bool:fmt.Printf("第%v个参数的类型是--bool\n",i)case string:fmt.Printf("第%v个参数的类型是--string\n",i)case *Student2:fmt.Printf("第%v个参数的类型是--*Student2\n",i)case Student2:fmt.Printf("第%v个参数的类型是--Student2\n",i)default:fmt.Printf("第%v个参数的类型不确定\n",i)}}}func main() {a:=1b:=1.0c:=trued:="旺财"e:=&Student2{}f:=Student2{}g :=make([]int,10)Judge(g,a,b,c,d,e,f)}
空接口的陷阱
- 在使用空接口做为数据类型时,在使用时一定要还原
type Cat struct {Name stringAge string}func main() {slice :=make([]interface{},3)slice[0]=1slice[1]="哈哈"slice[2]=Cat{"小花","10"}fmt.Println(slice)c :=slice[2]//a :=slice[0]//a++ 基本数据类型也需要断言//fmt.Println(c.Name) 编译不通过newc,flag:=c.(Cat)if !flag{panic("断言失败")}fmt.Println(newc.Name)//小花}
判断有没实现接口
type Printer interface {Print()}type Java struct {}func (j Java) SystemOut() {fmt.Println("java")}type Golang struct {}func (g Golang) Print() {fmt.Println("golang")}func main() {var g Golang//var j Javarun111(g)}func run111(i interface{}) {if p, ok := i.(Printer); ok {p.Print()} else {fmt.Println("未实现Printer接口")}}
