前言
空接口interface{}可以接收任意类型,type switch 专门用来判断空接口内部保存的动态类型,很多同学容易把它和类型断言混淆。
一、type switch 完整案例
题目要求:编写 Describe 函数,接收 any 类型参数,判断底层类型并按格式输出。
package main import "fmt" // any等价于interface{},可以接收任意类型数据 func Describe(v any) { // type switch固定语法,专门获取接口变量里面的动态类型 switch val := v.(type) { case int: fmt.Printf("This is an integer with value %d.\n", val) case string: fmt.Printf("This is a string: '%s'.\n", val) case float64: fmt.Printf("This is a float with value %g.\n", val) default: fmt.Println("Unknown type!") } } func main() { Describe(100) Describe("hello go") Describe(3.14) Describe(true) }输出结果
This is an integer with value 100. This is a string: 'hello go'. This is a float with value 3.14. Unknown type!重要知识点:
v.(type)只能写在 switch 里面,不能单独拿出来使用,这是 type switch 专属语法。和类型断言v.(int)区分开。
简答题 1:Go 接口实现为什么是非侵入式?
Go 语言没有implements关键字,不需要显式声明某个类型实现了某个接口。只要一个类型拥有接口定义的全部方法,编译器会自动判定该类型实现了这个接口。 不需要修改原有结构体的代码去添加实现声明,类型和接口之间没有强耦合,所以称为非侵入式接口。
简答题 2:interface{}和 any 的异同
相同点:any本质就是interface{}的别名,源码定义type any = interface{},底层完全一样。 不同点:
- any 是 Go1.18 引入泛型之后新增的别名,主要用于泛型约束;
interface{}是传统写法,多用于普通函数接收任意类型参数,搭配 type switch、类型断言。
运行时两者没有任何差别,只是开发编码习惯不同。
常见踩坑
- type switch 里面 case 写的是类型,不是变量。
- 空接口变量存储的包含两部分:动态类型 + 动态值。
- 非侵入式只关心方法集合,不关心类型有没有声明实现接口。
小结
- type switch 用于判断空接口存储的动态类型;普通类型断言用于单独判断某一种类型。
- Go 接口隐式实现,非侵入式,不存在 implements 关键字。
- any 就是 interface {} 别名,泛型场景推荐写 any,普通场景两种写法都可以。