Golang interface
在了解类型断言之前我们需要新了解一下interface,所以interface算是下一个博客内容的铺垫。
什么是interface,它都有什么用处?
1.interface type
就是一组方法签名的集合。我们使用一个接口来识别一个对象能够进行的操作。这也是我们最常用的方式,不管是在golang这门语言还是其他OOP类型的语言,碰到一个interface我们的第一想法是,它包含什么操作(方法)?谁实现了它?怎么实现它?
2.interface values
接口也是一种类型,那么这个接口类型的值到底是什么?一个interface可以存储任何实现了该接口的类型(里氏替换原则)。
3.The case of the empty interface
空接口类型 interface{}一个方法签名也不包含,所以所有的数据类型都实现了该方法,空接口类型interface{}在描述一个对象实例的行为上力不从心,但是当我们需要存储任意数据类型的实例的时候,空接口类型的使用当作java或者C#的object类型来使用。
func main() {
var msg interface{}
s := "Hello"
msg = s
fmt.Println(msg)
}
- 如果一个函数的参数包括空接口类型interface{},那么它可以接收任何类型
- 如果一个函数返回了一个空接口类型interface{},那么它可以返回任意类型
4.Functions with interface parameters
举例来说,我们已经知道fmt.Print 是一个可变参数的函数,他可以接受任意数量的参数。
我们来查看一下fmt.Print可接受任意数量参数的写法:
func main() {
Test("a", "b", "c", "d", "e")
}
func Test(a ...interface{}) {
for _, arg := range a {
fmt.Print(arg)
}
}
详细可以查看 fmt.Println() 是如何实现的。
这里我们顺藤摸瓜可以看到fmt包里居然有下面这个接口:
type Stringer interface {
String() string
}
那我们就尝试着去实现这个interface看一看,不出所料的我们并没有写这个inteface但是却显示实现了某个接口:
测试代码:
func main() {
a := new(A)
fmt.Println(a)
}
type A struct {
}
func (a *A) String() string {
return "可以看看实现的效果!"
}
输出:
可以看看实现的效果!
果然fmt.pringt()输出使用的是struct的tostring()方法,可以看出在标准库中还是有不少使用此类方式来实现的。
例如:sort包
func main() {
list := []int {10, 9, 8, 7, 6, 5, 4, 3, 2,1}
fmt.Println("The list is: ", list)
sort.Ints(list)
fmt.Println("The sorted list is: ", list)
}
输出:
The list is: [10 9 8 7 6 5 4 3 2 1]
The sorted list is: [1 2 3 4 5 6 7 8 9 10]
我们进入sort包内查看一下。发现如下interface
// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
实现上述接口就可以实现使用Sort进行排序,那么我们尝试一下:
package main
import (
"fmt"
"sort"
"strconv"
)
func main() {
TestSortMyStruct()
}
func TestSortMyStruct() {
group := PersonGroup{
Person{name: "zhangsan", age:24},
Person{name: "lisi", age:23},
Person{name: "wangwu", age:104},
Person{name: "tiezhu", age:44},
Person{name: "gangdan", age:34},
Person{name: "xiaoqiang", age:54},
Person{name: "xiaozhang", age:74},
Person{name: "xiaodong", age:4},
}
fmt.Println("未排序")
for _, v := range group{
fmt.Println(v)
}
sort.Sort(group)
fmt.Println("排序后")
for _, v := range group{
fmt.Println(v)
}
}
//实现了ToString()接口
type Person struct {
name string
age int
phone string
}
func (p Person) String() string {
return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
}
//实现了Sort接口
type PersonGroup []Person
func (g PersonGroup) Len() int {
return len(g)
}
func (g PersonGroup) Less(i, j int) bool {
if g[i].age < g[j].age {
return true
}
return false
}
func (g PersonGroup) Swap(i, j int){
g[i], g[j] = g[j], g[i]
}
输出:
未排序
(name: zhangsan - age: 24 years)
(name: lisi - age: 23 years)
(name: wangwu - age: 104 years)
(name: tiezhu - age: 44 years)
(name: gangdan - age: 34 years)
(name: xiaoqiang - age: 54 years)
(name: xiaozhang - age: 74 years)
(name: xiaodong - age: 4 years)
排序后
(name: xiaodong - age: 4 years)
(name: lisi - age: 23 years)
(name: zhangsan - age: 24 years)
(name: gangdan - age: 34 years)
(name: tiezhu - age: 44 years)
(name: xiaoqiang - age: 54 years)
(name: xiaozhang - age: 74 years)
(name: wangwu - age: 104 years)
可以看到实现了Sort接口我们就可以去使用sort进行排序。