接口声明
// 接口声明 语法:接口是一个 函数签名 的集合,函数签名(函数的声明,不包括实现) 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) } }