类型断言
类型断言(Type Assertion)用于从接口类型中提取其底层值,检查接口变量的实际类型并转换为具体类型。
基本语法
value, ok := interfaceValue.(Type)
- interfaceValue:接口类型的变量
- Type:想要断言的类型
- value:断言成功后的具体类型值
- ok:布尔值,表示断言是否成功
断言成功时 value 是实际值,ok 为 true;断言失败时 value 是 Type 的零值,ok 为 false
package main
import "fmt"
func main() {
var i interface{} = "Hello, Go!"
// 尝试将 i 断言为 string 类型
if s, ok := i.(string); ok {
fmt.Println("断言成功:", s) // 断言成功: Hello, Go!
} else {
fmt.Println("断言失败")
}
// 尝试将 i 断言为 int 类型
if n, ok := i.(int); ok {
fmt.Println("断言成功:", n)
} else {
fmt.Println("断言失败") // 断言失败
}
}
不带 ok 的断言
另一种形式不返回布尔值,断言失败时直接触发 panic:
value := interfaceValue.(Type)
package main
import "fmt"
func main() {
var i interface{} = "Hello, Go!"
s := i.(string) // 断言成功
fmt.Println("断言成功:", s)
n := i.(int) // 断言失败,会触发 panic
fmt.Println("断言成功:", n)
}
输出结果:
断言成功: Hello, Go!
panic: interface conversion: interface {} is string, not int
建议使用带 ok 的形式,避免断言失败导致程序崩溃
类型 switch(type switch)
使用 switch v := i.(type) 根据接口变量的实际类型执行不同逻辑:
package main
import "fmt"
func printType(i interface{}) {
switch v := i.(type) {
case int:
fmt.Println("这是一个整数:", v)
case string:
fmt.Println("这是一个字符串:", v)
case float64:
fmt.Println("这是一个浮点数:", v)
default:
fmt.Println("未知类型")
}
}
func main() {
printType(42) // 这是一个整数: 42
printType("hello") // 这是一个字符串: hello
printType(3.14) // 这是一个浮点数: 3.14
printType([]int{1, 2}) // 未知类型
}
从接口中提取具体类型
处理接口变量时,可以先断言为具体类型再进行进一步操作:
package main
import "fmt"
func processInterface(i interface{}) {
if s, ok := i.(string); ok {
fmt.Println("处理字符串:", s)
} else if n, ok := i.(int); ok {
fmt.Println("处理整数:", n)
} else {
fmt.Println("无法处理的类型")
}
}
func main() {
processInterface("abc") // 处理字符串: abc
processInterface(123) // 处理整数: 123
processInterface(1.5) // 无法处理的类型
}
注意事项
- 类型断言只能用于接口类型的变量,不能用于非接口类型的变量
- 使用不返回布尔值的类型断言时,务必确保类型不会断言失败,否则会触发 panic
- 类型断言在运行时进行类型检查,会带来一定的性能开销,性能敏感场景中应谨慎使用