type Transporter interface{//定义接口,通常接口名以er结尾//接口里面只定义方法,不定义变量move(src string, dest string)(int,error)//方法名 (参数列表) 返回值列表whistle(int)int//参数列表和返回值列表里的变量名可以省略}
接口的实现:
只要结构体拥有接口里声明的所有方法,就称该结构体“实现了接口”
一个struct可以同时实现多个接口
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
}
接口的本质:接口值有两部分组成
一个指向该接口的具体类型的指针
另外一个指向该具体类型真实数据的指针
type Transporter interface{//定义接口,通常接口名以er结尾//接口里面只定义方法,不定义变量move(src string, dest string)(int,error)//方法名 (参数列表) 返回值列表whistle(int)int//参数列表和返回值列表里的变量名可以省略}type Car struct{//定义结构体时无需要显式声明它要实现什么接口
name string
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
}funcmain(){
car := Car{"宝马",100}var transpoter Transporter
transpoter = car
transpoter.whistle(3)}
接口的使用:实现了接口后,在函数中传递接口参数作为形参,可以使用具体的接口实现作为实参
type Transporter interface{//定义接口,通常接口名以er结尾//接口里面只定义方法,不定义变量move(src string, dest string)(int,error)//方法名 (参数列表) 返回值列表whistle(int)int//参数列表和返回值列表里的变量名可以省略}type Car struct{//定义结构体时无需要显式声明它要实现什么接口
name string
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
}type Ship struct{//定义结构体时无需要显式声明它要实现什么接口
name string
price int}func(ship Ship)move(src string, dest string)(int,error){return ship.price,nil}func(ship Ship)whistle(n int)int{return n
}// 实现了接口后,在函数中传递接口参数作为形参,可以使用具体的接口实现作为实参functransport(src, dest string, transpoter Transporter)error{_, err := transpoter.move(src, dest)return err
}funcmain(){var car Car //Car实现了Transporter接口var ship Ship //Ship实现了Transporter接口transport("北京","天津", car)transport("北京","天津", ship)}
接口的赋值
值实现的方法,指针也同样实现了
指针实现的方法,只能使用指针进行接口的赋值
type Car struct{//定义结构体时无需要显式声明它要实现什么接口
name string
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
}type Ship struct{//定义结构体时无需要显式声明它要实现什么接口
name string
price int}func(ship *Ship)move(src string, dest string)(int,error){return ship.price,nil}func(ship *Ship)whistle(n int)int{return n
}functransport(src, dest string, transpoter Transporter)error{_, err := transpoter.move(src, dest)return err
}funcmain(){var car Car //Car实现了Transporter接口var ship Ship //Ship实现了Transporter接口transport("北京","天津", car)transport("北京","天津",&car)// transport("北京", "天津", ship) //错误,指针实现的方法不能使用值赋值transport("北京","天津",&ship)//指针实现的方法只能使用指针赋值}
type Transporter interface{whistle(int)int}type Steamer interface{
Transporter //接口嵌入,相当于Transporter接口定义的行为集合是Steamer的子集displacement()int}
二、类型断言
类型断言
funcmain(){var i interface{}if v, ok := i.(int); ok {//若断言成功,则ok为true,v是具体的类型
fmt.Printf("i是int类型,其值为%d\n", v)}else{
fmt.Println("i不是int类型")}//i不是int类型}
当要判断的类型比较多时,更好的方法是使用switch i.(type)
funcassert(i interface{}){switch v := i.(type){//隐式地在每个case中声明了一个变量vcaseint://v已被转为int类型
fmt.Printf("%d\n", v)casefloat64:
fmt.Printf("%f\n", v)casebyte,uint16,string://如果case后面跟多种type,则v还是interface{}类型
fmt.Printf("%T %v\n", v, v)}}funcassert2(i interface{}){switch i.(type){caseint:
v := i.(int)
fmt.Printf("%d\n", v)casefloat64:
v := i.(float64)
fmt.Printf("%f\n", v)casebyte,uint16,string:
fmt.Printf("%T %v\n", i, i)}}funcmain(){var i interface{}var a intvar b float64var c byte
i = a
assert(i)//0assert2(i)//0
i = b
assert(i)//0.000000assert2(i)//0.000000
i = c
assert(i)//uint8 0assert2(i)//uint8 0}
type HotRecall struct{
Tag string}func(hotrecall HotRecall)Name()string{return hotrecall.Tag
}func(hotrecall HotRecall)Recall(n int)[]*Product {//按销量降序排序
sort.Slice(allProducts,func(i, j int)bool{return allProducts[i].Sale > allProducts[j].Sale
})//返回前n个
rect :=make([]*Product,0, n)for i, ele :=range allProducts {if i >= n {break}
rect =append(rect, ele)}return rect
}
size -> 召回接口实现
type SizeRecall struct{
Tag string}func(sizerecall SizeRecall)Name()string{return sizerecall.Tag
}func(sizerecall SizeRecall)Recall(n int)[]*Product {
rect :=make([]*Product,0, n)for_, ele :=range allProducts {if ele.Size <200{//只召回size小于200的商品
rect =append(rect, ele)iflen(rect)>= n {break}}}return rect
}
size -> 排序接口实现
type SizeSorter struct{
Tag string}func(sizesorter SizeSorter)Name()string{return sizesorter.Tag
}func(sizesorter SizeSorter)Sort(products []*Product)[]*Product {
sort.Slice(products,func(i, j int)bool{//按尺寸升序排列return products[i].Size > products[j].Size
})return products
}
评价 -> 排序接口实现
type RatioSorter struct{
Tag string}func(ratiosorter RatioSorter)Name()string{return ratiosorter.Tag
}func(ratiosorter RatioSorter)Sort(products []*Product)[]*Product {
sort.Slice(products,func(i, j int)bool{//按好评率降序排列return products[i].PositiveRatio > products[j].PositiveRatio
})return products
}
1、N 皇后(数组,回溯)
n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 …