go语言接口

接口( interface)

接口是一种抽象的数据类型

1. 声明接口

接口本身是调用方和实现方均需要遵守的一种协议,接口是一种抽象的数据类型,不会暴露所含数据的格式、类型及结构。

接口声明的格式

type 接口类型名工 interface{
    方法名1(参数) 返回值列表1
    方法名2(参数) 返回值列表2
    ...
   }
  //Go语言在命名 时, 一般会在单词后面添 er ,

2. 实现接口的条件

2.1 接口的方法与实现接口的类型方法格式一致
(1)函数名不一致导致的报错
(2)实现接口的方法签名不一致导致的报错,签名包括方法中的名称、 参数数列表、返回参数列表。

2.2 接口中所有方法均被实现
当一个接口中有多个方法时,只有这些方法都被实现了,接口才能被正确编译并使用。

3. 理解类型与接口的关系

3.1 一个类型可以实现多个接口

一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现。
定义一个Socket类型的数据结构,定义两个方法用于数据的写入和资源的释放,用两个接口抽象的描述两个方法,他们的关系如图所示:
在这里插入图片描述
usingWriter() usingCloser()完全独立的 ,互相不知道对方存在,也不知道自己使用的 接口是 Socket实现现的。

3.2 多个类型可以实现相同的接口

package main

import (
	"fmt"
)

// Service 接口定义了两个方法个是开启服务的方法( Start()), 个是输出日志的方法( Log())

type Service interface {
	Start() error
	Log(data string)
}

// 日志器
type Logger struct {
}

func (log Logger) Log(data string) {
	fmt.Println(data)
}

// 游戏服务
type GameService struct {
	Logger // 嵌入日志器
}

func (game GameService) Start() error {
	return nil
}

func main() {
	game := new(GameService)
	game.Start()
	game.Log("启动成功")
}

game就可以使用 Start()方法和 Log()方法,其中, Start()GameService 实现, Log()方法由Logger 实现。

4。接口查询

接口查询(Interface Type Assertion)是一种用于检查接口值底层类型的机制,以及如何将接口值转换为底层类型的过程。在Go中,可以使用接口查询来判断接口值是否包含特定类型的值,并将其转换为该类型。接口查询有两种形式:类型断言和类型判断。下面是它们的详细解释:

4.1 类型断言
      类型断言允许你将接口值转换为具体的类型,前提是接口值确实包含了该类型的值。如果接口值不包含指定类型的值,类型断言将导致运行时恐慌(panic)。使用类型断言的语法如下:

value, ok := myInterface.(ConcreteType)
// myInterface 是要断言的接口值。
// ConcreteType 是目标类型。
// value 是接口值转换后的具体类型的值。
// ok 是一个布尔值,指示转换是否成功
-

4.2 类型判断
      类型判断允许你使用switch语句检查接口值的底层类型,并根据类型执行相应的操作。这是一种更安全的方式,因为它不会导致运行时恐慌。例如:

var myInterface interface{} = 42

switch value := myInterface.(type) {
case int:
    fmt.Println("Value is an int:", value)
case string:
    fmt.Println("Value is a string:", value)
default:
    fmt.Println("Value is of unknown type")
}

5. 接口组合

在Go语言中,接口组合(interface composition)是一种将多个接口合并成一个新接口的机制。通过接口组合,可以将多个接口的方法集合并在一起,形成一个新的接口,这个新接口包含了所有原始接口的方法。

接口组合的语法形式如下:

package main
import "fmt"
// 定义两个接口
type Reader interface {
	Read()
}
type Writer1 interface {
	Write()
}
// 将两个接口进行组合
type ReadWriter interface {
	Reader
	Writer1
}
// 实现接口
type File1 struct {
	name string
}
func (f File1) Read() {
	fmt.Printf("%s is reading...\n", f.name)
}
func (f File1) Write() {
	fmt.Printf("%s is writing...\n", f.name)
}
func main() {
	file := File1{name: "myFile"}
	// ReadWriter 接口包含了 Reader 和 Writer 接口的方法
	var rw ReadWriter = file
	rw.Read()
	rw.Write()
}

      在上述示例中,我们首先定义了两个接口Reader和Writer1,分别包含了Read()和Write()方法。接着,我们将这两个接口进行组合,形成了新的接口ReadWriter,包含了Reader和Writer的所有方法。
      然后,我们实现了一个File1类型,并为其实现了Read()和Write()方法。最后,在main()函数中,我们将File类型的实例赋值给ReadWriter类型的变量rw,并可以通过rw调用Read()和Write()方法。
通过接口组合,我们可以将多个接口的方法组合在一起,使得接口的使用更加灵活和方便。

6. 空接口类型( interface{})一一能保存所有值的类型

空接口是接口类型的特殊形式, 空接口没有任何方法,因此任何类型都无须实现空接口。从实现的角度看,任何值都满足这个接口的 。因为空接口类型可以保存任何值,也可以从空接口中取出原值。

** 6.1 将任何值保存到空接口中**

var any interface{}
any = 1
fmt.Printf("空接口any的值为%d,类型为%T\n", any, any)
any = "Hello"
fmt.Printf("空接口any的值为%s,类型为%T\n", any, any)
any = false
fmt.Printf("空接口any的值为%t,类型为%T\n", any, any)

运行结果
在这里插入图片描述

6.2 从空接口获取值
     保存到空接口的值,如果直接取出指定类型的值时,会发生编译错误,解决这类错误需要用到类型断言。

var a int = 1![在这里插入图片描述](https://img-blog.csdnimg.cn/d50d8c40858d474090b1aae5c2745552.png#pic_center)

var i interface{} = a
var b int = i  // 编译报错 :编译器告诉我们,不能将i变量视为 int 类型赋值给b
var b int = i.(int) //进行类型断言 

变量i还是一个interface{}类型的变量。类似于无论集装箱装的是茶叶还是烟草,集装箱依然是金属做的,不会因为所装物的类型改变而改变, 解决上面的错误需要用到类型断言,将i变为int类型。

6.3 空接口的值比较

空接口在保存不同的值后,可以和其他变量值一样使用“==”进行比较操作,保存有类型不同的值的空接口进行比较时,Go语言会优先较值的类型。当接口中保存有动态类型的值时,运行时将触发错误,比如map类型和切片类型,这两种类型是不可进行比较的。

本文部分内容有参考部分书籍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值