7.1 Go interface

雨痕-Go语言笔记

接口采用了duck type方式,在程序设计中是动态类型的一种风格
`当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。` 空接口类型interface{},类似于OOP的system.Object,可以接收任意类型。
准备交互的双方,共同遵守实现约定的规则,使得无须知道对方身份的情况下进行协作。
接口要实现的是做什么,而不关心怎么做,谁来做。 可以先实现类型,而后再抽象出所需接口。称作非侵入式设计。

概念

Go语言的主要设计者之一罗布·派克(Rob Pike)曾经说过,如果只能选择一个Go语言的特 性移植到其他语言中,他会选择接口

接口在Go语言有着至关重要的地位。如果说goroutinechannel是支撑起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的更多相关文章

  1. angular2系列教程(七)Injectable、Promise、Interface、使用服务

    今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我 ...

  2. 接口--interface

    “interface”(接口)关键字使抽象的概念更深入了一层.我们可将其想象为一个“纯”抽象类.它允许创建者规定一个类的基本形式:方法名.自变量列表以及返回类型,但不规定方法主体.接口也包含了基本数据 ...

  3. 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 ...

  4. 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 ...

  5. 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 ...

  6. 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 ...

  7. 谨慎使用Marker Interface

    之所以写这篇文章,源自于组内的一些技术讨论.实际上,Effective Java的Item 37已经详细地讨论了Marker Interface.但是从整个Item的角度来看,其对于Marker In ...

  8. 浅析Go语言的Interface机制

    前几日一朋友在学GO,问了我一些interface机制的问题.试着解释发现自己也不是太清楚,所以今天下午特意查了资料和阅读GO的源码(基于go1.4),整理出了此文.如果有错误的地方还望指正. GO语 ...

  9. 如何设计一门语言(七)——闭包、lambda和interface

    人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...

  10. abstract与interface之房祖名张默版

    最近把java基础知识拿出来看看,看到abstract与interface的时候,觉得有点模糊,好像面试官也喜欢问这个问题.我在百度了查了好长时间,觉得讲算比较清楚的是那篇讲 Door,然后想要带个报 ...

随机推荐

  1. tp5中“前置操作”和“钩子函数”的区别

    1.实行顺序: 以下都是标为删除前的操作: 点击删除  ->  前置操作  ->  删除方法(用模型删除)  ->  触发钩子函数(删除)  ->  删除成功 2.传入的参数: ...

  2. docker commit理解构建镜像(7)

    镜像是多层存储,每一层是在前一层的基础上进行的修改: 而容器同样也是多层存储是在以镜像为基础层,在基础层上加一层作为容器运行时的存储层. 当我们使用Docker Hub的镜像无法满足我们的需求时,我们 ...

  3. jdbc批量插入数据

    //插入很多书(批量插入用法) public void insertBooks(List<Book> book) {   final List<Book> tempBook=b ...

  4. JavaScript HTMlL DOM对象(下)

    DOM:document operation model 文档操作模型 每个标签都是一个对象. 一.查找元素 DOM 回顾 直接查找 var obj = document.getElementById ...

  5. 基于 react 的Java web 应用—— 组件复用(后续需更新)

    前言 实习第二周,被告知要用React与导师进行基于React的Javaweb 的开发,jinzhangaaaaa~由于React 这款框架没学过,看了一峰老师的基础入门教程,硬着头皮开始上了... ...

  6. 简要理解CommonJS规范

    写在前面: 一个文件就是一个模块. 另外本文中的示例代码需要在node.js环境中方可正常运行,否则将出现错误.事实上ES6已经出现了模块规范,如果使用ES6的模块规范是无需node.js环境的.因此 ...

  7. 四、CentOS 6.5 上传和安装Nginx

    CentOS 6.5 上传和安装Nginx

  8. CF思维联系–CodeForces - 225C. Barcode(二路动态规划)

    ACM思维题训练集合 Desciption You've got an n × m pixel picture. Each pixel can be white or black. Your task ...

  9. P4168 蒲公英

    神仙分块,把减写成加调了半小时.. 不过这题也启示我们其实有的分块题要把多个块的信息拿到一起维护 以前做的都是每个块的信息单独维护 写的分块题还不太多,同时维护一个块的左右边界好像有点冗余,不过这样代 ...

  10. postman(介绍)

    Postman 界面介绍 一. 安装后首次打开 postman,会提示你是否需要登录,登录的话可以云端保存你的收藏及历史记录,不登陆不影响使用.   二. 进入后就是如下图所示的界面了.看到这么多按钮 ...