golang中的接口(数据类型)
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中的接口(数据类型)的更多相关文章
- golang中的接口实现(一)
golang中的接口实现 // 定义一个接口 type People interface { getAge() int // 定义抽象方法1 getName() string // 定义抽象方法2 } ...
- golang中的接口值
package main import ( "bytes" "fmt" "io" ) // 此处的w参数默认是一个空接口,当传递进来buf参 ...
- golang中的接口实现(二)
指针类型 vs 值类型实现接口 package main import ( "fmt" ) // 定义接口 type Describer interface { Describe( ...
- golang中的接口
CSDN找的一个网页,照着抄练一次. 差不多的使用场景都在了. package main import ( "fmt" ) type People interface { Retu ...
- 七、golang中接口、反射
一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...
- golang中接口interface和struct结构类的分析
再golang中,我们要充分理解interface和struct这两种数据类型.为此,我们需要优先理解type的作用. type是golang语言中定义数据类型的唯一关键字.对于type中的匿名成员和 ...
- 六、golang中的结构体和方法、接口
结构体: 1.用来自定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分 4.strucr类型是值类型 5.struct类型可以嵌套 6. ...
- Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现
前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...
- 在golang中如何正确判断接口是否为nil
本文主要来分析一下在golang中,如何判断interface是否为nil,以及相关注意事项. 正常情况下,我们声明一个interface类型的变量,默认值将会返回nil,以golang自带的io.W ...
- [.net 面向对象编程基础] (3) 基础中的基础——数据类型
[.net 面向对象编程基础] (3) 基础中的基础——数据类型 关于数据类型,这是基础中的基础. 基础..基础..基础.基本功必须要扎实. 首先,从使用电脑开始,再到编程,电脑要存储数据,就要按类型 ...
随机推荐
- [转帖]oracle通过pid查找执行SQL
通过TOP 命令查看PID:1560 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1560 oracle 20 0 38.978g 0. ...
- 【转帖】10个Linux 系统性能监控命令行工具
引言: 系统一旦跑起来,我们就希望它能够稳定运行,不要宕机,不出现速度变慢.因此,对于Linux 系统管理员来说每天监控和调试 Linux 系统的性能问题是一项繁重却又重要的工作.监控和保持系统启动并 ...
- ARM 平台Docker运行RabbitMQ 以及迁移的简单办法
公司网络很垃圾. 可以使用vps 进行下载和打包 放到 公司的机器上面进行使用. 1. 搜索有没有可用的镜像. [root@JNXLH ~]# docker search rabbitmq |gre ...
- K8S 使用loki 监控 应用日志的搭建办法
1. 背景 这几天一直在用k8s部署分SU的测试环境,开发反馈看日志比较麻烦. 昨天晚上在家里本来想搭建ELK 发现比较重, 又说有一个比较轻量级的 loki 可以实现使用grafana进行监控和查看 ...
- [Python] 基于RapidFuzz库实现字符串模糊匹配
RapidFuzz是一个用于快速字符串模糊匹配的Python库,它能够快速计算两个字符串之间的相似度,并提供与Fuzzywuzzy(已停用)和TheFuzz(Fuzzywuzzy的升级版)类似的接口. ...
- 【k哥爬虫普法】简历大数据公司被查封,个人隐私是红线!
我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...
- 【JS 逆向百例】有道翻译接口参数逆向
逆向目标 目标:有道翻译接口参数 主页:https://fanyi.youdao.com/ 接口:https://fanyi.youdao.com/translate_o?smartresult=di ...
- Fabric网络升级(二)
原文来自这里. 如果想了解最新版Fabric的特殊事项,详见Upgrading to the latest release of Fabric. 本章只介绍更新Fabric组件的操作.关于如何通过编辑 ...
- 手撕Vue-Router-实现router-view
前言 在上一篇 [手撕Vue-Router-实现router-link] 中,我们实现了 router-link 组件,这一篇我们来实现 router-view 组件. 实现思路 router-vie ...
- 搜索推荐DeepFM算法详解:算法原理、代码实现、比赛实战
搜索推荐DeepFM算法详解:算法原理.代码实现.比赛实战 可以说,DeepFM 是目前最受欢迎的 CTR 预估模型之一,不仅是在交流群中被大家提及最多的,同时也是在面试中最多被提及的: 1.Deep ...