接口类型的合理运用
2020-12-22
对于一个接口类型来说,如果没有任何数据类型可以作为它的实现,那么该接口类型的值就不可能存在,接下来天眼数聚api接口大全就详细给大家讲解下接口类型的合理运用
使用关键字 type 和 interface,可以声明一个接口类型,接口类型的字面量和结构体类型看起来很相似,它们都用花括号包裹一些核心信息。只是结构体包裹的是它的字段声明,而接口包裹的是它的方法定义。
接口类型声明中的这些方法所代表的就是该接口的方法集合。一个接口的方法集合就是它的全部特征。
对应任何一个数据类型,只要它的方法集合中完全包含了一个接口的全部特征,那么它就是这个接口的实现类型:
type Pet interface { SetName(name string) Name() string Category() string}
只要一个数据类型的方法集合中有这 3 个方法,那么他就一定是 Pet 接口的实现类型。这是一种无侵入式的接口实现方式。
怎样判定一个数据类型的某一个方法实现的就是某接口类型中的某方法
有两个充分必要条件:
•两个方法的签名需要完全一致。
•两个方法的名称要一模一样。
显然,这比判断一个函数是否实现了某个函数类型要更加严格。
type Dog struct { name string // 名字。}func (dog *Dog) SetName(name string) { dog.name = name}func (dog Dog) Name() string { return dog.name}func (dog Dog) Category() string { return "dog"}
上面这个例子,Dog 类型有三个方法,两个值方法,一个指针方法,这意味这它的值方法并不是接口 Pet 的实现,而它的指针方法才是。
dog := Dog{"little pig"}var pet Pet = &dog
因此,我们可以声明并初始化一个 Dog 类型的变量 dog,然后把它的指针值赋给类型为 Pet 的变量。
这里有几个名词需要记住,对于一个接口类型的变量来说,我们赋给它的值可以叫做它的实际值(动态值),而该值的类型可以叫做这个变量的实际类型(动态类型)。动态类型这个叫法是相对于静态类型而言的,对于变量 pet 来说,它的静态类型就是 Pet,而它的动态类型会随着我们赋给它的动态值变化。
在给一个接口类型的变量赋予实际值之前,它的动态类型是不存在的。
为一个接口变量赋值时会发生什么
如果我们使用一个变量给另外一个变量赋值,那么真正赋值给后者的,并不是前者所持有的那个值,而是该值的一个副本。
接口本身是无法被值化的。在赋予它实际的值之前,它的值是 nil,这也是它的零值。
当我们给一个接口变量赋值时,该变量的动态类型会与它的动态值一起被存储再一个专用的数据结构中。这个结构在 Go 语言运行时系统 runtime 包中叫做 iface。它的实例包含两个指针,一个指向类型信息,一个指向动态值。这里的类型信息是由另一个专用数据结构的实例承载的,其中包含了动态值的类型,以及使用它实现了接口的方法和调用它们的途径等。
总之,接口变量被赋予动态值时,存储的是包含了这个动态值的副本的一个结构更加复杂的值。
接口变量的值在什么情况下才为 nil
Go 语言中,我们把字面量 nil 表示的值叫做无类型的 nil。这是真正的 nil,因为它的类型也是 nil 的。上面说了,当我们给接口变量赋值时,Go 语言会用 iface 的实例包装它,包装后的产物就不是 nil 了。
只要我们把一个有类型的 nil 赋给变量接口,那么这个变量的值就一定不会是真正的 nil。
只有在只声明但不初始化或者直接把字面量 nil 赋给它这两种情况下才真正为 nil。
怎样实现接口直接的组合
接口类型间的嵌入也叫做接口的组合,它比结构体类型的嵌入简单点,因为它不会涉及方法间的屏蔽。只要组合的接口之间有同名方法就会产生冲突,从而无法通过编译,即使同名方法的签名不同也会如此。因此,接口的组合根本不可能导致屏蔽现象。
type Animal interface { ScientificName() string Category() string}type Pet interface { Animal Name() string}
Go 语言团队鼓励我们声明体量较小的接口,并建议我们通过这种接口间的组合来扩展程序、增加程序的灵活性。
这是因为相比于包含很多方法的大接口而言,小接口可以更加专注的表达某一种能力或某一类特征,同时也更容易被组合在一起。
Go 语言标准库代码包 io 中的 ReadWriteCloser 接口和 ReadWriter 接口就是这样的例子,它们都是由若干个小接口组合而成的。以 io.ReadWriteCloser 接口为例,它是由 io.Reader、io.Writer 和 io.Closer 这三个接口组成的。
这三个接口都只包含了一个方法,是典型的小接口。它们中的每一个都只代表了一种能力,分别是读出、写入和关闭。我们编写这几个小接口的实现类型通常都会很容易。并且,一旦我们同时实现了它们,就等于实现了它们的组合接口 io.ReadWriteCloser。
即使我们只实现了 io.Reader 和 io.Writer,那么也等同于实现了 io.ReadWriter 接口,因为后者就是前两个接口组成的。可以看到,这几个 io 包中的接口共同组成了一个接口矩阵。它们既相互关联又独立存在。
天眼数聚api接口大全以大数据为基础,覆盖人脸身份核实、运营商、银行卡、车辆、医疗、智能识别等,为企业用户提供多维度、全方位的数据API服务;目前已服务近万家企业,涵盖了教育、游戏、电商、物流、金融、保险、支付、出行等数十个领域,同时公司在数据采集、模型算法、机器学习等领域具有较强的技术优势,所推出的基于业界领先算法模型的活体检测、人脸身份证识别接口等智能识别服务广受好评。
相关资讯
2021-04-29
2021-06-11
2021-08-20
2021-09-06
2024-05-16
2021-07-23
2020-12-03
2023-12-28
2021-07-07
2023-03-03