编程语言 15、接口-GOLANG xiu 2023-05-13 2024-11-27 概念 圆珠笔是一个确切的用于写字的物品,而能够用于写字的物件是一个抽象概念,其中不只有圆珠笔这一个物品,代码中的int,string类型是一个确切的类型,而接口则表达了一种抽象的概念
int类型用于存储整数,string类型用于存储文本,他们非常关心自己存储了什么
接口不关心存储的东西,接口只关心能够做什么
接口类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport "fmt" var t interface { talk() string } type martian struct {}type laser int func (m martian) talk() string { return "martian" } func (l laser) talk() string { return "laser" } func main () { ma := martian{} t = ma fmt.Println(t.talk()) var la laser t = la fmt.Println(t.talk()) }
为了便于复用,我们一般会把接口声明为类型为其命名,按照惯例,接口类型的名称通常以er作为后缀
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package mainimport ( "fmt" "strings" ) type talker interface { talk() string } type martian struct {}type laser int func shout (t talker) { louder := strings.ToUpper(t.talk()) fmt.Println(louder) } func (m martian) talk() string { return "martian" } func (l laser) talk() string { return "laser" } func main () { shout(martian{}) var la laser shout(la) }
通过嵌入式满足接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package mainimport ( "fmt" "strings" ) type talker interface { talk() string } type martian struct {}type laser int type starship struct { laser } func shout (t talker) { louder := strings.ToUpper(t.talk()) fmt.Println(louder) } func (m martian) talk() string { return "martian" } func (l laser) talk() string { return "laser" } func main () { var la laser s := starship{la} fmt.Println(s.talk()) shout(s) }
探索接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport ( "fmt" "time" ) func stardate (t time.Time) float64 { doy := float64 (t.YearDay()) h := float64 (t.Hour()) / 24.0 return 1000 + doy + h } func main () { day := time.Date(2023 , 3 , 11 , 10 , 11 , 0 , 0 , time.UTC) fmt.Printf("%f好奇号火星探测器着陆" , stardate(day)) }
上面这个虚假的计算星历的函数只能使用地球日期作为输入,我们接下来利用接口实现更复杂的输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package mainimport ( "fmt" "time" ) type stardater interface { YearDay() int Hour() int } type sol int func (s sol) YearDay() int { return int (s % 668 ) } func (s sol) Hour() int { return 0 } func stardate (t stardater) float64 { doy := float64 (t.YearDay()) h := float64 (t.Hour()) / 24.0 return 1000 + doy + h } func main () { day := time.Date(2023 , 3 , 11 , 10 , 11 , 0 , 0 , time.UTC) fmt.Printf("%f好奇号火星探测器着陆\n" , stardate(day)) s := sol(1422 ) fmt.Println(stardate(s)) }
满足接口 go语言标准库导出了很多只有单个方法的接口,开发者可以在自己的代码中实现他们
例如fmt包的Stringer接口,一种类型只要提供了String方法,他的值就可以被Println等函数打印
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport "fmt" type location struct { lat, long float64 } func (l location) String() string { return "0" } func main () { curiosity := location{-4.3243 , 137.1111 } fmt.Println(curiosity) }
这个时候聪明的小伙伴会有疑惑了,为什么我们平时打印文本或者其他各种类型的变量之前也妹实现接口啊,为啥也能打印呢
空接口没有任何方法,因此任何类型都无须实现空接口。
从实现的角度看,任何值都满足这个接口的需求。因此空接口类型可以保存任何值,也可以从空接口中取出原值。
so,任何值都可以被Println这个函数接受,Printf,Print同理