Toggle navigation
主页
English
K8S
Golang
Guitar
About Me
归档
标签
Welcome to Sanger's Blog!
面向接口编程
go
2024-01-10 17:54:46
22
0
0
sanger
go
# 面向接口编程 ## 接口的基本概念 接口是一组行为规范的集合。 ```Go type Transporter interface { //定义接口。通常接口名以er结尾 //接口里面只定义方法,不定义变量 move(src string, dest string) (int, error) //方法名 (参数列表) 返回值列表 whistle(int) int //参数列表和返回值列表里的变量名可以省略 } ``` 只要结构体拥有接口里声明的所有方法,就称该结构体“实现了接口”。一个struct可以同时实现多个接口。 ```Go type Car struct { //定义结构体时无需要显式声明它要实现什么接口 price int } func (car Car) move(src string, dest string) (int, error) { return car.price, nil } func (car Car) whistle(n int) int { return n } ``` 接口值有两部分组成, 一个指向该接口的具体类型的指针和另外一个指向该具体类型真实数据的指针。 ```Go car := Car{"宝马", 100} var transporter Transporter transporter = car ``` ![title]() <img src=/api/file/getImage?fileId=64744cce40c007000b000067 width=200 /> 接口的使用 ```Go func transport(src, dest string, transporter Transporter) error { _,err := transporter.move(src, dest) return err } var car Car //Car实现了Transporter接口 var ship Shiper // Shiper实现了Transporter接口 transport("北京", "天津", car) transport("北京", "天津", ship) ``` 接口的赋值 ```Go func (car Car) whistle(n int) int {…}//方法接收者是值 func (ship *Shiper) whistle(n int) int {…} //方法接收者用指针,则实现接口的是指针类型 car := Car{} ship := Shiper{} var transporter Transporter transporter = car transporter = &car //值实现的方法,指针同样也实现了 transporter = &ship ``` ## 接口嵌入 ```Go type Transporter interface { whistle(int) int } type Steamer interface { Transporter //接口嵌入。相当于Transporter接口定义的行为集合是Steamer的子集 displacement() int } ``` ## 空接口 空接口类型用interface{}表示,注意有{}。 ```Go var i interface{} ``` 空接口没有定义任何方法,因此任意类型都实现了空接口。 ```Go var a int = 5 i = a ``` ```Go func square(x interface{}){} //该函数可以接收任意数据类型 ``` slice的元素、map的key和value都可以是空接口类型。map中的key可以是任意能够用==操作符比较的类型,不能是函数、map、切片,以及包含上述3中类型成员变量的的struct。map的value可以是任意类型。 ## 类型断言 ```Go if v, ok := i.(int); ok {//若断言成功,则ok为true,v是具体的类型 fmt.Printf("i是int类型,其值为%d\n", v) } else { fmt.Println("i不是int类型") } ``` 当要判断的类型比较多时,就需要写很多if-else,更好的方法是使用switch i.(type)。 ```Go switch v := i.(type) { //隐式地在每个case中声明了一个变量v case int: //v已被转为int类型 fmt.Printf("ele is int, value is %d\n", v) //在 Type Switch 语句的 case 子句中不能使用fallthrough case float64: //v已被转为float64类型 fmt.Printf("ele is float64, value is %f\n", v) case int8, int32, byte: //如果case后面跟多种type,则v还是interface{}类型 fmt.Printf("ele is %T, value is %d\n", v, v) } ``` ## 面向接口编程 电商推荐流程 ![title]() <img src=/api/file/getImage?fileId=64744cef40c007000b000068 width=700 /> 为每一个步骤定义一个接口。 ```Go type Recaller interface { Recall(n int) []*common.Product //生成一批推荐候选集 } type Sorter interface { Sort([]*common.Product) []*common.Product //传入一批商品,返回排序之后的商品 } type Filter interface { Filter([]*common.Product) []*common.Product //传入一批商品,返回过滤之后的商品 } type Recommender struct { Recallers []recall.Recaller Sorter sort.Sorter Filters []filter.Filter } ``` 使用纯接口编写推荐主流程。 ```Go func (rec *Recommender) Rec() []*common.Product { RecallMap := make(map[int]*common.Product, 100) //顺序执行多路召回 for _, recaller := range rec.Recallers { products := recaller.Recall(10) //统一设置每路最多召回10个商品 for _, product := range products { RecallMap[product.Id] = product //把多路召回的结果放到map里,按Id进行排重 } } //把map转成slice RecallSlice := make([]*common.Product, 0, len(RecallMap)) for _, product := range RecallMap { RecallSlice = append(RecallSlice, product) } SortedResult := rec.Sorter.Sort(RecallSlice) //对召回的结果进行排序 //顺序执行多种过滤规则 FilteredResult := SortedResult for _, filter := range rec.Filters { FilteredResult = filter.Filter(FilteredResult) } return FilteredResult } ``` 面向接口编程,在框架层面全是接口。具体的实现由不同的开发者去完成,每种实现单独放到一个go文件里,大家的代码互不干扰。通过配置选择采用哪种实现,也方便进行效果对比。
上一篇:
函数
下一篇:
流程控制语句
0
赞
22 人读过
新浪微博
微信
更多分享
腾讯微博
QQ空间
人人网
文档导航