Day15-Go介面interface

前言

Go 语言的介面(interface)是一组以方法签名(method signatures)的组合,透过介面来定义物件的一组行为,它将物件导向的内容组织,实现得非常方便。

介绍Interface

Interface 定义了一组 method,Interface 里的值可以保存实现这些方法的任何值 。这里以 Go Tutorial 上的例子来解说,这边有稍微做了些调整,我们直接看以下的程序码:

package main
 
import (
   "fmt"
   "math"
)
 
type Abser interface {
   Abs() float64
}
 
func main() {
   var a Abser
   f := MyFloat(-math.Sqrt2)
   v := Vertex{3, 4}
 
   a = f  // a MyFloat implements Abser
   fmt.Println(a.Abs())
 
   a = &v // a *Vertex implements Abser
   fmt.Println(a.Abs())
}
 
type MyFloat float64
 
func (f MyFloat) Abs() float64 {
   if f < 0 {
       return float64(-f)
   }
   return float64(f)
}
 
type Vertex struct {
   X, Y float64
}
 
func (v *Vertex) Abs() float64 {
   return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

我们来解释一下上述程序码, Abser interface 实现了 Abs method,而 Abs method 同时定义在 Vertex struct 和 MyFloat 上。

Interface 值

Interface 里到底能存什麽值呢?如果我们定义了一个 interface 的变数,那麽这个变数可以实现该 interface 里所有的变数型态。例如上述的例子, Abser interface 最终实现了 Vertex struct 和 MyFloat 两种变数型态,而最後储存 float64 这个变数型态。

我们再来看一个例子:

package main
 
import (
   "fmt"
   "math"
)
 
type I interface {
   M()
}
 
type T struct {
   S string
}
 
func (t *T) M() {
   fmt.Println(t.S)
}
 
type F float64
 
func (f F) M() {
   fmt.Println(f)
}
 
func main() {
   var i I
 
   i = &T{"Hello"}
   describe(i)
   i.M()
 
   i = F(math.Pi)
   describe(i)
   i.M()
}
 
func describe(i I) {
   fmt.Printf("(%v, %T)\n", i, i)
}

Interface I 实现了 M method,而 M method 定义在 T struct 和 F float64上,最後 M method 因出了两个型态变数中带的参数

空 Interface

空 interface 不包含任何的 method,所以所有的型别都实现了空 interface。空 interface 对於描述起不到任何的作用(因为它不包含任何的 method),但是在我们需要储存任意型别的数值时,空 interface 及发挥到他的作用,因为它可以储存任意变数型态,我们来看一下下面的例子:

package main
 
import (
   "fmt"
)
 
var a interface{}
 
func main() {
   // 定义 a 为空介面
 
   var i int = 5
   s := "Hello world"
   // a 可以储存任意型别的数值
   a = i
   fmt.Println(a) // 5
 
   a = s
   fmt.Println(a) // Hello world
}

nil Interface 值

一个 nil interface 值既不包含值也不包含具体类型。
在 nil interface 上调用方法是一个运行时错误,因为 interface 里没有任何类型定义在任何方法上。

package main
 
import "fmt"
 
type I interface {
   M()
}
 
func main() {
   var i I
   describe(i)
   i.M()
}
 
func describe(i I) {
   fmt.Printf("(%v, %T)\n", i, i)
}

结语

今天带来 Go 语言中非常巧妙的设计 interface,它让物件导向,内容组织实现非常的方便,本人自觉 Go 语言的 interface 简单且非常实用,希望今天带来的文章对你有初步认识 interface 的帮助,谢谢你今天的阅读。

参考来源

https://tour.golang.org/methods/9
https://tour.golang.org/methods/10
https://tour.golang.org/methods/11
https://tour.golang.org/methods/12
https://tour.golang.org/methods/13
https://tour.golang.org/methods/14


<<:  Day11 do-while

>>:  33岁转职者的前端笔记-DAY 23 JavaScript 变数与型别

设定档格式 YAML

YAML YAML的诞生不算太晚, 1.0在2004就出了, 虽然晚了JSON 5年(1999年),...

梳理useEffect和useLayoutEffect的原理与区别

点击进入React源码调试仓库。 React在构建用户界面整体遵循函数式的编程理念,即固定的输入有固...

【HTML】【CSS】<table>里面时常无效的margin和padding

【前言】 本系列为个人前端学习之路的学习笔记,在过往的学习过程中累积了很多笔记,如今想藉着IT邦帮忙...

[30天 Vue学好学满 DAY16] slot 插槽

slot 在子元件(内层)中预留空间,由父元件(外层)设定、分配内容。 子元件本身对slot无控制权...