package main

import "fmt"

// ========== 1. 定义接口（鸭子类型）==========
type Speaker interface {
	Speak() string
}

type Dog struct{}

func (d Dog) Speak() string {
	return "Woof!"
}

type Cat struct{}

func (c Cat) Speak() string {
	return "Meow~"
}

type Robot struct{}

func (r Robot) Speak() string {
	return "Beep boop."
}

// ========== 2. 空接口（interface{}）==========
// 在 Go 1.18+ 中，推荐使用 any（它是 interface{} 的别名）
func printAnything(v any) {
	fmt.Printf("接收到: %v (类型: %T)\n", v, v)
}

// ========== 3. 类型断言 ==========
func describeSpeaker(s Speaker) {
	fmt.Println("它说:", s.Speak())

	// 类型断言：判断具体类型
	if d, ok := s.(Dog); ok {
		fmt.Println("这是一只狗！", d)
	} else if c, ok := s.(Cat); ok {
		fmt.Println("这是一只猫！", c)
	}
}

// 使用 switch 进行类型断言（更优雅）
func identify(v any) {
	switch x := v.(type) {
	case string:
		fmt.Printf("字符串: %s\n", x)
	case int:
		fmt.Printf("整数: %d\n", x)
	case Speaker:
		fmt.Printf("会说话的东西: %s\n", x.Speak())
	default:
		fmt.Printf("未知类型: %T\n", x)
	}
}

// ========== 主函数 ==========
func main() {
	fmt.Println("=== 1. 鸭子类型：只要会 Speak()，就是 Speaker ===")
	animals := []Speaker{Dog{}, Cat{}, Robot{}}
	for _, a := range animals {
		fmt.Println(a.Speak())
	}

	fmt.Println("\n=== 2. 空接口（any）可接收任意类型 ===")
	printAnything(42)
	printAnything("Hello")
	printAnything(Dog{})

	fmt.Println("\n=== 3. 类型断言：从接口还原具体类型 ===")
	describeSpeaker(Dog{})
	describeSpeaker(Cat{})

	fmt.Println("\n=== 4. 类型 switch：安全高效的类型判断 ===")
	identify("Gopher")
	identify(100)
	identify(Robot{})
	identify(true) // 未知类型

	fmt.Println("\n=== 5. 安全 vs 不安全的类型断言 ===")
	var i any = "hello"
	s := i.(string) // 不安全：如果类型不对，会 panic
	fmt.Println("不安全断言结果:", s)

	// 安全方式
	if val, ok := i.(int); ok {
		fmt.Println("是整数:", val)
	} else {
		fmt.Println("不是整数！")
	}
}
