接口是一组函数声明,当某个对象实现了接口声明的函数就作为实现了接口,接口的实现是隐式的
Go
// Shape 是接口类型: 任何实现了这两个方法的类型都自动满足它, 无需显式声明(隐式实现)。
type Shape interface { // 接口只描述行为, 不描述数据
Area() float64 // 面积方法
Perimeter() float64 // 周长方法
} // Shape 定义结束
// Rect 矩形, 通过值接收者方法实现 Shape。
type Rect struct { // 结构体实现接口
W float64 // 宽
H float64 // 高
} // Rect 定义结束
// Area 计算矩形面积, 实现 Shape。
// 参数/接收者 r: 矩形值副本。
// 返回: 面积。
func (r Rect) Area() float64 { // 满足 Shape.Area
return r.W * r.H // 宽乘高
} // 方法结束
// Perimeter 计算矩形周长, 实现 Shape。
// 参数/接收者 r: 矩形值副本。
// 返回: 周长。
func (r Rect) Perimeter() float64 { // 满足 Shape.Perimeter
return 2 * (r.W + r.H) // 两倍的(宽 + 高)
} // 方法结束
// Circle 圆, 同样实现 Shape。
type Circle struct { // 结构体实现接口
R float64 // 半径
} // Circle 定义结束
// Area 计算圆面积, 实现 Shape。
// 参数/接收者 c: 圆值副本。
// 返回: 面积。
func (c Circle) Area() float64 { // 满足 Shape.Area
return math.Pi * c.R * c.R // πr²
} // 方法结束
// Perimeter 计算圆周长, 实现 Shape。
// 参数/接收者 c: 圆值副本。
// 返回: 周长。
func (c Circle) Perimeter() float64 { // 满足 Shape.Perimeter
return 2 * math.Pi * c.R // 2πr
} // 方法结束
当一个函数的形参要求的是接口Shape 的时候,我们就可以传递任意实现该接口的类型了如Circle和Rect,都可以作为合法参数传递
Go
// TotalArea 演示面向接口的多态: 任何满足 Shape 的值都能传进来。
// 参数 shapes: 由多个 Shape 实现组成的切片。
// 返回: 所有图形面积之和。
func TotalArea(shapes ...Shape) float64 { // 参数是接口切片
total := 0.0 // 累加器
for _, s := range shapes { // 遍历接口值
total += s.Area() // 动态派发: 运行时按动态类型查找方法
} // range 结束
return total // 返回总面积
} // 函数结束
同时interface{}和any作为一个接口作为参数的时候,可以在函数的内部进行断言判断类型是什么
语法格式是:对象.(类型)。switch语句可以使用对象.(type)然后case具体的类型做判断
Go
func main() {
var u any
//var u2 interface{}
u = "123"
defer func() {
if recover() != nil {
fmt.Println("panic")
fmt.Println("断言失败")
}
}()
if u.(string) != "" {
fmt.Println("断言success")
}
}
类型断言的经典安全形式是v, ok := x.(T),v是断言后确定的值
对于任意数值切片求和,演示泛型函数与类型参数
既然是求和函数,接收参数是限定在int float这几个里面的。但是又不能每一个类型都单独的去写一个求和,所以这里就是用类型参数约束
Go
type Tnumber interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}
func Sum[t Tnumber](numbers []t) t {
var sum t
for _, number := range numbers {
sum += number
}
return sum
}
func main() {
fmt.Println(Sum([]int{1, -2, 3, 4, 5}))
}