1058 lines
25 KiB
Go
1058 lines
25 KiB
Go
/*
|
||
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. 类型 switch:switch 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. 类型断言与反射的区别
|
||
*/ |