golang中的接口

Golang 中的接口是一种抽象数据类型,Golang 中接口定义了对象的行为规范,只定义规范 不实现。接口中定义的规范由具体的对象来实现,通俗的讲接口就一个标准,它是对一个对象的行为和规范进行约定,约定实现接口的对象必须得按照接口的规范

接口的定义

  • 在go中接口(interface)是一种类型,一种抽象的类型。接口(interface)是一组函数 method 的集合,Golang 中的接口不能包含任何变量。

  • 接口中的所有方法都没有方法体,接口定义了一个对象的行为规范,只定 义规范不实现。接口体现了程序设计的多态和高内聚低耦合的思想

  • 接口也是一种数据类型,不需要显示实现。只需要一个变量含有接口类型 中的所有方法,那么这个变量就实现了这个接口

  • 只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗

定义格式

每个接口由数个方法组成

/*
Geter:接口名,接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有字符串功能的接口叫 Stringer
interface:声明接口的关键字
*/
type Geter interface {
// 方法名 (参数类型) 返回值类型,没有则不写
// 方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包之外的代码访问
User(int) int
Head()
}

接口定义的方法,实现接口的对象必须全部实现,实现接口的对象可以有额外的方法,通过对象本身调用

package main

import "fmt"

// 定义一个usb接口
type Usber interface {
start()
stop()
} // 如果接口里面有方法,必现通过结构体或者自定义类型实现接口 // 定义一个手机结构体
type Phone struct {
Name string
} // 定义 phone 的start方法
func (p Phone) start() {
fmt.Printf("%v开机\n", p.Name)
} // 定义 phone 的stop方法
func (p Phone) stop() {
fmt.Printf("%v关机\n", p.Name)
}
接口使用
func main() {

	// 实例化Phone
phone := Phone{
Name: "苹果手机",
} // golang中接口就是一个数据类型,只是一个规范
// usb:接口对象
var usb Usber
usb = phone // phone实现usb接口
usb.start() // 苹果手机开机
usb.stop() // 苹果手机关机 }

空接口

Golang 中的接口可以不定义任何方法,没有定义任何方法的接口就是空接口。空接口表示

没有任何约束,因此任何类型变量都可以实现空接口,空接口在实际项目中用的是非常多的,用空接口可以表示任意数据类型

空接口定义
// 空接口
type A interface {
// 不定义任意方法
} func main() { var a A
var str = "golang"
a = str
fmt.Printf("%v %T \n", a, a) // golang string var num = 123
a = num
fmt.Printf("%v %T \n", a, a) // 123 int }
func main() {
// 空接口也可以当做类型使用,可以表示任意类型
var a interface{} a = 20
fmt.Printf("%v %T \n", a, a) // 20 int a = "123"
fmt.Printf("%v %T \n", a, a) // 123 string }
空接口当做函数参数
// 空接口当做函数参数,表示任意类型,传入int则是int,传入string则是string
func show(a interface{}) { }
值是空接口任意类型存储

使用空接口可以实现值保存任意类型

	// 空接口类型的值,可以实现任意类型
var m1 = make(map[string]interface{})
m1["name"] = "l"
m1["age"] = 1
fmt.Printf("%v", m1)
func main() {
// 值是任意类型
var aa = []interface{}{"lll", "qqq", true, 1}
fmt.Println(aa) }

类型断言

一个接口的值是由一个具体类型和具体类型的值两部分组成的,这两部分分别称为接口的动态类型和动态值

如果我们想要判断空接口中值的类型,那么这个时候就可以使用类型断言

断言语法
x.[T]

/*
x : 表示类型为 interface{}的变量 T : 表示断言 x 可能是的类型。 该语法返回两个参数,第一个参数是 x 转化为 T 类型后的变量,第二个值是一个布尔值,若为 true 则表示断言成功,为 false 则表示断言失败 */
func main() {
// 定义一个空接口
var a interface{} a = "golang" v, s := a.(string) // 判断a是不是一个string类型
fmt.Println(v, s) // golang true v1, s1 := a.(int) // 判断a是不是一个int类型
fmt.Println(v1, s1) // 0 false }
func Parser(x interface{}) {
if _, s := x.(string); s {
fmt.Printf("字符串") } else if _, s := x.(int); s {
fmt.Printf("int") } }
结合switch断言判断

类型.(type)只能结合 switch 语句使用

func Parser(x interface{}) {
// x.(type) 获取类型,供下方 case判断
switch x.(type) {
case int:
fmt.Printf("int")
case string:
fmt.Printf("string") default:
fmt.Printf("err") }
}
结构体接口断言
// 定义usb接口
type Usber interface {
start()
stop()
} // 定义Phone 结构体
type Phone struct {
Name string
} // 定义Phone 的方法
func (p Phone) start() {
fmt.Printf("%v开机", p.Name)
} // 定义Phone 的方法
func (p Phone) stop() {
fmt.Printf("%v关机", p.Name)
} // 定义一个方法,参数是usb接口类型
func Work(usb Usber) {
// 判断接口是不是Phone
if _, s := usb.(Phone); s {
fmt.Printf("Phone类型的接口")
} }

空接口和断言使用细节-解决空接口类型无法具体取值

type Address struct {
Name string
Phone int
} func main() { var userinfo = make(map[string]interface{})
userinfo["name"] = "li"
userinfo["age"] = 20
userinfo["hobby"] = []string{"吃饭", "睡觉"} /* 问题一
map的值是空接口可以是任意类型,hobby是一个切片,我们想取里面的值
我们通过该下标方法取值,会提示接口类型不支持索引
fmt.Println(userinfo["hobby"][1])
无效运算: 'userinfo["hobby"][1]' (类型 'interface{}' 不支持索引) */ /*
问题一解决
golang中 通过断言,我们可以获得两个值,一个是断言成功后原变量值,一个是true or false
通过断言hobby的类型是[]string,获取到bobby的值 赋值给v,再使用v通过下标取值
*/ v, _ := userinfo["hobby"].([]string)
fmt.Println(v[0]) // 吃饭 /* 问题二
如果值是一个结构体的话,可以获取到结构体的整体内容,无法获取单个的,无法.Name or 索引获取
*/
var address = Address{"李", 123123123}
userinfo["address"] = address
fmt.Printf("%v", userinfo["address"]) // {李 123123123}
// 问题二解决,逻辑和问题一一样
m, _ := userinfo["address"].(Address)
fmt.Println(m.Name) // 李 }

值接收者和指针接收者实现接口的区别

值接收者

如果结构体中的方法是值接收者,那么实例化后的结构体值类型和结构体指针类型都可以赋值给接口变量

// 定义usb接口
type Usber interface {
start()
stop()
} // 定义Phone 结构体
type Phone struct {
Name string
} // 定义Phone 的方法
func (p Phone) start() { // 值接收者
fmt.Printf("%v开机", p.Name)
} // 定义Phone 的方法
func (p Phone) stop() {
fmt.Printf("%v关机", p.Name)
} func main() {
/* 值接收者 */
// 实例化phone
var phone = Phone{"苹果"} // phone实现usb接口
var usb Usber = phone
usb.start() // 苹果开机 var phone1 = &Phone{"小米"}
var ubs1 Usber = phone1
ubs1.start() // 小米开机 }
指针接收者

如果结构体中的方法是指针接收者,那么实例化后结构体指针类型都可以赋值给接口变量, 结构体值类型没法赋值给接口变量

// 定义usb接口
type Usber interface {
start()
stop()
} // 定义Phone 结构体
type Phone struct {
Name string
} // 定义Phone 的方法
func (p *Phone) start() { // 指针接收者
fmt.Printf("%v开机", p.Name)
} // 定义Phone 的方法
func (p Phone) stop() {
fmt.Printf("%v关机", p.Name)
} func main() { /*
var phone = Phone{"苹果"}
var usb Usber = phone
会报错 结构体值类型没法赋值给接口变量 */ // 正确写法
var phone = &Phone{"苹果"}
var usb Usber = phone
usb.start() }

一个结构体实现多个接口

// 接口一
type Animaler1 interface {
SetName(string)
} // 接口二
type Animaler2 interface {
GetName() string
} type Dog struct {
Name string
} func (d *Dog) SetName(name string) {
d.Name = name } func (d Dog) GetName() string {
return d.Name } func main() { d := &Dog{"小黑"} var d1 Animaler1 = d // d实现Animaler1接口
var d2 Animaler2 = d // d实现Animaler2接口 d1.SetName("大黑")
fmt.Printf("%v", d2.GetName()) // 大黑
}

接口嵌套

接口与接口间可以通过嵌套创造出新的接口

// A接口
type Ainterface interface {
GetA()
} // B接口
type Binterface interface {
GetB()
} // 接口三
type Cinterface interface {
// 在接口C中嵌套接口A和B
Ainterface
Binterface
} // User结构体
type User struct {
Name string
} // 实现User方法A
func (u User) GetA() {
fmt.Println(1)
} // 实现User方法B
func (u User) GetB() {
fmt.Println(2)
} func main() {
/*
实现嵌套的接口,必现实现所嵌套的接口里所有接口的所有方法 */
var u = User{"li"}
var c Cinterface
c = u // u实现接口c
c.GetA()
c.GetB() }

golang中的接口(数据类型)的更多相关文章

  1. golang中的接口实现(一)

    golang中的接口实现 // 定义一个接口 type People interface { getAge() int // 定义抽象方法1 getName() string // 定义抽象方法2 } ...

  2. golang中的接口值

    package main import ( "bytes" "fmt" "io" ) // 此处的w参数默认是一个空接口,当传递进来buf参 ...

  3. golang中的接口实现(二)

    指针类型 vs 值类型实现接口 package main import ( "fmt" ) // 定义接口 type Describer interface { Describe( ...

  4. golang中的接口

    CSDN找的一个网页,照着抄练一次. 差不多的使用场景都在了. package main import ( "fmt" ) type People interface { Retu ...

  5. 七、golang中接口、反射

    一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...

  6. golang中接口interface和struct结构类的分析

    再golang中,我们要充分理解interface和struct这两种数据类型.为此,我们需要优先理解type的作用. type是golang语言中定义数据类型的唯一关键字.对于type中的匿名成员和 ...

  7. 六、golang中的结构体和方法、接口

    结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...

  8. Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现

    前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...

  9. 在golang中如何正确判断接口是否为nil

    本文主要来分析一下在golang中,如何判断interface是否为nil,以及相关注意事项. 正常情况下,我们声明一个interface类型的变量,默认值将会返回nil,以golang自带的io.W ...

  10. [.net 面向对象编程基础] (3) 基础中的基础——数据类型

    [.net 面向对象编程基础] (3) 基础中的基础——数据类型 关于数据类型,这是基础中的基础. 基础..基础..基础.基本功必须要扎实. 首先,从使用电脑开始,再到编程,电脑要存储数据,就要按类型 ...

随机推荐

  1. [转帖]资料整理——Oracle版本历史(很全面)(Releases and versions of Oracle Database)

    资料来源: https://en.wikipedia.org/wiki/Oracle_Database Oracle Database Version Initial Release Version ...

  2. [转帖]Linux 学习笔记: shell中${} 的用法,删除&替换

    Linux 学习笔记: shell中${} 的用法,删除&替换 字符串的删除 echo${i##*/} 删除 / 前的所有内容 ## 删除 tt=$i echo{tt:22} #取的22位以后 ...

  3. [转帖]总结:SpringBoot启动参数配置

    一.背景 由于项目中加了bootstrap.properties文件,且文件中有变量,如spring.cloud.config.profile=${spring.profiles.active},而b ...

  4. [转帖]【JVM】JVM源码分析之Metaspace解密

    概述 metaspace,顾名思义,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm,这块空间很有自己的特点,前段时间公司这块的问题太多了,主要是因为升级了中间件所致,看到 ...

  5. Linux运行服务的几种方式

    摘要 1. nohup & 2. screen 3. bg & disown 4. systemd 5. crontab @reboot 背景 最近一直在用linux 想着多总结一下. ...

  6. Springboot 数据库连接池大小简单总结

    最近在进行性能压测, 想验证一下产品的极限性能, 在使用openpower 2路22核(SMT4)176线程 512G内存的服务器上面进行性能压测 压测进行到1000并发或者是2000并发时性能有一定 ...

  7. K8S 使用loki 监控 应用日志的搭建办法

    1. 背景 这几天一直在用k8s部署分SU的测试环境,开发反馈看日志比较麻烦. 昨天晚上在家里本来想搭建ELK 发现比较重, 又说有一个比较轻量级的 loki 可以实现使用grafana进行监控和查看 ...

  8. 2024-01-27:用go语言,阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有N堆金币, 第i堆金币的总重量和总价值分别是m[i]、v[i], 阿里巴巴有一个承重量为T的背包,但并不一定有办法将全部的

    2024-01-27:用go语言,阿里巴巴走进了装满宝藏的藏宝洞.藏宝洞里面有N堆金币, 第i堆金币的总重量和总价值分别是m[i].v[i], 阿里巴巴有一个承重量为T的背包,但并不一定有办法将全部的 ...

  9. session未过期就丢失的原因以及处理方式

    转 https://blog.csdn.net/flamelp/article/details/5316725?utm_medium=distribute.pc_relevant.none-task- ...

  10. 加速tortoisegit的show log,减少等待时间

    KMSID: 81703 是否同步到KM: 是 是否原创: 是 标签: 游戏开发 允许复制: 是 允许评论: 是 允许导出PDF: 是 职业库分类KMS: 游戏-游戏程序 查看权限KMS:网易正式员工 ...