Go教程接口
Posted 玖五二七
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go教程接口相关的知识,希望对你有一定的参考价值。
在Go中一个接口被定义为特定值预期具体的一组方法,后面跟一个,内部有一组方法,以及方法期望参数和返回值.
可以把接口看作需要struct实现的一组行为.
接口定义
type myInterface interface
method() // 无参数无返回值的方法
methodWithParam(float64) // 带参数的方法
methodWithReturn() string // 带返回值的方法
一个拥有接口定义的所有方法的类型被称作满足那个接口.一个满足接口的类型可以用在任何需要接口的地方.
方法名,参数类型(可选)和返回值(可选)都需要与接口定义的一致.除了接口中列出的方法之外,类型还可以有更多的方法,但它不能缺少接口中的任何方法,否则就不满足那个接口.
一个类型可以满足多个接口,一个接口可以有多个类型满足它.
定义满足接口的类型
下面的例子定义了有三个方法的接口,然后定义了几个类型,正好可以满足该myInterface .
为了满足myInterface 接口,需要有三个方法.
然后我们声明另外一个类型,MyType.这个例子中,MyType的基础类型并不重要,我们就用string,为了MyType满足myInterface,我们定义了接口需要的所有方法,另外包含一个并不属于接口的额外的方法.
type Mtinterface interface
Method()
MethodWithArg(int)
MethodWithReturn() string
type MyType string
func (m MyType) Method()
fmt.Println("method")
func (m MyType) MethodWithArg(n int)
fmt.Println("method", n)
func (m MyType) MethodWithReturn() string
fmt.Println("method with return")
return "9"
func (m MyType) Me()
fmt.Println("me")
如果声明了一个指针类型的接收器方法,只能将那个类型的指针传递给接口变量
当Go判断值是否满足一个接口的时候,指针方法并没有包含直接的值.它包含了指向那个值的地址.解决方法是将一个指向该值的指针赋值给被调用的变量,来代替直接的地址.
type Animal interface
Sound()
type Cat struct
Name string
// 指针类型的接收器方法
func (c *Cat) Sound()
fmt.Println("miao")
// 该函数需要传递指针类型的参数
func Sound(a *animals.Cat)
a.Sound()
func main()
var c animals.Cat
c.Name = "小花"
Sound(&c)
具体类型和接口类型
一个具体类型既定义了
- 它的值可以做什么:可以调用哪些方法.
- 它是什么:它定义了保存值的数据的基础类型.
接口类型并不描述是哪个值,
- 它不说它的基础类型是什么,或者数据是如何存储的.
- 它们仅仅描述了这个值能做什么.它有哪些方法.
分配满足接口的所有类型
当你有一个接口类型的变量时,它可以保存满足此接口的任何类型的值.
假设我们有Cat和Dag类型,它们都满足Sound方法.我们可以创建一个Aninal接口来代替声明了Sound方法的所有类型
如果我们定义了 Animal类型的变量animal后,可以把Dag和Cat赋值给它.甚至之后再定义的任何类型,只要它有Sound方法,都可以.
我们可以调用 任何赋值给aninal变量的值上的Sound方法.虽然我们并不知道 aninal保存值的具体类型是什么,但我们知道它能做什么:Sound.如果它的类型没有Sound方法,那么它不满足Animal接口.我们就不能给它赋值.
aninal/a.go
package animals
import "fmt"
type Animal interface
Sound()
type Cat struct
Name string
// 具有Sound方法
func (c *Cat) Sound()
fmt.Println("miao")
type Dog struct
Name string
// 具有Sound方法
func (d *Dog) Sound()
fmt.Println("wang")
main.go
package main
import (
"fmt"
"inter/animals"
)
func main()
fmt.Println("hello")
// 再次复习指针类型的接收器
var animal animals.Animal
animal = &d
animal.Sound() // wang
animal = &c
animal.Sound() // miao
函数的参数也可以是接口类型.函数的参数也是变量.如果声明一个Sound的函数来接收Aninal类型,我们可以传入任何包含了Sound的方法的值来发声.
接口类型的名称首字母大写则是可以导出的.否则不能被导出
类型断言
我们在类型转换中提到过类型断言.现在讲一讲细节
在上面的例子中,我们在Dog类型中增加一个Swamming方法.由于Cat不能swaaming所以不会有这个方法.
我们再添加一个函数Action,传入一个Animal接口变量,让它先调用Sound再调用Swamming.由于Cat类型没有Swamming方法,调用会失败.因为我们只有一个Animal的值,并没有Cat的值,Animal值上没有Swamming方法.
在VScode中直接提示报错,aninal中未定义Swamming方法.
我们需要一个方法来取回具体类型的值,就是那个确定含有Swamming方法的值.
根据第类型转换的指引,们是不是可以把它用类型转换来处理呢?
以上是直接使用类型转换,并不能编译通过,仍然报错.
类型断言能让你从接口类型的值取回具体类型的值.它的语法像是函数和类型转换的合体.在一个接口值后面.输入一个点.接一对(),括号中间是具体类型
// 指针类型接收器,必须要断言为指针类型
func Action(a animals.Animal)
a.Sound()
dog, ok := a.(*animals.Dog) // 第二个参数表示类型断言是否成功
if ok
dog.Swamming()
// 非指针类型接收器
func MyAction(i animals.MyInterface)
my, ok := i.(animals.MyType) // 第二个参数表示类型断言是否成功
if ok
my.Me()
以上是关于Go教程接口的主要内容,如果未能解决你的问题,请参考以下文章