主要讲解Go语言中接口的定义与实现
主要知识点
- 熟悉Go语言中如何定义接口
- Go语言中实现接口不需要显式实现,只需要实现其方法就可以
- 学会如何判断接口的真实类型,如何将接口类型转为真实类型
- 接口变量中 封装了 实现者的类型 和 实现者的指针
- 在实际运用中 避免使用接口指针,直接使用值传递就可以
- interface{} 代表任意类型
- head.(int) 代表将 head 变量强制转换为 int 类型
- 如果一个结构体的方法为指针接收者,最好把其他方法也改为指针接收者
- Go语言中的接口是由使用者定义规则的,底层实现可以很多方法,但是接口使用者只需要几个方法,则只需定义需要方法的接口即可
示例代码如下:
package main
import "fmt"
//定义接口 1
type Retriever interface {
Get(url string) string
}
//定义接口 2
type SentPost interface {
Post(url string) string
}
//定义结构体
type RetrieverImpl struct {
Contents string
}
//为结构体定义Get方法
// RetrieverImpl 有了Get方法,系统会默认认为 RetrieverImpl 实现了 Retriever接口
func (RetrieverImpl) Get(url string) string {
return url
}
//定义结构体 2 ,
type RetrieverOtherImpl struct {
Name string
}
//为结构体定义Get方法
// RetrieverImpl 有了Get方法,系统会默认认为 RetrieverImpl 实现了 Retriever接口
func (RetrieverOtherImpl) Get(url string) string {
return "RetrieverOtherImpl"
}
//定义接口使用者,此方法中需要传入一个接口类型,实现中对接口进行调用
func download( r Retriever) string {
return r.Get("https://www.baidu.com")
}
//使用 switch 的方式 判断 Retriever 接口的真实类型
func inspect(r Retriever) {
fmt.Println("Inspecting", r)
fmt.Printf(" > Type:%T Value:%vn", r, r)
fmt.Print(" > Type switch: ")
switch r.(type) {
case RetrieverImpl:
fmt.Println("当前 Retriever 接口的类型为 :RetrieverImpl")
case RetrieverOtherImpl:
fmt.Println("当前 Retriever 接口的类型为 :RetrieverOtherImpl")
}
fmt.Println()
}
// 接口的组合,以下是 一个组合接口
// WebBaseOpration 接口组合了 Retriever 和 SentPost 接口
// 还可以有自己特定的其他 方法
type WebBaseOpration interface {
Retriever
SentPost
Delete()
}
func main() {
//定义两个实现 Retriever 接口的 结构体
var r1 Retriever
r1 = RetrieverImpl{"RetrieverImpl"}
fmt.Println(download(r1))
var r2 Retriever
r2 = RetrieverOtherImpl{ Name:"RetrieverOtherImpl"}
fmt.Println(download(r2))
//判断一个接口类型 背后 的真实类型
inspect(r1)
inspect(r2)
//将接口类型转为真实类型
tempRetriever :=r1.(RetrieverImpl)
fmt.Println(tempRetriever.Contents)
// Type assertion,以上方法当类型不对时会报错,导致中断,需要进行判断,如下:
// 将 r1 转为自己 真实类型,并调用自己特有的方法
if tempRetriever, ok := r1.(RetrieverImpl); ok {
fmt.Println("r1调用自己方法:",tempRetriever.Contents)
} else if tempRetriever, ok := r1.(RetrieverOtherImpl); ok{
fmt.Println("r1调用自己方法:",tempRetriever.Name)
}
}
必须知道的三个系统接口
- Stringer 接口,相当于Java 中的 toString() 方法,实现了Stringer 接口,在打印输出变量时可以自定义格式,否则默认会输出类型
- Reader 接口,主要用于文件或者网络读取
- Writer 接口,主要用于文件或者网络的写入
Reader 和 Writer 接口 是对 文件和网络的抽象 ,被文件、网络操作结构实现之后,可以更加方便的 进行读写操作,系统中大部分需要读写的操作,都是通过 Reader 和 Writer 实现的。
以下为代码示例:
package main
import "fmt"
type RuoliNode struct {
Name string
Age int
}
func (node RuoliNode) String() string {
return fmt.Sprintf("RuoliNode {Name:%s,Age:%d} n",node.Name,node.Age)
}
func main() {
node :=RuoliNode{"Ruoli",18}
fmt.Println(node) //RuoliNode {Name:Ruoli,Age:18}
}