学习GO:接口类型

103 阅读5分钟

学习GO:接口类型

Interface Types 是Go编程语言中最强大的功能之一,如果使用得当,它可以使代码更容易维护和扩展。根据你的编程经验,这个概念可能有点难以理解,因为你可能是第一次听到这个概念,或者你所熟悉的编程语言没有相应的概念,或者即使有,它的实现方式也与Go的实现方式不同。

Interfaces Types类型,因此我们需要清楚地了解什么是 ,Go中支持的类型有哪些。type


什么是类型?

在Go中,一个Type表示状态或行为的一种方式。有两种类型。基本类型和复合类型

基本类型包括你众所周知的类型,这些类型是用来以特定的方式存储数据的,具体来说。

  • string, 比如说。"hello",
  • numeric,其中包括以integerfloatcomplex 数字表示的数字类型。有一些数字类型是为了描述允许的最大容量和支持的可能值,例如uint8 代表一个无符号整数,其容量为8比特
  • bool,定义了一个布尔值,允许truefalse

这些将被视为*"基本 "的* 基本类型,意味着其他类型通过别名使用它们来定义新的类型,这是为了区分它们的目标,但最终它们重用了原始基本类型的能力。例如,byte 类型是uint8 的别名。

复合类型包括一些更复杂的类型,在幕后是由其他多种类型组成的,具体而言。

  • pointer, 用来保存一个值的内存地址。
  • function, 定义了一个共同工作的语句集合。
  • map,用于将键映射到值的数据结构。
  • array,定义了一个静态的值集合。
  • **slice**定义了一个动态大小的数组。
  • **struct**定义了一种创建新的自定义类型的方法,该类型有一个字段集合。
  • **channel**定义了一个用于发送和接收值的管道,以及最后
  • interface,是一组方法签名。

函数和方法

使用这些类型来定义变量可以让我们把它们和函数结合起来使用,而函数是用来模块化我们的代码并允许一些重用性。因为Go不是一种面向对象的编程语言,也没有类,所以当我们试图将行为附加到我们的自定义类型时,函数就派上了用场,当我们这样做时,就会引入一个新的概念。方法

方法是在幕后接收一个特殊的第一个参数的函数。这个参数类型与定义方法的类型相同,其值是调用函数的参数,它在某种程度上被用来模仿面向对象的编程语言对类的作用。

例如,一个表示三种不同优先级的简单类型可以定义为。

type Priority int8

func (p Priority) String() string {
	switch int8(p) {
	case 0:
		return "low"
	case 1:
		return "high"
	}

	return "unknown"
}

上面的代码创建了一个名为Priority 的新类型,它使用了int8 基本类型,行为是在实现String 方法后添加的,该方法返回一个代表存储在自定义类型中的值的string

为了利用这个行为,我们有几种不同的方法,让我们看看下面的代码。

func main() {
	var p Priority = 1

	fmt.Println(p.String())         // "high"
	fmt.Println(Priority.String(p)) // "high"
	fmt.Println(p)                  // "high"
}

这三种情况的输出都是一样的,但是在这个例子中重要的是如何调用String 这个方法。

  • p.String():因为这是一个方法调用,变量p 在幕后作为第一个参数传递给类型为String 的函数Priority ,并像往常一样执行。
  • Priority.String(p): 回想一下,方法就是函数,因此我们仍然可以用这种方式对函数进行调用,这种方式肯定是不常见的,但是看到这个调用的动作,就更加明确了前面的说法。方法就是函数

最后,最后一行fmt.Println 做了一些有趣的事情,因为它没有明确地调用String 。这是怎么做到的呢?这就是接口类型的作用。

什么是接口类型?

Interface Types 是一组方法签名,可以容纳任何实现这些方法的。实现这组方法的类型会自动与被定义的接口类型兼容,换句话说,与其他编程语言相比,Go中的接口类型implicit.

这意味着要实现一个接口的类型不需要像其他语言那样,事先知道接口类型实现它或扩展它。

接口类型带来了面向对象编程语言的一个特点。多态性

如果一个类型满足了一组方法的签名,那么该类型就等同于定义了上述方法的接口类型。这就是为什么fmt.Println 中的第三个调用不需要显式调用String ,实现了 fmt.Println的实现定义了一个文档中提到的接口类型

如果一个操作数实现了String()字符串方法,该方法将被调用以将对象转换为字符串,然后按动词(如果有的话)的要求进行格式化。

具体来说,在这种情况下,在fmt 包中有一个接口类型,叫做 Stringer它定义了我们的Priority 类型所实现的String 方法,最终用于打印出字符串值。

总结

就像我在开始写这篇文章时提到的,接口类型是Go中的一个伟大的功能,它允许我们建立可以处理不同实现的多态代码,但不仅如此,它还允许扩展现有的代码,因为不需要明确定义/输入/扩展接口类型