Go语言的interface
1 定义
interface 类型可以定义一组方法,用来表示一个对象的行为特征。interface不能包含任何变量。接口是抽象的,是行为规范,不是实例。
package mainimport("fmt" )//接口规范两个方法 type Animal interface{Eat() Talk() }// 定义Dog结构体,并实现Animal接口中的所有方法 type Dog struct {}func (d *Dog) Eat() {fmt.Println("dog eating...") }func (d *Dog) Talk() {fmt.Println("dog talking...") }// 定义Cat结构体,并实现Animal接口中的所有方法 type Cat struct {}func (c *Cat) Eat() {fmt.Println("cat eating...") }func (c *Cat) Talk() {fmt.Println("cat talking...") }func main() {var a Animalvar d Dogd.Eat()a = &d //Dog实现了Animal中的所有方法,因此Animal实例可被Dog实例赋值a.Eat()var c Catc.Eat()a = &ca.Talk() }
注:interface是引用类型。
(1)go中的接口不需要显式的实现。只要一个对象实现了一个接口类型中的所有方法,那么这个对象就实现了这个接口。
(2)如果一个对象实现了多个interface类型的方法,那么这个对象就实现了多个接口。
(3)多态:一种事物的多种形态都可以按照统一的接口进行操作。
比如我们要统一对动物调用某个方法,都可以通过接口的多态性来做:
package mainimport("fmt" )//接口规范两个方法 type Animal interface{Eat() Talk() }// 定义Dog结构体,并实现Animal接口中的所有方法 type Dog struct {Name string }func (d *Dog) Eat() {fmt.Printf("%s is eating...\n", d.Name) }func (d *Dog) Talk() {fmt.Printf("%s is talking...\n", d.Name) }// 定义Cat结构体,并实现Animal接口中的所有方法 type Cat struct {Name string }func (c *Cat) Eat() {fmt.Printf("%s is eating...\n", c.Name) }func (c *Cat) Talk() {fmt.Printf("%s is talking...\n", c.Name) }func main() {var myAnimal []Animald1 := &Dog{Name:"阿黄",}myAnimal = append(myAnimal, d1)d2 := &Dog{Name:"旺财",}myAnimal = append(myAnimal, d2)c1 := &Cat{Name:"小七",}myAnimal = append(myAnimal, c1)for _, v := range myAnimal{v.Eat()}}
这段代码的输出结果是:
阿黄 is eating... 旺财 is eating... 小七 is eating...
这里我们可以和原生支持多态的Python对比一下,因为Python中声明变量的时候不需要声明其类型,原生支持多态,写起来确实很爽。
2 空接口
一个方法都没有的接口就是空接口:
interface {}
所有类型都实现了空接口,也就是任何类型都可以赋值给空接口。这有点像弱类型语言了。
package mainimport("fmt" )func main() {var a interface {}var b intb = 1000a = bfmt.Println(a) }
3 接口嵌套
形如:
type ReadWrite interface {Read(b Buffer) boolWrite(b Buffer) bool }type Lock interface {Lock()Unlock() }type File interface {ReadWriteLockClose() }
嵌套之后的File interface包含5个方法,若要实现这个接口需要实现这5个方法。
4 类型断言
如果我们要知道这个接口变量里面实际存储的是哪个类型的对象可以采用以下方法进行转换。
方法一:强制转换,如果失败,则挂掉
package mainimport ("fmt" )func typeRaise() {var t int = 100var x interface{}x = ty := x.(int) // 强制转换fmt.Println(y) }func main() {typeRaise() // 强制转换 }
方法二:先判断再转换(推荐)
package mainimport ("fmt" )func typeRaiseJustify() {var t int = 100var x interface{}x = ty, ok := x.(string) // 强制转换if !ok {fmt.Println("convert faild!\n")}fmt.Println(y) }func main() {typeRaiseJustify() //带判断类型转换 }
例子,获取变量类型:
package mainimport ("fmt" )func justify (items ...interface{}) {for i, v := range items {switch v.(type) {case bool:fmt.Printf("第%d个参数是bool\n", i)case int32:fmt.Printf("第%d个参数是int32\n", i)case string:fmt.Printf("第%d个参数是string\n", i)}} }func main() {var a int32var b stringvar c booljustify(a, b, c) }
判断一个变量是否实现了指定接口:
package mainimport("fmt" )//接口规范两个方法 type Animal interface{Eat() Talk() }// 定义Dog结构体,并实现Animal接口中的所有方法 type Dog struct {Name string }func (d *Dog) Eat() {fmt.Printf("%s is eating...\n", d.Name) }func (d *Dog) Talk() {fmt.Printf("%s is talking...\n", d.Name) }// 定义Cat结构体,并实现Animal接口中的所有方法 type Cat struct {Name string }func (c *Cat) Eat() {fmt.Printf("%s is eating...\n", c.Name) }func (c *Cat) Talk() {fmt.Printf("%s is talking...\n", c.Name) }func justify() {d := &Dog {Name:"BUCKER",}var v interface{} = dif dog, ok := v.(Animal); ok {dog.Eat()} }func main() {justify() }
5 实战:实现负载均衡接口
我们可以写一个具有随机、轮询算法的负载均衡接口。
package mainimport ("fmt""math/rand" )// [1]定义负载均衡接口,及方法 type LoadBalance interface {DoBalance ([]string) string }// [2] 定义随机算法结构体 RandBalance,并实现LoadBalance接口 type RandBalance struct {}func (r *RandBalance) DoBalance(addrList []string) string {// 此处省略判断ip是否是活的等业务逻辑l := len(addrList)index := rand.Intn(l)return addrList[index] }// [3] 定义轮询算法结构体 PollBalance,并实现LoadBalance接口 type PollBalance struct {curIndex int }func (p *PollBalance) DoBalance(addrList []string) string {// 此处省略判断ip是否是活的等业务逻辑index := p.curIndex % (len(addrList)) // 取余,防止index溢出addr := addrList[index]p.curIndex++return addr }// [4] 通过接口实现多态 func doBalance(balance LoadBalance, addrList []string) (addr string) {return balance.DoBalance(addrList) }func main() {// 随机生成IP地址切片var addrList []stringfor i:=0; i<5; i++ {addr := fmt.Sprintf("%d.%d.%d.%d:80", rand.Intn(255), rand.Intn(255), rand.Intn(255), rand.Intn(255))addrList = append(addrList, addr)}fmt.Println("addrList:", addrList)// 通过配置balanceFunc变量,调用不同的算法var balanceFunc string = "poll"var balance LoadBalanceif balanceFunc == "random" {balance = &RandBalance{}} else if balanceFunc == "poll" {balance = &PollBalance{}}// 10次调用负载均衡算法算出IPfor i:=0; i<10; i++ {addr := doBalance(balance, addrList)fmt.Printf("Index %d <--> Addr %s\n", i, addr)}}
生产环境中,可以将“random” /“poll”等存到K/V存储中,负载均衡代码定期读取K/V拿到值,实现负载均衡算法切换。
转载于:https://www.cnblogs.com/zingp/p/9267628.html
Go语言的interface相关推荐
- 12-Go语言接口interface
接口 在Go语言中接口(interface)是一种类型,一种抽象的类型.相较于之前章节讲到的那些具体类型,接口更注重"我能做什么的问题".接口类型就像是一种约定–概括了一种类型应具 ...
- Go语言-Go interface 接口的最佳实践
文章目录 Go语言-Go 接口的最佳实践 什么是Golang中的interface 编写接口的最佳实践 1. 保持interfaces足够小 2. Interfaces Should Have No ...
- 多重继承_Java语言编程第25讲——Java中多重继承,也会导致模棱两可的歧义
前面第23讲介绍Java语言通过interface实现多重继承,是一种很优雅的实现.即便是这样,也不能完全避免多重继承带来的歧义. 下面用一个很简单的例子来说明: 1.定义一个很简单的接口One,它只 ...
- 如何设计一门语言(三)——什么是坑(面向对象和异常处理)
在所有的文字之前,我需要强调一下,我本人对structure typing持反对态度,所以就算文中的内容"看起来很像"go的interface,读者们也最好不要觉得我是在赞扬go的 ...
- Go语言类库-reflect(反射)
概述 什么是反射? 反射是计算机程序在运行时可以访问,检查和修改本身状态或者行为的一种能力,大多数编程语言都支持反射.Go语言中,使用反射可以在程序执行过程中更新变量和检查对象的属性,调用对象的方法. ...
- java什么是网络接口_Java语言:什么叫面向接口编程(来自网络)
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的.在这种情况下,各个对象内部是如何实现自己的对系统设计人员来讲就不那么重要了:而各个对象之间的协作关系则成为系统设计的关键.小到不 ...
- Gox语言中的数组类型及其常用操作 - GX7.1
作为脚本语言,Gox语言中的复合类型当然会设计得更加方便一些,也很容易理解.由于Gox默认使用Qlang脚本引擎,Qlang中关于数组或者叫做切片(也就是Go语言中的slice,以后我们约定这两个称呼 ...
- System Verilog学习笔记—虚接口(virtual interface)
1.虚接口(virtual interface) 1.1为什么引入虚接口? 我们知道,通过引入interface可以简化模块儿之间的连接,即interface是连接硬件的,其是硬件语言:但对于验证来说 ...
- python有多态特性吗_Python:多态、协议和鸭子类型
多态 问起面向对象的三大特性,几乎每个人都能对答如流:封装.继承.多态.今天我们就要来说一说 Python 中的多态. 所谓多态:就是指一个类实例的相同方法在不同情形有不同表现形式.多态机制使具有不同 ...
最新文章
- python celery
- C++二叉树的建立与遍历
- 如何让 Hyper-V 和 VMware 虚拟机软件共存?
- 强化学习《基于价值 - Dueling Q-Learning》
- python cmdb_Django之入门 CMDB系统 (一) 基础环境
- 一次完整的http请求
- 正确的CentOS系统配置
- fastjson转换json格式数据为ListHashMap转换异常问题
- 基础教程之Spin旋转篇
- 二叉树的遍历_递归实现
- 短文本相似度比较:simHash简介以及java实现
- Visio 2003 精简版(简体中文,免激活)百度云链接
- 【Oracle】执行计划详解
- GCA matting(2020, trimap)
- linux下调试域格CLM920 NC5 pppd拨号
- 此nvidia驱动程序与此windows版本不兼容
- 微信小程序配置多环境
- Python class __int__容易理解
- SVN更新或提交时出现冲突该如何解决
- 记录JVM中Eden区、Survivor from区和Survivor to区及Minor GC和Major GC的理解
热门文章
- java c# 线程,DART隔离和线程(Java,C#)之间的区别
- idea ssm框架搭建详细步骤_搭建一套纯净版的SSM框架,随时CV使用它不香吗?
- mysql数据库隐式表_解析MySQL隐式转换问题
- SpringSecurity 流程图
- docker 镜像 增删改查
- nginx ngx_http_access_module
- 2.10 词嵌入除偏
- fiddler 页面介绍
- Matplolib subplot 子图控制
- java 类里面对象共享_Java并发编程 - 对象的共享