前言
go语言中的接口和java中的接口地位不同,而跟python中的协议类似。实际上,go语言的接口就是参考python的鸭子类型和java的接口。
python鸭子类型
鸭子类型:当看到一只鸟走过来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
以可迭代对象为例,只要类里面实现了名为__iter__()
的方法,其对象就是可迭代对象。
from typing import Iterable
# 并没有继承typing.Iterable
class Tenno():
def __init__(self, warframe_list):
self.warframe_list = warframe_list
# 实现了Iterable的__iter__方法
def __iter__(self):
return iter(self.warframe_list)
wl = Tenno(["saryn","volt","mesa","gauss"])
print(type(wl))
if isinstance(wl, Iterable):
print("iterable")
for i in wl:
print(i)
else:
print("not iterable")
# 迭代非Iterable类型会报错,提示非Iterable类型
# for i in wl:
# print(i)
入门示例
- go语言中,接口更像python中的协议。
- 接口是一种类型,是一种抽象类型。
- 接口的命名一般以
er
结尾。 - 通过接口可以实现面向对象三大特性之一的多态(多种实现方式)
// 定义一个程序员接口,1. 可以编写代码,返回字符串。2. 可以debug,返回字符串
type Programmer interface {
Coding() string // 方法只是声明
Debug() string
}
// go程序员结构体
type Gopher struct {
}
func (g Gopher) Coding() string {
return "gopher在编程"
}
func (g Gopher) Debug() string {
return "gopher在debug"
}
// python程序员结构体
type Pythoner struct {
}
func (p Pythoner) Coding() string {
return "pythoner在编程"
}
func (p Pythoner) Debug() string {
return "pythoner在debug"
}
func main() {
var coder Programmer = Gopher{}
fmt.Println(coder.Coding())
fmt.Println(coder.Debug())
var coders []Programmer
coders = append(coders, Gopher{})
coders = append(coders, Pythoner{})
}
接口组合实现继承
类似于结构体组合,接口也可以通过组合的形式实现继承。
type DBA interface {
Sql() string
}
type Programmer interface {
Coding() string
Debug() string
}
type JiaGouShi interface {
DBA // 组合DBA的接口
Programmer // 组合Programmer的接口
Design() string // 再加一个方法
}
在上述示例中,如果要实现JiaGouShi的接口,结构体必须同时实现Sql() string
、Coding() string
、Debug() string
和Design() string
方法。
error接口
go语言的error
类型实际上是一个接口,如果有需要也可以自定义error结构体。
type error interface {
Error() string
}
空接口
空接口是没有定义任何方法的接口,例如:
// i 是空接口变量
var i interface{}
- 可以把任何类型都赋值给空接口变量
i = 10
i = "gopher"
type Warframe struct {
Name string
HP int
Defence int
}
i = Warframe{}
- 空接口也可以用于函数任意传参
func print(i interface{}) {
fmt.Printf("%v\n",i)
}
var i interface{}
i = 10
print(i)
i = "gopher"
print(i)
- 字典的值类型可以是空接口
var teacherInfo = make(map[string]interface{})
teacherInfo["name"] = "Lotus"
teacherInfo["age"] = 28
teacherInfo["weight"] = 56.7
类型断言
func print(i interface{}) {
fmt.Printf("%v\n",i)
switch v := x.(type) {
case string:
fmt.Printf("%s is string\n",v)
case int:
fmt.Printf("%d is int\n",v)
}
}
var i interface{}
i = 10
print(i) // 10 is int
i = "gopher"
print(i) // gopher is string
示例:对复杂类型进行排序
go语言标准库提供sort
模块(sort.Sort()
),可以对一些简单类型排序。但其实该模块为一个接口,通过实现该接口,便可以对复杂类型进行排序。
package main
import (
"fmt"
"sort"
)
type Course struct {
Name string
Price int
Url string
}
type Courses []Course
func (c Courses) Len() int {
return len(c)
}
func (c Courses) Less(i,j int) bool {
return c[i].Price < c[j].Price
}
func (c Courses) Swap(i,j int) {
c[i], c[j] = c[j], c[i]
}
func main() {
c := Courses{
Course{Name: "python", Price: 200, Url: "123"},
Course{Name: "linux", Price: 100, Url: "456"},
Course{Name: "go", Price: 300, Url: "789"},
}
// 排序
sort.Sort(c)
for _,v := range(c){
fmt.Printf("%v\n",v)
}
}