永远不要高估自己
接口(interface)是一种类型!!
1.接口是一种类型,使用关键字type
与interface
进行定义
2.接口类型只定义方法
,不关心数据
3.通俗地讲接口类型定义了规则
,不关心规则
的实现
接口的定义格式
type 接口类型名 interface { 方法名1(参数列表1) 返回值列表1 方法名2(参数列表2) 返回值列表2 ...}
接口类型名:从type
关键字可以看出接口就是类型的一种,接口类型名称就是给接口去哟个名字。接口类型命名规则一般会在单词的后面添加 er,比如说写 *** 作的接口名称名义为 Writer,字符串接口叫做 Stringer
,接口类型的名称最好能体现接口的含义!方法名:当方法名称首字母大写并且接口类型名称首字母也是大写,这个方法可以被接口所在包之外的代码使用参数列表、返回值列表:可以省略举个栗子:
type Writer interface( Write([]byte) error)
所见即所得,看见接口类型名称与方法名称大概能猜出,这个接口的功能!
4.实现接口的条件接口类型就是一个需要实现的方法列表
,一个结构体示例实现了接口中的所有方法,那么就实现了这个接口类型
1.我们定义一个Caller
接口:
// Caller 接口类型type Caller interface { call()}
2.定义Dog
与 Cat
两个结构体:
type Dog struct{}type Cat struct{}
3.因为Caller
接口里面有一个call
方法,所以我们需要给Dog
与Cat
两个结构体分别实现Call
方法
// Dog 实现了Caller接口类型func (d Dog) call(){ fmt.Println("汪汪汪...")}// Cat 实现了Caller接口类型func (c Cat) call(){ fmt.Println("喵喵喵...")}
接口的实现即时这么简单,只要实现了接口中的所有方法,就实现了这个接口
5.接口类型变量接口类型变量能够存储所有实现了该接口的实例。
列如上面的例子中,Dog
与Cat
的实例实现了,接口Caller
中的call
方法,那么定义一个Caller类型的变量就可以存储Dog与Cat的实例。
func main(){ var x Caller // 声明一个Caller类型的变量x c := Cat{} // 实例化Cat d := Dog{} // 实例化Dog x = c // 可以吧cat的实例赋值给x x.call() // 喵喵喵 x = d // 可以吧dog的实例赋值给x x.call() // 汪汪汪}
观察下列代码,感受_
的妙用
// 摘自gin框架routergroup.gotype IRouter interface{ ... }type RouterGroup struct { ... }var _ IRouter = &RouterGroup{} // 确保RouterGroup实现了接口IRouter
6.值接受者与指针接受者实现接口的区别定义一个Mover
接口类型与一个dog
结构体
type Mover interface { move()}type cat struct{}
6.1 值类型接受者实现接口func (c cat) move(){ fmt.Println("猫动起来了")}
此时实现接口类型的是cat
类型
func main(){ var x Mover var Tom = cat{} //Tom是cat类型 x = Tom // x可以接受cat类型 var jialaolian = &cat{} // jiaolaolian是*cat类型 x = jialaolian // x 可以接受*cat类型 x.move()}
6.2 指针接受者实现接口从代码可以看出,使用值接受者实现接口之后,不管是cat结构体还是结构体指针*cat类型的变量都可以赋值给该接口变量
同样的代码我们再来测试一下使用指针接受者有什么区别
func (c *cat) move(){ fmt.Println("猫动起来了")}func main(){ var x Mover var Tom = cat{} // Tom是cat类型 x = Tom // x接收cat类型报错 var jialaolian = &cat{} x = jialaolian // x可以接受*cat类型}
此时实现Mover接口类型是*cat
类型,所以不能给x传入cat类型的Tom,此时x只能传入*cat
类型的值
一个结构体类型可以同时实现多个接口类型,并且接口类型之间互相独立。
举个栗子:猫可以叫,也可以动,我们可以分别定义Caller
与Mover
接口
type Caller interface{ call()}type Mover interface { move()}
cat 即实现了Caller接口,也实现了Mover接口
type cat struct { name string}func (c cat) call() { fmt.Println("喵喵喵")}func (c cat)move() { fmt.println("动起来")}func main(){ var x Caller var y Mover var c1 = cat(name:Tom) x = c1 y = c1 x.call() x.move()}
7.2 多个结构体类型实现同一接口类型。。。
8 接口类型嵌套接口与接口之前可以通过嵌套创造出新的接口
// Caller 接口type Caller interface { call()}// Mover 接口type Mover interface { move()}//接口嵌套type Animal interface { Caller Mover}
嵌套得到的接口使用与普通接口一样
type cat struct { name string}func (c cat) call(){ fmt.Println("喵喵喵")}func (c cat)move(){ fmt.Println("动起来")}func main(){ var x Animal x = cat{name:"Tom"} x.move() x.call()}
9 空接口9.1 空接口的定义空接口是指没有定义任何方法的接口,因此任何类型都实现了空接口
空接口的变量,可以存储任意类型的变量
package mainimport "fmt"func main() { var x interface{} s := "你好啊" x = s fmt.Printf("type:%T value:%v\n", x, x) i := 100 x = i fmt.Printf("type:%T value:%v\n", x, x) b := true x = b fmt.Printf("type:%T value:%v\n", x, x)}`type:string value:你好啊type:int value:100type:bool value:true``
9.2 空接口的应用9.2.1 空接口作为函数的参数使用空接口类型可以接受任意类型的参数
// 空接口作为函数形参func show(a interface{}){ fmt.Printf("type:%T value:%v",a,a)}
9.2.2 空接口作为map的值使用空接口,实现可以保存任意值得字典
// 空接口作为map的值var studentInfo = make(map[string]interface{})studentInfo["name"] = "sss"studentInfo["age"] = 18studentInfo["gender"] = truefmt.Println(studentInfo)
10 类型断言空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?
10.1 接口值一个接口的值(简称接口值)是由一个具体类型
与具体类型的值
两部分组成。
这两部分分别称之为接口的动态类型
和动态值
类型断言格式
x.(T)
x:表示类型为interface{}
的变量T:表示x可能的类型举个栗子:
func main() { var x interface{} x = "Hello 沙河" v, ok := x.(string) if ok { fmt.Println(v) } else { fmt.Println("类型断言失败") }}
上面的示例中如果要断言多次就需要写多个if判断,这个时候我们可以使用switch语句来实现:
func justifyType(x interface{}) { switch v := x.(type) { case string: fmt.Printf("x is a string,value is %v\n", v) case int: fmt.Printf("x is a int is %v\n", v) case bool: fmt.Printf("x is a bool is %v\n", v) default: fmt.Println("unsupport type!") }}
因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。
关于接口需要注意的是,只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗。
总结以上是内存溢出为你收集整理的12.Go语言干货-接口类型全部内容,希望文章能够帮你解决12.Go语言干货-接口类型所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)