Go 之 interface接口理解
2010 年 9 月 29 日
go语言并没有面向对象的相关概念,go语言提到的接口和java、c++等语言提到的接口不同,它不会显示的说明实现了接口,没有继承、子类、implements关键词。go语言通过隐性的方式实现了接口功能,相对比较灵活。
interface是go语言的一大特性,主要有以下几个特点:
interface是go语言的一大特性,主要有以下几个特点:
- interface 是方法或行为声明的集合
- interface接口方式实现比较隐性,任何类型的对象实现interface所包含的全部方法,则表明该类型实现了该接口。
- interface还可以作为一中通用的类型,其他类型变量可以给interface声明的变量赋值。
- interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。
下面是一些代码示例
接口实现
package main import "fmt" type Animal interface { GetAge() int32 GetType() string } type Dog struct { Age int32 Type string } func (a *Dog) GetAge() int32 { return a.Age } func (a *Dog) GetType() string { return a.Type } func main() { animal := &Dog{Age: 20, Type: "DOG"} fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge()) }
interface作为通用类型
package main import ( "fmt" "reflect" ) type User struct { Id int Name string Amount float64 } func main() { var i interface{} i = "string" fmt.Println(i) i = 1 fmt.Println(i) i = User{Id: 2} //i.(User).Id = 15 //运行此处会报错,在函数中修改interface表示的结构体的成员变量的值,编译时遇到这个编译错误,cannot assign to i.(User).Id fmt.Println(i.(User).Id) }
interface接口查询
接口查询,在一个接口变量中,查询所赋值的对象有没有实现其他接口所有的方法的过程,就是查询接口。即接口A实现了接口B中所有的方法,那么通过查询赋值A可以转化为B。
代码示例
package main import "fmt" type Animal interface { GetAge() int32 GetType() string } type AnimalB interface { GetAge() int32 } type Dog struct { Age int32 Type string } func (a *Dog) GetAge() int32 { return a.Age } func (a *Dog) GetType() string { return a.Type } func main() { var animal Animal = &Dog{Age: 20, Type: "DOG"} fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge()) var animalb AnimalB = &Dog{Age: 20, Type: "DOG"} fmt.Printf("max age is: %d", animalb.GetAge()) //这里实现了animalb 转化Animal接口 val, ok := animalb.(Animal) if !ok { fmt.Println("ok") } else { fmt.Printf("%s max age is: %d", val.GetType(), val.GetAge()) } }
接口转化很简单
val, ok := animalb.(Animal)
注意,animalb 只有AnimalB所包含的方法GetAge()。
如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A,反之则不行。
接口类型查询
只能对interface{}类型的变量使用类型查询
示例
package main import "fmt" type Animal interface { GetAge() int32 GetType() string } type AnimalB interface { GetAge() int32 } type Dog struct { Age int32 Type string } func (a *Dog) GetAge() int32 { return a.Age } func (a *Dog) GetType() string { return a.Type } func main() { var i interface{} //i = "ok" //方法一 val, ok := i.(Animal) if !ok { fmt.Println("no") } else { fmt.Println(val.GetAge()) } // 方法二 switch val := i.(type) { case string: fmt.Println(val) case int: fmt.Println(val) default: fmt.Println(val) } // 方法三 通过反射 typename := reflect.TypeOf(i) fmt.Println(typename) }
interface默认nil所以查出是nil,如果给i赋值一个字符型值(去掉i = “ok”前面的注释),则返回
no
ok
string
参考:
https://blog.csdn.net/hzwy23/…
https://www.cnblogs.com/zhang…