博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go Interface
阅读量:5780 次
发布时间:2019-06-18

本文共 4225 字,大约阅读时间需要 14 分钟。

hot3.png

1. 什么是interface?简单的说,interface是一组method的组合,我们通过interface来定义对象的一组行为。interface类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。任意的类型都实现了空interface(interface{}),也就是包含0个method的interface。如果定义了一个interface的变量,那么这个变量里面可以存实现这个interface的任意类型的对象。

package mainimport "fmt"type Human struct {    name string    age int    phone string}type Student struct {    Human //匿名字段    school string    loan float32}type Employee struct {    Human //匿名字段    company string    money float32}//Human实现Sayhi方法func (h Human) SayHi() {    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)}//Human实现Sing方法func (h Human) Sing(lyrics string) {    fmt.Println("La la la la...", lyrics)}//Employee重载Human的SayHi方法func (e Employee) SayHi() {    fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,        e.company, e.phone) //Yes you can split into 2 lines here.    }// Interface Men被Human,Student和Employee实现// 因为这三个类型都实现了这两个方法type Men interface {    SayHi()    Sing(lyrics string)}func main() {    mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}    paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}    sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}    Tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}    //定义Men类型的变量i    var i Men    //i能存储Student    i = mike    fmt.Println("This is Mike, a Student:")    i.SayHi()    i.Sing("November rain")    //i也能存储Employee    i = Tom    fmt.Println("This is Tom, an Employee:")    i.SayHi()    i.Sing("Born to be wild")    //定义了slice Men    fmt.Println("Let's use a slice of Men and see what happens")    x := make([]Men, 3)    //T这三个都是不同类型的元素,但是他们实现了interface同一个接口    x[0], x[1], x[2] = paul, sam, mike    for _, value := range x{        value.SayHi()    }}

interface就是一组抽象方法的集合,它必须由其他非interface类型实现,而不能自我实现, go 通过interface实现了duck-typing。

2. 空interface(interface{})不包含任何的method,正因为如此,所有的类型都实现了空interface。空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。它有点类似于C语言的void*类型。

// 定义a为空接口var a interface{}var i int = 5s := "Hello world"// a可以存储任意类型的数值a = ia = s

一个函数把interface{}作为参数,那么他可以接受任意类型的值作为参数,如果一个函数返回interface{},那么也就可以返回任意类型的值。

3. interface的变量可以持有任意实现该interface类型的对象,这给我们编写函数(包括method)提供了一些额外的思考,我们可以通过定义interface参数,让函数接受各种类型的参数。

4. interface的变量里面可以存储任意类型的数值(该类型实现了interface)。那么我们怎么反向知道这个变量里面实际保存了的是哪个类型的对象呢?目前常用的有两种方法:

  • Comma-ok断言

          Go语言里面有一个语法,可以直接判断是否是该类型的变量: value, ok = element.(T),这里value就是变量的值,ok是一个bool类型,element是interface变量,T是断言的类型。如果element里面确实存储了T类型的数值,那么ok返回true,否则返回false。

  • switch测试
package mainimport (    "fmt"    "strconv")type Element interface{}type List [] Elementtype Person struct {    name string    age int}//打印func (p Person) String() string {    return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"}func main() {    list := make(List, 3)    list[0] = 1 //an int    list[1] = "Hello" //a string    list[2] = Person{"Dennis", 70}    for index, element := range list{        switch value := element.(type) {            case int:                fmt.Printf("list[%d] is an int and its value is %d\n", index, value)            case string:                fmt.Printf("list[%d] is a string and its value is %s\n", index, value)            case Person:                fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)            default:                fmt.Println("list[%d] is of a different type", index)        }    }}
element.(type)
语法不能在switch外的任何逻辑里面使用,如果你要在switch外面判断一个类型就使用comma-ok

5. 嵌入interface。如果一个interface1作为interface2的一个嵌入字段,那么interface2隐式的包含了interface1里面的method。

 

源码包container/heap里面有这样的一个定义

type Interface interface {    sort.Interface //嵌入字段sort.Interface    Push(x interface{}) //a Push method to push elements into the heap    Pop() interface{} //a Pop elements that pops elements from the heap}

我们看到sort.Interface其实就是嵌入字段,把sort.Interface的所有method给隐式的包含进来了。也就是下面三个方法

type Interface interface {    // Len is the number of elements in the collection.    Len() int    // Less returns whether the element with index i should sort    // before the element with index j.    Less(i, j int) bool    // Swap swaps the elements with indexes i and j.    Swap(i, j int)}

 

转载于:https://my.oschina.net/renguijiayi/blog/152043

你可能感兴趣的文章
湘潭邀请赛——Alice and Bob
查看>>
js设置定时器
查看>>
数据库除运算
查看>>
LeetCode--112--路径总和
查看>>
DeviceIOControl与驱动层 - 缓冲区模式
查看>>
感悟贴2016-05-13
查看>>
vim使用教程
查看>>
JDK在LINUX系统平台下的部署案例与总结
查看>>
跨vlan通信-----单臂路由技术
查看>>
百度编辑器ueditor 光标位置的坐标
查看>>
DEV-C++ 调试方法简明图文教程(转)
查看>>
VS2017+EF+Mysql生成实体数据模型(解决闪退的坑)
查看>>
C++多态、继承的简单分析
查看>>
库克称未来苹果用户可自己决定是否降频 网友:你是在搞笑吗?
查看>>
6倍性能差100TB容量,阿里云POLARDB咋实现?
查看>>
linux 安装 MySQLdb for python
查看>>
php扩展资源类
查看>>
Sublime Text 2 技巧
查看>>
使用fscanf()函数从磁盘文件读取格式化数据
查看>>
网站一些error_log报错
查看>>