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. thinkphp5--多文件入口设置

    来源:http://www.cnblogs.com/walblog/p/8035426.html 今天在用tp5做项目的时候发现,前台是可以绑定默认到index模块的,但是后台不好弄,于是查了一下手册 ...

  2. ps 和 top

    ps 进程和线程的关系: (1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程. (2)资源分配给进程,同一进程的所有线程共享该进程的所有资源. (3)处理机分给线程,即真正在处 ...

  3. mac OS nvm 常用命令

    nvm install stable ## 安装最新稳定版 node,当前是node v10.15.0 (npm v6.4.1) nvm install <version> ## 安装指定 ...

  4. 无向图双连通分量BCC(全网最好理解)

    不是标题党,之前我也写过一篇比较全的,但是对于初学者不友好.传送门? 双连通分量(Biconnected component):     1.边双联通 E-BCC     2.点双连通 V-BCC 双 ...

  5. RF(页面断言)

    一.RF中断言方式 title should be(断言title与预期指定的title内容相等) Open Browser https://www.baidu.com/ gc Title Shoul ...

  6. 在html中使用vue组件

    最近在维护公司的项目,当我拿到项目时,发现他用了vue. 但是~~仅仅是引用vue.js文件,整体的架构还是html那种,没有用webpack! 当时觉得~哇~原来还可以这样! 然后了解了业务逻辑和代 ...

  7. windows远程执行命令总结

    1. 利用Impacket Impacket是一个Python类库,用于对SMB1-3或IPv4 / IPv6 上的TCP.UDP.ICMP.IGMP,ARP,IPv4,IPv6,SMB,MSRPC, ...

  8. CSS3.16

    <style>#back-top { position: fixed; bottom: 10px; right: 5px; z-index: 99;}#back-top span { wi ...

  9. [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& ...

  10. JAVA设计模式之工厂系列(factory)

    任何可以产生对象的方法或者类,都可以称之为工厂.单例就是所谓的静态工厂. 为什么jdk中有了new,还需要工厂呢? a.灵活的控制生产过程 b.给对象加修饰.或者给对象加访问权限,或者能够在对象生产过 ...