7.1 Go interface
7.1 Go interface
雨痕-Go语言笔记
接口采用了duck type方式,在程序设计中是动态类型的一种风格
`当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。` 空接口类型interface{},类似于OOP的system.Object,可以接收任意类型。
准备交互的双方,共同遵守实现约定的规则,使得无须知道对方身份的情况下进行协作。
接口要实现的是做什么,而不关心怎么做,谁来做。 可以先实现类型,而后再抽象出所需接口。称作非侵入式设计。
概念
Go语言的主要设计者之一罗布·派克(Rob Pike)曾经说过,如果只能选择一个Go语言的特 性移植到其他语言中,他会选择接口
。
接口在Go语言有着至关重要的地位。如果说goroutine
和channel
是支撑起Go语言的并发模型
的基石,让Go语言在如今集群化
与多核化
的时代成为一道极为亮丽的风景,那么接口
是Go语言 整个类型系统
的基石,让Go语言在基础编程哲学的探索上达到前所未有的高度。
Go语言在编程哲学上是变革派,而不是改良派。这不是因为Go语言有goroutine和channel, 而更重要的是因为Go语言的类型系统,更是因为Go语言的接口
。Go语言的编程哲学因为有接口
而趋近完美。
接口只有方法声明,没有实现,也没有数据字段。
接口可以匿名嵌入到其他接口。
对象赋值给接口时,会发生拷贝。
只有当接口存储的类型和对象都是nil时,接口等于nil。
空接口可以接收任意的数据类型。
一个类型可以实现多个接口。
接口变量名习惯以 er 结尾。
接口类型是对其它类型行为的抽象和概括,接口类型不会和特定的实现细节绑定。
Go接口独特在它是隐式实现的,这是指:一个结构体只要实现了接口要求的所有方法,我们就说这个结构体实现了该接口。
接口
在现实世界也是有真实场景的,如同笔记本上都有USB插口,且不用担心这个插槽是为手机
、U盘
、平板
哪一个准备的,因为笔记本的usb插槽和各种设备的厂家统一了USB的插槽规范。
1.2. 接口语法
type 接口名 interface {
method1(参数列表)返回值列表
method2(参数列表)返回值列表
} interface类型可以定义一组方法,且不需要实现这些方法!并且interface不能有任何变量。
只要有一个变量类型,含有接口中的所有方法,就说这个变量类型实现了这个接口。
Go多态与接口
package main import "fmt" //定义一个Usb接口,且定义Usb功能方法
type Usb interface {
Start()
Stop()
} type Phone struct {
Name string
Price int
} //让手机Phone实现Usb接口的方法
func (p Phone) Start() {
fmt.Println("手机已连接USB,开始工作")
} //必须实现接口所有的方法,少一个都报错 如下:Phone does not implement Usb (missing Stop method)
func (p Phone) Stop() {
fmt.Println("手机断开了USB,停止工作")
} type IPad struct {
Name string
Price int
} func (p IPad) Start() {
fmt.Println("ipad已经连接USB,开始工作")
} func (p IPad) Stop() {
fmt.Println("ipad断开了USB,停止工作")
} //定义一个电脑结构体,这个结构体可以实现usb的接口
type Computer struct {
} //定义working方法,接收Usb接口类型变量
//实现Usb接口声明的所有方法
//这是一个多态的函数,调用同一个Working函数,不同的执行结果
func (mbp Computer) Working(usb Usb) {
//不同的usb实参,实现不同的功能
//只要实现了usb接口的数据类型,那么这个类型的变量,就可以给usb接口变量赋值
usb.Start()
usb.Stop()
} func main() {
//分别创建结构体对象
c := Computer{}
p := Phone{"苹果手机", 6999}
i := IPad{"华为平板", 7999} //
//手机连接笔记本,插上手机
c.Working(p)
fmt.Printf("名字:%v 价格:%d\n", p.Name, p.Price) fmt.Println("------------------")
//平板连接笔记本,插上平板
c.Working(i)
fmt.Printf("名字:%v 价格:%d\n", i.Name, i.Price)
}
接口实例2
package main import "fmt" //员工接口
type Employer interface {
CalcSalary() float32
} //开发者
type Programer struct {
name string
base float32
extra float32
} //创建开发者实例
func NewProgramer(name string, base float32, extra float32) Programer {
return Programer{
name,
base,
extra,
}
} //计算开发者工资,实现了CalcSalary方法
func (p Programer) CalcSalary() float32 {
return p.base
} //销售群体
type Sale struct {
name string
base float32
extra float32
} //创建销售实例
func NewSale(name string, base float32, extra float32) Sale {
return Sale{
name,
base,
extra,
}
} //实现了CalcSalary方法
func (p Sale) CalcSalary() float32 {
return p.base + p.extra*p.base*0.5
} //计算所有人的工资接收参数,接口切片
func calcAll(e []Employer) float32 {
/*
fmt.Println(e)
[{码云 50000 0} {刘抢东 40000 0} {麻花藤 30000 0} {格格 3000 2.5} {小雪 1800 2.5} {小雨 2000 2.5}]
*/
var cost float32
//忽略索引,v是每一个结构体
for _, v := range e {
cost = cost + v.CalcSalary()
}
return cost
}
func main() {
p1 := NewProgramer("码云", 50000.0, 0)
p2 := NewProgramer("刘抢东", 40000, 0)
p3 := NewProgramer("麻花藤", 30000, 0) s1 := NewSale("格格", 3000, 2.5)
s2 := NewSale("小雪", 1800, 2.5)
s3 := NewSale("小雨", 2000, 2.5) var employList []Employer
employList = append(employList, p1)
employList = append(employList, p2)
employList = append(employList, p3)
employList = append(employList, s1)
employList = append(employList, s2)
employList = append(employList, s3) cost := calcAll(employList)
fmt.Printf("这个月人力成本:%f\n", cost)
}
1.3. Go接口细节
1.接口本身不能创建实例,但是可以指向一个实现了该接口的变量实例,如结构体
2.接口中所有方法都没有方法体,是没有实现的方法
3.Go中不仅是struct可以实现接口,自定义类型也可以实现接口,如type myInt int 自定义类型
4.一个自定义类型,只有实现了某个接口,才可以将自定义类型的实例变量,赋给接口类型,否则报错missing xx method
5.一个自定义类型,可以实现多个接口(实现多个接口的所有方法)
6.接口类型不得写入任何变量 如
type Usb interface{
method1()
method2()
Name string //错误,编译器不通过
}
7.接口A可以继承多个别的接口B、接口C,想要实现A,也必须实现B、C所有方法,称作接口组合
8.interface类型,默认是指针(引用类型),如果没初始直接使用,输出nil,可以赋给实现了接口的变量
9.空接口interface{},没有任何类型,也就是实现了任何类型,可以吧任何一个变量赋给空接口
10.匿名组合的接口,不可以有同名方法,否则报错duplicate method
1.3.1. 空接口
package main import "fmt" type A interface {
} type Cat struct {
name string
age int
} type Person struct {
name string
sex string
} //参数类型是接口类型,可以接收任意类型数据
func test1(a A) {
fmt.Println(a) } //
func test2(a interface{}) {
fmt.Println(a) } //数组元素是接口,可以存放任意不同的数据类型,输出不同类型
func test3(slice2 []interface{}) { for i := 0; i < len(slice2); i++ {
//数组中元素类型不同,通过接口的类型断言判断
switch ins := slice2[i].(type) {
case Cat:
fmt.Println("\t传入cat对象:", ins.name, ins.age)
case Person:
fmt.Println("\t传入person对象:", ins.name, ins.sex)
case int:
fmt.Println("\t传入了int类型:", ins)
case string:
fmt.Print("\t传入了string类型:", ins)
}
}
} func main() {
a1:=Cat{"花花",1}
p1:=Person{"锐萌萌","女性"}
i1:=123
s1:="峡谷之巅,最强王者" test1(a1)
test2(p1)
//test3接收切片类型
//初始化一个切片s1
slice1:=[]interface{}{}
fmt.Println(slice1,len(slice1),cap(slice1))
fmt.Println("你好") slice1=append(slice1,a1,p1,i1,s1)
fmt.Println(slice1) //传入切片
test3(slice1)
}
7.1 Go interface的更多相关文章
- angular2系列教程(七)Injectable、Promise、Interface、使用服务
今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我 ...
- 接口--interface
“interface”(接口)关键字使抽象的概念更深入了一层.我们可将其想象为一个“纯”抽象类.它允许创建者规定一个类的基本形式:方法名.自变量列表以及返回类型,但不规定方法主体.接口也包含了基本数据 ...
- Configure a bridge interface over a VLAN tagged bonded interface
SOLUTION VERIFIED February 5 2014 KB340153 Environment Red Hat Enterprise Linux 6 (All Versions) Red ...
- Create a bridge using a tagged vlan (8021.q) interface
SOLUTION VERIFIED April 27 2013 KB26727 Environment Red Hat Enterprise Linux 5 Red Hat Enterprise Li ...
- Configure a bridged network interface for KVM using RHEL 5.4 or later?
environment Red Hat Enterprise Linux 5.4 or later Red Hat Enterprise Linux 6.0 or later KVM virtual ...
- Set up VLAN (802.1q) tagging on a network interface?
SOLUTION VERIFIED October 13 2015 KB39674 KB741413 environment Red Hat Enterprise Linux 4 Red Hat En ...
- 谨慎使用Marker Interface
之所以写这篇文章,源自于组内的一些技术讨论.实际上,Effective Java的Item 37已经详细地讨论了Marker Interface.但是从整个Item的角度来看,其对于Marker In ...
- 浅析Go语言的Interface机制
前几日一朋友在学GO,问了我一些interface机制的问题.试着解释发现自己也不是太清楚,所以今天下午特意查了资料和阅读GO的源码(基于go1.4),整理出了此文.如果有错误的地方还望指正. GO语 ...
- 如何设计一门语言(七)——闭包、lambda和interface
人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...
- abstract与interface之房祖名张默版
最近把java基础知识拿出来看看,看到abstract与interface的时候,觉得有点模糊,好像面试官也喜欢问这个问题.我在百度了查了好长时间,觉得讲算比较清楚的是那篇讲 Door,然后想要带个报 ...
随机推荐
- thinkphp5--多文件入口设置
来源:http://www.cnblogs.com/walblog/p/8035426.html 今天在用tp5做项目的时候发现,前台是可以绑定默认到index模块的,但是后台不好弄,于是查了一下手册 ...
- ps 和 top
ps 进程和线程的关系: (1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程. (2)资源分配给进程,同一进程的所有线程共享该进程的所有资源. (3)处理机分给线程,即真正在处 ...
- mac OS nvm 常用命令
nvm install stable ## 安装最新稳定版 node,当前是node v10.15.0 (npm v6.4.1) nvm install <version> ## 安装指定 ...
- 无向图双连通分量BCC(全网最好理解)
不是标题党,之前我也写过一篇比较全的,但是对于初学者不友好.传送门? 双连通分量(Biconnected component): 1.边双联通 E-BCC 2.点双连通 V-BCC 双 ...
- RF(页面断言)
一.RF中断言方式 title should be(断言title与预期指定的title内容相等) Open Browser https://www.baidu.com/ gc Title Shoul ...
- 在html中使用vue组件
最近在维护公司的项目,当我拿到项目时,发现他用了vue. 但是~~仅仅是引用vue.js文件,整体的架构还是html那种,没有用webpack! 当时觉得~哇~原来还可以这样! 然后了解了业务逻辑和代 ...
- windows远程执行命令总结
1. 利用Impacket Impacket是一个Python类库,用于对SMB1-3或IPv4 / IPv6 上的TCP.UDP.ICMP.IGMP,ARP,IPv4,IPv6,SMB,MSRPC, ...
- CSS3.16
<style>#back-top { position: fixed; bottom: 10px; right: 5px; z-index: 99;}#back-top span { wi ...
- [E. Ehab's REAL Number Theory Problem](https://codeforces.com/contest/1325/problem/E) 数论+图论 求最小环
E. Ehab's REAL Number Theory Problem 数论+图论 求最小环 题目大意: 给你一个n大小的数列,数列里的每一个元素满足以下要求: 数据范围是:\(1<=a_i& ...
- JAVA设计模式之工厂系列(factory)
任何可以产生对象的方法或者类,都可以称之为工厂.单例就是所谓的静态工厂. 为什么jdk中有了new,还需要工厂呢? a.灵活的控制生产过程 b.给对象加修饰.或者给对象加访问权限,或者能够在对象生产过 ...