82 lines
2.1 KiB
Go
82 lines
2.1 KiB
Go
package main
|
||
|
||
import "fmt"
|
||
|
||
// 定义基础接口
|
||
type Reader interface {
|
||
Read() string
|
||
}
|
||
|
||
// 定义扩展接口(方法集包含Reader)
|
||
type ReadWriter interface {
|
||
Reader // 嵌入接口,继承Read()方法
|
||
Write(string)
|
||
}
|
||
|
||
// 实现ReadWriter接口(隐式实现Reader)
|
||
type File struct {
|
||
content string
|
||
}
|
||
|
||
func (f *File) Read() string {
|
||
return f.content
|
||
}
|
||
|
||
func (f *File) Write(s string) {
|
||
f.content = s
|
||
}
|
||
|
||
// 接口作为函数参数
|
||
func readData(r Reader) {
|
||
fmt.Println("读取数据:", r.Read())
|
||
}
|
||
|
||
func main() {
|
||
// 隐式实现与接口赋值
|
||
var f *File = &File{content: "test data"}
|
||
var r Reader = f // File实现Reader,可赋值
|
||
var rw ReadWriter = f // File实现ReadWriter,可赋值
|
||
fmt.Printf("Reader Read: %s\n", r.Read()) // 输出test data
|
||
|
||
rw.Write("测试数据")
|
||
fmt.Printf("ReadWriter Read: %s\n", rw.Read()) // 输出测试数据
|
||
// 类型断言(判断接口存储的具体类型)
|
||
if file, ok := r.(*File); ok {
|
||
file.Write("new data")
|
||
fmt.Printf("After Write: %s\n", r.Read()) // 输出new data
|
||
}
|
||
|
||
// 接口作为函数参数
|
||
readData(f) // File实现了Reader接口,可以传递
|
||
|
||
// 空接口使用
|
||
var any interface{}
|
||
any = 100
|
||
fmt.Printf("any type: %T, value: %v\n", any, any) // 输出int, 100
|
||
|
||
any = "hello"
|
||
fmt.Printf("any type: %T, value: %v\n", any, any) // 输出string, hello
|
||
|
||
// 空接口与nil的陷阱
|
||
var p *int = nil
|
||
var i interface{} = p
|
||
fmt.Printf("p == nil? %t, i == nil? %t\n", p == nil, i == nil) // 输出true, false
|
||
// 说明:
|
||
// 当一个接口变量被赋值时,它会存储两个信息:
|
||
// 动态类型 (dynamic type)
|
||
// 动态值 (dynamic value)
|
||
// p 是一个指向 int 的指针,其值为 nil
|
||
// 当将 p 赋值给接口变量 i 时:
|
||
// i 的动态类型是 *int
|
||
// i 的动态值是 nil(来自 p 的值)
|
||
// 但是 i 本身不是 nil 接口,而是一个包含 (*int, nil) 的接口
|
||
// i (interface{}):
|
||
// ├── type: *int
|
||
// └── value: nil (p的值)
|
||
//
|
||
// p (*int):
|
||
// └── value: nil
|
||
var emptyInterface interface{} // 这个才是 == nil 的
|
||
fmt.Println("emptyInterface == nil?", emptyInterface == nil)
|
||
}
|