首页 > 其他分享 >golang中的接口(数据类型)

golang中的接口(数据类型)

时间:2024-02-22 19:04:10浏览次数:27  
标签:string fmt 数据类型 接口 golang Phone func interface

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()

}

image

标签:string,fmt,数据类型,接口,golang,Phone,func,interface
From: https://www.cnblogs.com/Mickey-7/p/18027942

相关文章

  • golang中的类型断言,解释.(float64)和.(string)
    在Go语言中,. 后跟括号中的类型名称(如 .(float64) 或 .(string))通常出现在类型断言(typeassertion)的上下文中。类型断言用于检查一个空接口(interface{})值是否包含特定的类型,如果是,则将其转换为该类型。类型断言的语法如下:value,ok:=x.(T)其中 x 是一个 interface{}......
  • 29.Jenkins Api 接口
    JenkinsApi简介Jenkins对外暴露的动作交付入口为外部程序提供入口,可以控制Jenkins支持协议-HttpApi接口支持用户名、密码认证JenkinsApi支持的典型功能:运行Job、查看任务状态、返回任务编号…等JenkinsApi环境准备使用curl调用获取所有Jobs接口创建一......
  • QT使用OpenSSL的接口实现RSA2的签名和验签
    QT使用OpenSSL的接口实现RSA2的签名和验签加密和签名在RSA加密算法中是两个不同的概念,虽然它们都涉及RSA密钥对的使用,但目的和应用场景有所不同。加密(encrypt/decrypt):加密:使用接收方的公钥对数据进行加密,只有拥有相应私钥的接收方才能解密数据。解密:使用接收方的私钥对......
  • 请求第三方接口
      请求钉钉varobj="";vartoken=AccessToken();if(string.IsNullOrWhiteSpace(token)){returnfalse;}varclient=newRestClient($"https://api.dingtalk.com/v1.0/workflow/processInstances?processInstanceId={processInstanceId}&quo......
  • Golang Gorm 的标签tag
    当使用GORM进行数据库模型映射时,可以使用多种标签来定义字段的行为。以下是一些常用的GORM标签:gorm:"primary_key":定义字段作为模型的主键。gorm:"column:<column_name>":指定字段在数据库表中的列名。gorm:"type:<data_type>":指定字段的数据库数据类型。gorm:"......
  • Python数据类型中bytes 与 bytearray
    在Python中,我们可以使用bytes和bytearray两种数据类型来处理二进制数据。bytes是一个不可变的序列类型,而bytearray是一个可变的序列类型。本文将介绍如何使用Python来创建、操作和转换bytes和bytearray。bytes:可以看作是一组二进制数值(0-255)的str序列bytearray:可以看......
  • 从C#接口的属性获取多个实现类中字段的值
    privateList<string>GetImplName(){List<string>ls=newList<string>();vartypes=AppDomain.CurrentDomain.GetAssemblies().SelectMany(a=>a.GetTypes().Where(t=>......
  • golang 读取excel 保存xml
    1、首先下载第三方excel读取库gogetgithub.com/xuri/excelize/v22、读取xml库,未使用默认xml库 gogetgithub.com/beevik/etreepackagemainimport( "fmt" "github.com/beevik/etree" "github.com/xuri/excelize/v2")funcLoadExcelAndSaveXML(){ ......
  • 【JAVA】函数式接口示例
     Java的函数式接口提供了更简洁和声明性的方式来处理数据。以下是一些使用Predicate<T>、Function<T,R>、Consumer<T>和Supplier<T>的代码示例 Predicate(谓词语句)importjava.util.function.Predicate;publicclassPredicateExample{publicstaticvoidmain(Str......
  • golang 包&go mod
    gomod初始化项目gomodinit项目开发中首先要在项目目录中用gomod命令生成一个go.mod文件管理项目的依赖自定义包自定义包://自定义包一定要放在第一行packagecalc/*定义的方法、变量、结构体等首字母大写表示公有方法,其他包中可以引入该方法首字母小......