Files
golang/golang-learning/05-interfaces/03-type-assertions.go
2025-08-24 11:24:52 +08:00

1058 lines
25 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
03-type-assertions.go - Go 语言类型断言详解
学习目标:
1. 掌握类型断言的语法和用法
2. 理解类型断言的安全性
3. 学会类型 switch 的使用
4. 了解接口类型断言的应用
5. 掌握类型断言的最佳实践
知识点:
- 类型断言的基本语法
- 安全类型断言 vs 不安全类型断言
- 类型 switch 语句
- 接口到具体类型的断言
- 接口到接口的断言
- 类型断言的性能考虑
- 类型断言的实际应用场景
*/
package main
import (
"fmt"
"io"
"strings"
)
func main() {
fmt.Println("=== Go 语言类型断言详解 ===\\n")
// 演示基本类型断言
demonstrateBasicTypeAssertions()
// 演示安全 vs 不安全类型断言
demonstrateSafeVsUnsafeAssertions()
// 演示类型 switch
demonstrateTypeSwitchExamples()
// 演示接口类型断言
demonstrateInterfaceAssertions()
// 演示类型断言的实际应用
demonstratePracticalApplications()
// 演示类型断言的高级用法
demonstrateAdvancedUsageExamples()
// 演示类型断言的最佳实践
demonstrateBestPracticesExamples()
}
// demonstrateBasicTypeAssertions 演示基本类型断言
func demonstrateBasicTypeAssertions() {
fmt.Println("1. 基本类型断言:")
// 类型断言的基本语法
fmt.Printf(" 类型断言的基本语法:\\n")
fmt.Printf(" value.(Type) - 不安全断言,失败时 panic\\n")
fmt.Printf(" value, ok := value.(Type) - 安全断言,返回值和布尔标志\\n")
// 基本类型断言示例
fmt.Printf(" 基本类型断言示例:\\n")
var value interface{} = "Hello, World!"
// 安全的类型断言
if str, ok := value.(string); ok {
fmt.Printf(" 字符串断言成功: \\\"%s\\\" (长度: %d)\\n", str, len(str))
} else {
fmt.Printf(" 字符串断言失败\\n")
}
// 断言为整数(会失败)
if num, ok := value.(int); ok {
fmt.Printf(" 整数断言成功: %d\\n", num)
} else {
fmt.Printf(" 整数断言失败,实际类型: %T\\n", value)
}
// 不同类型的断言
fmt.Printf(" 不同类型的断言:\\n")
values := []interface{}{
42,
3.14159,
true,
"Go语言",
[]int{1, 2, 3},
map[string]int{"key": 100},
Person{Name: "Alice", Age: 30},
}
for i, v := range values {
fmt.Printf(" 值 %d (%v):\\n", i+1, v)
// 尝试断言为不同类型
if intVal, ok := v.(int); ok {
fmt.Printf(" -> 整数: %d\\n", intVal)
} else if floatVal, ok := v.(float64); ok {
fmt.Printf(" -> 浮点数: %.3f\\n", floatVal)
} else if boolVal, ok := v.(bool); ok {
fmt.Printf(" -> 布尔值: %t\\n", boolVal)
} else if strVal, ok := v.(string); ok {
fmt.Printf(" -> 字符串: \\\"%s\\\"\\n", strVal)
} else {
fmt.Printf(" -> 其他类型: %T\\n", v)
}
}
fmt.Println()
}
// demonstrateSafeVsUnsafeAssertions 演示安全 vs 不安全类型断言
func demonstrateSafeVsUnsafeAssertions() {
fmt.Println("2. 安全 vs 不安全类型断言:")
// 安全类型断言
fmt.Printf(" 安全类型断言 (推荐):\\n")
var value interface{} = 42
// 安全断言 - 返回值和布尔标志
if str, ok := value.(string); ok {
fmt.Printf(" 字符串断言成功: %s\\n", str)
} else {
fmt.Printf(" 字符串断言失败,实际类型: %T值: %v\\n", value, value)
}
if num, ok := value.(int); ok {
fmt.Printf(" 整数断言成功: %d\\n", num)
} else {
fmt.Printf(" 整数断言失败\\n")
}
// 不安全类型断言
fmt.Printf(" 不安全类型断言 (谨慎使用):\\n")
// 成功的不安全断言
num := value.(int)
fmt.Printf(" 不安全整数断言成功: %d\\n", num)
// 失败的不安全断言(会 panic
fmt.Printf(" 演示不安全断言的 panic 风险:\\n")
// 使用 defer 和 recover 捕获 panic
func() {
defer func() {
if r := recover(); r != nil {
fmt.Printf(" 捕获到 panic: %v\\n", r)
}
}()
// 这会导致 panic
str := value.(string)
fmt.Printf(" 不安全字符串断言: %s\\n", str)
}()
// 安全断言的实际应用
fmt.Printf(" 安全断言的实际应用:\\n")
data := []interface{}{
"hello",
42,
3.14,
true,
nil,
}
for i, item := range data {
fmt.Printf(" 处理项目 %d:\\n", i+1)
processItemSafely(item)
}
fmt.Println()
}
// demonstrateTypeSwitchExamples 演示类型 switch
func demonstrateTypeSwitchExamples() {
fmt.Println("3. 类型 switch:")
fmt.Printf(" 类型 switch 是处理多种类型的优雅方式\\n")
// 基本类型 switch
fmt.Printf(" 基本类型 switch:\\n")
values := []interface{}{
42,
"Hello",
3.14159,
true,
[]int{1, 2, 3},
map[string]int{"a": 1, "b": 2},
Person{Name: "Alice", Age: 30},
&Person{Name: "Bob", Age: 25},
nil,
}
for i, value := range values {
fmt.Printf(" 值 %d: ", i+1)
processWithTypeSwitch(value)
}
// 类型 switch 的高级用法
fmt.Printf(" 类型 switch 的高级用法:\\n")
// 处理不同的数值类型
numbers := []interface{}{
int(42),
int8(8),
int16(16),
int32(32),
int64(64),
uint(42),
float32(3.14),
float64(2.718),
}
fmt.Printf(" 数值类型处理:\\n")
for _, num := range numbers {
result := convertToFloat64(num)
fmt.Printf(" %v (%T) -> %.3f\\n", num, num, result)
}
// 类型 switch 与接口
fmt.Printf(" 类型 switch 与接口:\\n")
shapes := []Shape{
Circle{Radius: 5},
Rectangle{Width: 4, Height: 6},
Triangle{Base: 8, Height: 6},
}
for i, shape := range shapes {
fmt.Printf(" 形状 %d: ", i+1)
describeShape(shape)
}
fmt.Println()
}
// demonstrateInterfaceAssertions 演示接口类型断言
func demonstrateInterfaceAssertions() {
fmt.Println("4. 接口类型断言:")
// 接口到具体类型的断言
fmt.Printf(" 接口到具体类型的断言:\\n")
var shape Shape = Circle{Radius: 5}
// 断言为具体类型
if circle, ok := shape.(Circle); ok {
fmt.Printf(" 断言为圆形成功: 半径 = %.1f\\n", circle.Radius)
fmt.Printf(" 圆形面积: %.2f\\n", circle.Area())
fmt.Printf(" 圆形周长: %.2f\\n", circle.Perimeter())
}
if rect, ok := shape.(Rectangle); ok {
fmt.Printf(" 断言为矩形成功: %dx%d\\n", int(rect.Width), int(rect.Height))
} else {
fmt.Printf(" 断言为矩形失败,实际类型: %T\\n", shape)
}
// 接口到接口的断言
fmt.Printf(" 接口到接口的断言:\\n")
var writer io.Writer = &strings.Builder{}
// 断言为更具体的接口
if stringWriter, ok := writer.(io.StringWriter); ok {
fmt.Printf(" 支持 StringWriter 接口\\n")
n, err := stringWriter.WriteString("Hello, Interface!")
if err == nil {
fmt.Printf(" 写入字符串成功: %d 字节\\n", n)
}
}
// 检查接口是否支持其他方法
if closer, ok := writer.(io.Closer); ok {
fmt.Printf(" 支持 Closer 接口\\n")
closer.Close()
} else {
fmt.Printf(" 不支持 Closer 接口\\n")
}
// 多接口断言
fmt.Printf(" 多接口断言:\\n")
var device Device = &NetworkDevice{
name: "路由器",
address: "192.168.1.1",
}
// 检查设备支持的接口
fmt.Printf(" 设备: %s\\n", device.GetName())
if networkable, ok := device.(Networkable); ok {
fmt.Printf(" 支持网络功能: %s\\n", networkable.GetAddress())
}
if configurable, ok := device.(Configurable); ok {
config := configurable.GetConfig()
fmt.Printf(" 支持配置功能: %v\\n", config)
}
if manageable, ok := device.(Manageable); ok {
status := manageable.GetStatus()
fmt.Printf(" 支持管理功能: %s\\n", status)
}
fmt.Println()
}
// demonstratePracticalApplications 演示类型断言的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 类型断言的实际应用:")
// 应用1: 错误处理
fmt.Printf(" 应用1 - 错误处理:\\n")
errors := []error{
&ValidationError{Field: "email", Message: "无效的邮箱格式"},
&NetworkError{Code: 500, Message: "服务器内部错误"},
fmt.Errorf("普通错误"),
}
for i, err := range errors {
fmt.Printf(" 错误 %d: ", i+1)
handleError(err)
}
// 应用2: 插件系统
fmt.Printf(" 应用2 - 插件系统:\\n")
plugins := []Plugin{
&LoggingPlugin{Level: "INFO"},
&CachePlugin{Size: 1000},
&SecurityPlugin{Enabled: true},
}
pluginManager := PluginManager{plugins: plugins}
pluginManager.ExecuteAll("测试数据")
// 应用3: 数据序列化
fmt.Printf(" 应用3 - 数据序列化:\\n")
serializer := DataSerializer{}
data := []interface{}{
Person{Name: "Alice", Age: 30},
&Person{Name: "Bob", Age: 25},
[]int{1, 2, 3, 4, 5},
map[string]interface{}{
"name": "Charlie",
"age": 35,
},
}
for i, item := range data {
serialized := serializer.Serialize(item)
fmt.Printf(" 数据 %d: %s\\n", i+1, serialized)
}
// 应用4: 类型转换器
fmt.Printf(" 应用4 - 类型转换器:\\n")
converter := TypeConverter{}
values := []interface{}{
42,
"123",
3.14,
true,
"false",
}
for _, value := range values {
strResult := converter.ToString(value)
intResult := converter.ToInt(value)
boolResult := converter.ToBool(value)
fmt.Printf(" %v (%T):\\n", value, value)
fmt.Printf(" -> 字符串: \\\"%s\\\"\\n", strResult)
fmt.Printf(" -> 整数: %d\\n", intResult)
fmt.Printf(" -> 布尔值: %t\\n", boolResult)
}
fmt.Println()
}
// demonstrateAdvancedUsageExamples 演示类型断言的高级用法
func demonstrateAdvancedUsageExamples() {
fmt.Println("6. 类型断言的高级用法:")
// 高级用法1: 链式类型断言
fmt.Printf(" 高级用法1 - 链式类型断言:\\n")
var value interface{} = &strings.Builder{}
// 链式断言检查多个接口
if writer, ok := value.(io.Writer); ok {
fmt.Printf(" 支持 Writer 接口\\n")
if stringWriter, ok := writer.(io.StringWriter); ok {
fmt.Printf(" 同时支持 StringWriter 接口\\n")
stringWriter.WriteString("链式断言测试")
}
if stringer, ok := writer.(fmt.Stringer); ok {
fmt.Printf(" 同时支持 Stringer 接口: %s\\n", stringer.String())
}
}
// 高级用法2: 类型断言与反射结合
fmt.Printf(" 高级用法2 - 类型断言与反射结合:\\n")
inspector := TypeInspector{}
testValues := []interface{}{
Person{Name: "Alice", Age: 30},
&Person{Name: "Bob", Age: 25},
[]Person{{Name: "Charlie", Age: 35}},
map[string]Person{"key": {Name: "David", Age: 40}},
}
for i, value := range testValues {
fmt.Printf(" 检查值 %d:\\n", i+1)
inspector.InspectWithAssertion(value)
}
// 高级用法3: 动态方法调用
fmt.Printf(" 高级用法3 - 动态方法调用:\\n")
objects := []interface{}{
&Calculator{},
&Formatter{},
&Validator{},
}
for i, obj := range objects {
fmt.Printf(" 对象 %d:\\n", i+1)
callMethodsDynamically(obj)
}
// 高级用法4: 接口适配器模式
fmt.Printf(" 高级用法4 - 接口适配器模式:\\n")
// 旧接口实现
oldLogger := &OldLogger{}
// 使用适配器
var newLogger Logger = &LoggerAdapter{oldLogger: oldLogger}
newLogger.Log("这是通过适配器记录的日志")
// 检查适配器是否支持额外功能
if advancedLogger, ok := newLogger.(AdvancedLogger); ok {
advancedLogger.LogWithContext("错误消息", map[string]string{
"user_id": "123",
"action": "login",
})
}
fmt.Println()
}
// demonstrateBestPracticesExamples 演示类型断言的最佳实践
func demonstrateBestPracticesExamples() {
fmt.Println("7. 类型断言的最佳实践:")
fmt.Printf(" 最佳实践原则:\\n")
fmt.Printf(" 1. 总是使用安全的类型断言(检查 ok 值)\\n")
fmt.Printf(" 2. 优先使用类型 switch 处理多种类型\\n")
fmt.Printf(" 3. 在断言失败时提供有意义的错误处理\\n")
fmt.Printf(" 4. 避免过深的类型断言链\\n")
fmt.Printf(" 5. 考虑使用接口而不是具体类型断言\\n")
// 最佳实践示例
fmt.Printf(" 最佳实践示例:\\n")
// 1. 安全的类型断言
fmt.Printf(" 1. 安全的类型断言:\\n")
var data interface{} = "test data"
result, err := safeStringAssertion(data)
if err != nil {
fmt.Printf(" 断言失败: %v\\n", err)
} else {
fmt.Printf(" 断言成功: %s\\n", result)
}
// 2. 优雅的错误处理
fmt.Printf(" 2. 优雅的错误处理:\\n")
values := []interface{}{
"valid string",
42,
nil,
}
for i, value := range values {
result, err := safeStringAssertion(value)
fmt.Printf(" 值 %d: ", i+1)
if err != nil {
fmt.Printf("错误 - %v\\n", err)
} else {
fmt.Printf("成功 - \\\"%s\\\"\\n", result)
}
}
// 3. 接口优先的设计
fmt.Printf(" 3. 接口优先的设计:\\n")
// 好的做法:依赖接口而不是具体类型
var processor DataProcessor = &JSONProcessor{}
// 检查是否支持额外功能
if validator, ok := processor.(DataValidator); ok {
fmt.Printf(" 处理器支持数据验证\\n")
isValid := validator.Validate(`{"name": "Alice"}`)
fmt.Printf(" 数据验证结果: %t\\n", isValid)
}
if formatter, ok := processor.(DataFormatter); ok {
fmt.Printf(" 处理器支持数据格式化\\n")
formatted := formatter.Format(`{"name":"Alice","age":30}`)
fmt.Printf(" 格式化结果: %s\\n", formatted)
}
// 4. 性能考虑
fmt.Printf(" 4. 性能考虑:\\n")
fmt.Printf(" - 类型断言有运行时开销\\n")
fmt.Printf(" - 在热点代码中谨慎使用\\n")
fmt.Printf(" - 考虑缓存断言结果\\n")
fmt.Printf(" - 优先使用具体类型而不是接口\\n")
// 5. 常见陷阱
fmt.Printf(" 5. 避免常见陷阱:\\n")
fmt.Printf(" - 不要忽略断言的 ok 返回值\\n")
fmt.Printf(" - 注意 nil 接口的断言行为\\n")
fmt.Printf(" - 理解接口的动态类型和动态值\\n")
fmt.Printf(" - 避免对 nil 值进行类型断言\\n")
// 演示 nil 接口断言
var nilInterface interface{}
if str, ok := nilInterface.(string); ok {
fmt.Printf(" nil 断言成功: %s\\n", str)
} else {
fmt.Printf(" nil 接口断言失败(正确行为)\\n")
}
fmt.Println()
}
/
/ ========== 类型定义 ==========
// 基本结构体
type Person struct {
Name string
Age int
}
// 几何图形接口和实现
type Shape interface {
Area() float64
Perimeter() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
type Triangle struct {
Base, Height float64
}
func (t Triangle) Area() float64 {
return 0.5 * t.Base * t.Height
}
func (t Triangle) Perimeter() float64 {
// 假设是等腰三角形
side := (t.Base*t.Base + 4*t.Height*t.Height) / (2 * t.Base)
return t.Base + 2*side
}
// 设备接口系统
type Device interface {
GetName() string
}
type Networkable interface {
GetAddress() string
}
type Configurable interface {
GetConfig() map[string]string
}
type Manageable interface {
GetStatus() string
}
type NetworkDevice struct {
name string
address string
}
func (nd *NetworkDevice) GetName() string {
return nd.name
}
func (nd *NetworkDevice) GetAddress() string {
return nd.address
}
func (nd *NetworkDevice) GetConfig() map[string]string {
return map[string]string{
"ip": nd.address,
"type": "network",
}
}
func (nd *NetworkDevice) GetStatus() string {
return "online"
}
// 错误类型
type ValidationError struct {
Field string
Message string
}
func (ve *ValidationError) Error() string {
return fmt.Sprintf("验证错误 [%s]: %s", ve.Field, ve.Message)
}
type NetworkError struct {
Code int
Message string
}
func (ne *NetworkError) Error() string {
return fmt.Sprintf("网络错误 [%d]: %s", ne.Code, ne.Message)
}
// 插件系统
type Plugin interface {
Execute(data string) string
}
type LoggingPlugin struct {
Level string
}
func (lp *LoggingPlugin) Execute(data string) string {
return fmt.Sprintf("[%s] 日志: %s", lp.Level, data)
}
type CachePlugin struct {
Size int
}
func (cp *CachePlugin) Execute(data string) string {
return fmt.Sprintf("缓存 (大小:%d): %s", cp.Size, data)
}
type SecurityPlugin struct {
Enabled bool
}
func (sp *SecurityPlugin) Execute(data string) string {
if sp.Enabled {
return fmt.Sprintf("安全检查通过: %s", data)
}
return fmt.Sprintf("安全检查跳过: %s", data)
}
type PluginManager struct {
plugins []Plugin
}
func (pm *PluginManager) ExecuteAll(data string) {
for i, plugin := range pm.plugins {
result := plugin.Execute(data)
fmt.Printf(" 插件 %d 结果: %s\\n", i+1, result)
}
}
// 数据序列化器
type DataSerializer struct{}
func (ds DataSerializer) Serialize(data interface{}) string {
switch v := data.(type) {
case Person:
return fmt.Sprintf("Person{Name:%s,Age:%d}", v.Name, v.Age)
case *Person:
return fmt.Sprintf("*Person{Name:%s,Age:%d}", v.Name, v.Age)
case []int:
return fmt.Sprintf("[]int%v", v)
case map[string]interface{}:
return fmt.Sprintf("map%v", v)
default:
return fmt.Sprintf("%T(%v)", v, v)
}
}
// 类型转换器
type TypeConverter struct{}
func (tc TypeConverter) ToString(value interface{}) string {
switch v := value.(type) {
case string:
return v
case int:
return strconv.Itoa(v)
case float64:
return strconv.FormatFloat(v, 'f', -1, 64)
case bool:
return strconv.FormatBool(v)
default:
return fmt.Sprintf("%v", v)
}
}
func (tc TypeConverter) ToInt(value interface{}) int {
switch v := value.(type) {
case int:
return v
case string:
if num, err := strconv.Atoi(v); err == nil {
return num
}
case float64:
return int(v)
case bool:
if v {
return 1
}
return 0
}
return 0
}
func (tc TypeConverter) ToBool(value interface{}) bool {
switch v := value.(type) {
case bool:
return v
case string:
return v == "true"
case int:
return v != 0
case float64:
return v != 0.0
}
return false
}
// 类型检查器
type TypeInspector struct{}
func (ti TypeInspector) InspectWithAssertion(value interface{}) {
// 使用类型断言检查不同类型
if person, ok := value.(Person); ok {
fmt.Printf(" Person 值类型: %s, %d岁\\n", person.Name, person.Age)
} else if personPtr, ok := value.(*Person); ok {
fmt.Printf(" Person 指针类型: %s, %d岁\\n", personPtr.Name, personPtr.Age)
} else if personSlice, ok := value.([]Person); ok {
fmt.Printf(" Person 切片类型: %d 个元素\\n", len(personSlice))
} else if personMap, ok := value.(map[string]Person); ok {
fmt.Printf(" Person 映射类型: %d 个键值对\\n", len(personMap))
} else {
fmt.Printf(" 未知类型: %T\\n", value)
}
}
// 动态方法调用相关类型
type Calculator struct{}
func (c *Calculator) Add(a, b int) int {
return a + b
}
func (c *Calculator) GetType() string {
return "Calculator"
}
type Formatter struct{}
func (f *Formatter) Format(text string) string {
return fmt.Sprintf("[格式化] %s", text)
}
func (f *Formatter) GetType() string {
return "Formatter"
}
type Validator struct{}
func (v *Validator) Validate(data string) bool {
return len(data) > 0
}
func (v *Validator) GetType() string {
return "Validator"
}
// 日志系统
type Logger interface {
Log(message string)
}
type AdvancedLogger interface {
LogWithContext(message string, context map[string]string)
}
type OldLogger struct{}
func (ol *OldLogger) WriteLog(level, message string) {
fmt.Printf(" [旧日志系统] %s: %s\\n", level, message)
}
type LoggerAdapter struct {
oldLogger *OldLogger
}
func (la *LoggerAdapter) Log(message string) {
la.oldLogger.WriteLog("INFO", message)
}
func (la *LoggerAdapter) LogWithContext(message string, context map[string]string) {
contextStr := ""
for k, v := range context {
contextStr += fmt.Sprintf("%s=%s ", k, v)
}
la.oldLogger.WriteLog("ERROR", fmt.Sprintf("%s [%s]", message, contextStr))
}
// 数据处理器接口
type DataProcessor interface {
Process(data string) string
}
type DataValidator interface {
Validate(data string) bool
}
type DataFormatter interface {
Format(data string) string
}
type JSONProcessor struct{}
func (jp *JSONProcessor) Process(data string) string {
return fmt.Sprintf("处理JSON: %s", data)
}
func (jp *JSONProcessor) Validate(data string) bool {
// 简单的JSON验证
return strings.HasPrefix(data, "{") && strings.HasSuffix(data, "}")
}
func (jp *JSONProcessor) Format(data string) string {
// 简单的JSON格式化
return strings.ReplaceAll(data, ",", ", ")
}
// ========== 辅助函数 ==========
// 安全处理项目
func processItemSafely(item interface{}) {
switch v := item.(type) {
case nil:
fmt.Printf(" nil 值\\n")
case string:
fmt.Printf(" 字符串: \\\"%s\\\" (长度: %d)\\n", v, len(v))
case int:
fmt.Printf(" 整数: %d\\n", v)
case float64:
fmt.Printf(" 浮点数: %.3f\\n", v)
case bool:
fmt.Printf(" 布尔值: %t\\n", v)
default:
fmt.Printf(" 其他类型: %T, 值: %v\\n", v, v)
}
}
// 使用类型 switch 处理值
func processWithTypeSwitch(value interface{}) {
switch v := value.(type) {
case nil:
fmt.Printf("nil 值\\n")
case int:
fmt.Printf("整数: %d\\n", v)
case string:
fmt.Printf("字符串: \\\"%s\\\" (长度: %d)\\n", v, len(v))
case float64:
fmt.Printf("浮点数: %.3f\\n", v)
case bool:
fmt.Printf("布尔值: %t\\n", v)
case []int:
fmt.Printf("整数切片: %v (长度: %d)\\n", v, len(v))
case map[string]int:
fmt.Printf("字符串到整数的映射: %v (大小: %d)\\n", v, len(v))
case Person:
fmt.Printf("Person 结构体: %s (%d岁)\\n", v.Name, v.Age)
case *Person:
fmt.Printf("Person 指针: %s (%d岁)\\n", v.Name, v.Age)
default:
fmt.Printf("未知类型: %T, 值: %v\\n", v, v)
}
}
// 转换为 float64
func convertToFloat64(value interface{}) float64 {
switch v := value.(type) {
case int:
return float64(v)
case int8:
return float64(v)
case int16:
return float64(v)
case int32:
return float64(v)
case int64:
return float64(v)
case uint:
return float64(v)
case float32:
return float64(v)
case float64:
return v
default:
return 0.0
}
}
// 描述形状
func describeShape(shape Shape) {
area := shape.Area()
perimeter := shape.Perimeter()
switch s := shape.(type) {
case Circle:
fmt.Printf("圆形 (半径: %.1f) - 面积: %.2f, 周长: %.2f\\n", s.Radius, area, perimeter)
case Rectangle:
fmt.Printf("矩形 (%.1fx%.1f) - 面积: %.2f, 周长: %.2f\\n", s.Width, s.Height, area, perimeter)
case Triangle:
fmt.Printf("三角形 (底: %.1f, 高: %.1f) - 面积: %.2f, 周长: %.2f\\n", s.Base, s.Height, area, perimeter)
default:
fmt.Printf("未知形状 - 面积: %.2f, 周长: %.2f\\n", area, perimeter)
}
}
// 处理错误
func handleError(err error) {
switch e := err.(type) {
case *ValidationError:
fmt.Printf("验证错误 - 字段: %s, 消息: %s\\n", e.Field, e.Message)
case *NetworkError:
fmt.Printf("网络错误 - 代码: %d, 消息: %s\\n", e.Code, e.Message)
default:
fmt.Printf("普通错误: %s\\n", err.Error())
}
}
// 动态调用方法
func callMethodsDynamically(obj interface{}) {
// 检查对象类型并调用相应方法
switch o := obj.(type) {
case *Calculator:
fmt.Printf(" %s: 10 + 20 = %d\\n", o.GetType(), o.Add(10, 20))
case *Formatter:
fmt.Printf(" %s: %s\\n", o.GetType(), o.Format("测试文本"))
case *Validator:
fmt.Printf(" %s: 验证 'test' = %t\\n", o.GetType(), o.Validate("test"))
default:
fmt.Printf(" 未知对象类型: %T\\n", obj)
}
}
// 安全的字符串断言
func safeStringAssertion(value interface{}) (string, error) {
if str, ok := value.(string); ok {
return str, nil
}
return "", fmt.Errorf("无法将 %T 类型断言为 string", value)
}
/*
运行这个程序:
go run 03-type-assertions.go
学习要点:
1. 类型断言用于从接口值中提取具体类型
2. 安全断言返回值和布尔标志,不安全断言可能 panic
3. 类型 switch 是处理多种类型的优雅方式
4. 接口可以断言为具体类型或其他接口
5. 类型断言在错误处理、插件系统等场景中很有用
类型断言语法:
1. 不安全断言value.(Type) - 失败时 panic
2. 安全断言value, ok := value.(Type) - 返回值和布尔标志
3. 类型 switchswitch value.(type) - 处理多种类型
类型断言的应用场景:
1. 错误处理:检查错误的具体类型
2. 接口功能检查:检查接口是否支持额外方法
3. 插件系统:动态调用不同插件的方法
4. 数据序列化:根据类型选择序列化方式
5. 类型转换:在不同类型间进行转换
最佳实践:
1. 总是使用安全的类型断言
2. 优先使用类型 switch 处理多种类型
3. 提供有意义的错误处理
4. 避免过深的类型断言链
5. 考虑使用接口而不是具体类型断言
性能考虑:
1. 类型断言有运行时开销
2. 在热点代码中谨慎使用
3. 考虑缓存断言结果
4. 优先使用具体类型而不是接口
常见陷阱:
1. 忽略断言的 ok 返回值
2. 对 nil 接口进行断言
3. 不理解接口的动态类型和动态值
4. 过度使用类型断言而不是接口设计
注意事项:
1. nil 接口值的断言总是失败
2. 类型断言只能用于接口类型
3. 断言失败时的零值行为
4. 接口到接口的断言规则
5. 类型断言与反射的区别
*/