golang快速入门:接口

接口

在 Go 语言中,接口是一组仅包含方法名、参数、返回值的未具体实现的方法的集合。

scss 复制代码
type Animal interface {
	Sing()
	GetName() string
}

在 Go 语言中,类对接口的实现和子类对父类的继承一样,并没有提供类似 ​​implement​​ 这种关键字显式声明该类实现了哪个接口,一个类只要实现了某个接口要求的所有方法,我们就说这个类实现了该接口。

go 复制代码
type Chicken struct {
	Name string
}

func (ch *Chicken) Sing() {
	fmt.Println(ch.Name + "在打鸣")
}

func (ch *Chicken) GetName() string {
	return ch.Name
}

​Chicken​​ 结构体实现​​Animal​​​ 接口声明的所有方法,则​​Chicken​​​ 结构体就实现了​​​Animal​​ 接口。

通过组合实现接口继承

Go 语言也支持类似的「接口继承」特性,但是由于不支持 ​​extends​​ 关键字,是通过组合来完成的。

go 复制代码
type Animal interface {
    Call()
}

type Bird interface {
    A
    Fly()
}

type Chicken struct {}

func (c Chicken) Call() {
    fmt.Println("小鸡在打鸣")
}
func (c Chicken) Fly() {
    fmt.Println("小鸡会飞")
}

Chicken​​ 结构体可以只实现 ​​Call​​ 方法,也可以只实现 ​​Fly​​ 方法,也可以都不实现。如果只实现了 ​​Call​​ 方法,则 ​​Chicken​​ 实现了接口 ​​Animal​​;如果只实现了 ​​Fly​​ 方法,则既没有实现接口 ​​Animal​​ 也没有实现接口 ​​Bird​​,只有两个方法都实现了系统才会判定实现了接口 ​​Bird​​。

接口断言

Go 语言通过类型断言运算符 ​​.(type)​​ 来实现,其中 ​​type​​​ 对应的就是要断言的类型。下面,我们来看下具体的使用示例。

go 复制代码
type Animal interface {
	Sing()
	GetName() string
}
type Chicken struct {
	Name string
}

func (ch *Chicken) Sing() {
	fmt.Println(ch.Name + "在打鸣")
}

func (ch *Chicken) GetName() string {
	return ch.Name
}

type Cat struct {
	Name string
}

func (c *Cat) Sing() {
	fmt.Println(c.Name + "在唱歌")
}

func (c *Cat) GetName() string {
	return c.Name
}
scss 复制代码
func handle(a Animal) {
  if ch, ok := a.(*Chicken); ok {
      fmt.Println("ch is Chicken")
  }
	fmt.Println(ch, ok)

}

func main() {

	ch := Chicken{Name: "公鸡"}
	ca := Cat{Name: "喵咪"}
	handle(&ch)
	handle(&ca)
}

通过 ​​a.(*Chicken)​​ 这个表达式断言 ​​a​​ 是否是​​Chicken​​ 类型的实例,如果是,​​ok​​ 值为 ​​true​​,然后执行 ​​if​​ 语句块中的代码;否则 ​​ok​​ 值为 ​​false​​,不执行 ​​if​​ 语句块中的代码。

go 复制代码
	switch ser := a.(type) {
	case *Chicken:
		fmt.Println(ser)
	case *Cat:
		fmt.Println(ser)
	default:
		fmt.Println("其他")

	}

也可以通过switch语句做断言判断

空接口

在 Go 语言中,结构体与接口的实现关系是通过结构体所实现的方法在编译期推断出来的,如果我们定义一个空接口的话,那么显然所有的类都实现了这个接口,反过来,我们也可以通过空接口来指向任意类型, Go 的空接口实现简单,通过一个简单的字面量即可完成:

csharp 复制代码
interface{}

指向任意类型变量

csharp 复制代码
//基本类型
var v1 interface{} = 1 // 将 int 类型赋值给 interface{} 
var v2 interface{} = "空接口" // 将 string 类型赋值给 interface{} 
var v3 interface{} = true  // 将 bool 类型赋值给 interface{}

//复合类型
var v4 interface{} = &v2 // 将指针类型赋值给 interface{} 
var v5 interface{} = []int{1, 2, 3}  // 将切片类型赋值给 interface{} 
var v6 interface{} = struct{   // 将结构体类型赋值给 interface{}
    id int
    name string
}{1, "结构体"}

声明任意类型参数

go 复制代码
func Printf(fmt string, args ...interface{}) 
func Println(args ...interface{}) ...
func (p *pp) printArg(arg interface{}, verb rune)

总结

  1. 接口是一种抽象类型,描述了一个对象的行为和功能,没有数据字段。接口只定义一组方法,不做具体的功能实现,实现接口的类型必须实现所有这些方法。
  2. 实现接口的类型可以是任何类型,包括结构体、基本数据类型、数组、切片、映射或函数等,只要实现了接口的所有方法,那么它就实现了该接口。
  3. 接口类型的值可以保存任何实现了该接口的类型。它们可以作为参数传递,也可以作为返回值返回。
  4. 接口可以嵌套在其他接口中,也可以通过嵌套其他接口来实现接口的组合。
  5. 空接口interface{}没有任何方法,因此可以用来表示任何类型的值。
相关推荐
你的人类朋友1 天前
说说签名与验签
后端
databook1 天前
Manim实现脉冲闪烁特效
后端·python·动效
canonical_entropy1 天前
AI时代,我们还需要低代码吗?—— 一场关于模型、演化与软件未来的深度问答
后端·低代码·aigc
颜如玉1 天前
HikariCP:Dead code elimination优化
后端·性能优化·源码
考虑考虑1 天前
Jpa使用union all
java·spring boot·后端
bobz9651 天前
virtio vs vfio
后端
Rexi1 天前
“Controller→Service→DAO”三层架构
后端
bobz9651 天前
计算虚拟化的设计
后端
深圳蔓延科技1 天前
Kafka的高性能之路
后端·kafka
Barcke1 天前
深入浅出 Spring WebFlux:从核心原理到深度实战
后端