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. 如何打开 Visual Studio 的 Dump,适用于调试 appcrash,exception

    https://keithbabinec.com/2018/06/12/how-to-capture-and-debug-net-application-crash-dumps-in-windows/ ...

  2. Elasticsearch系列---实现分布式锁

    概要 Elasticsearch在文档更新时默认使用的是乐观锁方案,而Elasticsearch利用文档的一些create限制条件,也能达到悲观锁的效果,我们一起来看一看. 乐观锁与悲观锁 乐观锁 E ...

  3. Vue3.0新版API之composition-api入坑指南

    关于VUE3.0 由于vue3.0语法跟vue2.x的语法几乎是完全兼容的,本文主要介绍了如何使用composition-api,主要分以下几个方面来讲 使用vite体验vue3.0 composit ...

  4. Hexo博客插入图片的方法

    Hexo博客插入图片的方法 hexo图片blog hexo blog 插入图片的方法总结 hexo 的blog 内容是根据 markdown 文件的内容生成的html文件, 生成的文件全部在 /pub ...

  5. tcpdump常用抓包命令

    主要语法 过滤主机/IP: tcpdump -i eth1 host 172.16.7.206 抓取所有经过网卡1,目的IP为172.16.7.206的网络数据   过滤端口: tcpdump -i ...

  6. 【shell】Shell变量基础及深入

    1. 什么是变量 变量就是用一个固定的字符串(也可能是字符数字等的组合),替代更多更复杂的内容,这个内容里可能还会包含变量和路径,字符串等其他内容. 变量的定义是存在内存中. x=1 y=2 2. 变 ...

  7. 酷狗音乐快速转换MP3格式的方法

    喜欢听音乐的朋友们,散步跑步的时候都是随身听,音乐可以给人带来力量,让人心情愉悦,有时候甚至还可以让我们忘记烦恼和忧愁,是一种不错的解压方式,所以热爱运动的宝宝们是离不来音乐的陪伴的,这样说来随身听的 ...

  8. 怎么在Chrome和Firefox浏览器中清除HSTS设置?

    HSTS代表的是HTTPS严格传输安全协议,它是一个网络安全政策机制,能够强迫浏览器只通过安全的HTTPS连接(永远不能通过HTTP)与网站交互.这能够帮助防止协议降级攻击和cookie劫持. HST ...

  9. 删除集群mds

    2019独角兽企业重金招聘Python工程师标准>>> 删除cephfs文件系统步骤: 1.停掉服务端mds: #systemctl stop {mds_service} 2.将md ...

  10. 我的Android进阶之旅------> Android为TextView组件中显示的文本加入背景色

    通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...