接口声明
// 接口声明 语法:接口是一个 函数签名 的集合,函数签名(函数的声明,不包括实现)
type interfaceName interface {
method1(param paramType, param paramType...) (returnName returnType ...)
method2(param paramType, param paramType...) (returnName returnType ...)
}
// 接口名一般加 er
type writer interface {
write(num int) (n int, flag bool)
cache(p []byte) int
}
// 若方法名首字母是大写时,且接口名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
// 声明结构体
type structName struct {
filed1 filedType
filed2 filedType
}
// 实现接口中的方法
func (structVariableName structName) method1 (param paramType, param paramType...) (returnName returnType returName returnType, ...) {
// do something
}
func (structVairableName structName) method2 (param paramType, param paramType...) (returnName returnType, returnName returnType,...) {
// do something
}
// 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以被忽略
// 实例
type Phone interface {
call(number int) string
}
// 定义结构体
type Apple struct {
name string
}
type Sony struct {
name string
}
// 实现方法
func (appleBanner Apple) call(number int) string {
fmt.Println("param number: ", number)
fmt.Println("banner name: ", appleBanner.name)
return "successful"
}
func (sonyBanner Sony) call(number int) string {
fmt.Println("param number: ", number)
fmt.Println("banner name: ", sonyBanner.name)
return "successful"
}
func main() {
var apple = Apple{"apple"}
apple.call(1031)
sony := Sony{"sony"}
sony.call(313)
}
实现接口的条件
- 接口中的方法签名包括:方法名称、方法所需参数、参数类型、方法的返回值、返回值类型;若需要实现接口中的某个方法签名,其上述的五个要点需全部保持一致。
- 接口被正确的编译使用需要 实现接口中的全部方法

类型与接口、接口与接口
- 一个类型可以实现多个接口,比如一个 socket 结构体同时实现了 io接口和日志接口。
- 多个类型可以实现相同的接口 ,一个结构体可以嵌套另一个结构体,若一个接口有多个方法需要实现,可以某个结构体实现其中几个方法,剩下的方法由另一个结构体实现。
// 包含 开启方法和写日志方法 的服务接口
type Service interface {
Start() // 开启服务
Log(string) // 日志输出
}
// 日志器
type Logger struct {
}
// 日志结构体 实现 Log()方法
func (g *Logger) Log(l string) {
}
// 游戏服务
type GameService struct {
Logger // 嵌入日志器
}
// 游戏结构体 Start()方法
func (g *GameService) Start() {
}
// 使用
var s Service = new(GameService)
s.Start()
s.Log(“hello”)
- 一个接口同时包含了多个其他接口,产生了一个新的接口
// 写入接口
type Writer interface { Write(p []byte) (n int, err error)}
// 关闭接口
type Closer interface {
Close() error
}
// 接口嵌套
type Logger interface { // 此接口需要两个接口嵌入
Writer
Closer
}
排序接口


package main
import (
"fmt"
"sort"
)
// 自定义类型 排序
type Interface interface {
Len() int // 序列内元素数量
Less(i, j int) bool // 序列中 索引为i的元素 < 索引为j的元素
Swap(i , j int) // 交换两个索引上的元素
}
// 将字符串定义成 自定义类型 (type 关键字)
type MyStringList []string // []string: 字符串切片; 为了能对自定义的字符串切片排序,需要让 MyStringList 实现 Interface 接口
// 方法
func (stringLists MyStringList) Len() int {
return len(stringLists)
}
func (stringLists MyStringList) Less(i, j int) bool {
return stringLists[i] < stringLists[j]
}
func (stringLists MyStringList) Swap(i, j int) {
stringLists[i], stringLists[j] = stringLists[j], stringLists[i]
}
// 结构体排序
type HeroKind int // 英雄的种类
const ( // 定义 HeroKind 的 value 为常量, 类似枚举
None HeroKind = iota
Tank
Assassin
Mage
)
type Hero struct { // 定义英雄的结构
Name string // 英雄名字
Kind HeroKind // 英雄种类
}
type Heros []*Hero // 英雄切片集合
// 实现 Interface 接口的三个方法
func (heros Heros) Len() int {
return len(heros)
}
func (heros Heros) Less(i, j int) bool {
if heros[i].Kind != heros[j].Kind { // 两个英雄的种类不一致时, 优先的按照 种类数字大小进行对比, 否则 则按照英雄名字对比
return heros[i].Kind < heros[j].Kind
}
return heros[i].Name < heros[j].Name
}
func (heros Heros) Swap(i, j int) {
heros[i], heros[j] = heros[j], heros[i]
}
// 对切片元素进行排序: sort.Slice()
func main() {
// 1、自定义类型实现排序
names := MyStringList {
"3. Triple Kill",
"5. Penta Kill",
"2. Double Kill",
"4. Quadra Kill",
"1. First Blood",
}
fmt.Println(names)
sort.Sort(names) // 排序:sort.Interface 用于指定 通用排序算法 和 可能被排序到的序列类型 之间的规定
fmt.Println(names)
// 2、sort 包中的便捷排序
//names := sort.StringSlice { // 字符串切片 排序
// "3. Triple Kill",
// "5. Penta Kill",
// "2. Double Kill",
// "4. Quadra Kill",
// "1. First Blood",
//}
//fmt.Println(names)
//sort.Strings(names)
//fmt.Println(names)
//nums := sort.IntSlice { // 整型切片 排序
// 10,
// 1,
// 6,
// 5,
// 2,
//}
//fmt.Println(nums)
//sort.Ints(nums)
//fmt.Println(nums)
//doubles := sort.Float64Slice{ // 双精度小数切片 排序
// 5.02,
// 3.31,
// 10.19,
// 2.20,
// 12.12,
// 6.18,
// 1.12,
//}
//fmt.Println(doubles)
//sort.Float64s(doubles)
//fmt.Println(doubles)
// 3、结构体排序
heros := Heros{
&Hero{"吕布", Tank},
&Hero{"李白", Assassin},
&Hero{"妲己", Mage},
&Hero{"貂蝉", Assassin},
&Hero{"关羽", Tank},
&Hero{"诸葛亮", Mage},
}
fmt.Println("排序前结构体顺序: ")
for index, hero := range heros {
fmt.Print(index, "\t")
fmt.Println(*hero)
}
//sort.Sort(heros)
// 4、对切片元素排序: sort.Slice(slice interface{}, less func(i, j int) bool) {...}
sort.Slice(heros, func(i, j int) bool { // 传入 切片 和 在排序时对元素进行判断的回调函数
if heros[i].Kind != heros[j].Kind {
return heros[i].Kind < heros[j].Kind
}
return heros[i].Name < heros[j].Name
})
fmt.Println()
for index, hero := range heros {
fmt.Print(index, "\t")
fmt.Println(*hero)
}
}