Go学习笔记-Interfaces

接口是Go语言的核心特性之一,它定义了对象的行为规范。Go的接口是隐式实现的,这使得代码更加灵活和解耦。接口是实现多态和依赖注入的重要工具。

基本接口定义

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main

import "fmt"

// 1. 基本接口定义
type Writer interface {
    Write([]byte) (int, error)
}

type Reader interface {
    Read([]byte) (int, error)
}

// 2. 组合接口
type ReadWriter interface {
    Reader
    Writer
}

// 3. 空接口
type Any interface{}

// 4. 实现接口的结构体
type File struct {
    name string
    data []byte
}

func (f *File) Write(data []byte) (int, error) {
    f.data = append(f.data, data...)
    return len(data), nil
}

func (f *File) Read(buffer []byte) (int, error) {
    if len(f.data) == 0 {
        return 0, fmt.Errorf("no data to read")
    }
    
    n := copy(buffer, f.data)
    f.data = f.data[n:]
    return n, nil
}

func (f *File) String() string {
    return fmt.Sprintf("File{name: %s, data: %s}", f.name, string(f.data))
}

// 5. 另一个实现相同接口的类型
type Buffer struct {
    data []byte
}

func (b *Buffer) Write(data []byte) (int, error) {
    b.data = append(b.data, data...)
    return len(data), nil
}

func (b *Buffer) Read(buffer []byte) (int, error) {
    if len(b.data) == 0 {
        return 0, fmt.Errorf("buffer is empty")
    }
    
    n := copy(buffer, b.data)
    b.data = b.data[n:]
    return n, nil
}

func (b *Buffer) String() string {
    return fmt.Sprintf("Buffer{data: %s}", string(b.data))
}

func main() {
    // 1. 接口变量的使用
    var w Writer
    var r Reader
    var rw ReadWriter
    
    // 接口的零值是nil
    fmt.Printf("Writer接口零值: %v\n", w == nil)
    
    // 2. 将具体类型赋值给接口
    file := &File{name: "test.txt"}
    buffer := &Buffer{}
    
    w = file
    r = file
    rw = file  // File实现了ReadWriter接口
    
    fmt.Printf("Writer接口: %T\n", w)
    fmt.Printf("Reader接口: %T\n", r)
    fmt.Printf("ReadWriter接口: %T\n", rw)
    
    // 3. 通过接口调用方法
    data := []byte("Hello, Go!")
    n, err := w.Write(data)
    if err != nil {
        fmt.Printf("写入错误: %v\n", err)
    } else {
        fmt.Printf("写入了 %d 字节\n", n)
    }
    
    // 4. 读取数据
    readBuffer := make([]byte, 20)
    n, err = r.Read(readBuffer)
    if err != nil {
        fmt.Printf("读取错误: %v\n", err)
    } else {
        fmt.Printf("读取了 %d 字节: %s\n", n, string(readBuffer[:n]))
    }
    
    // 5. 接口切片
    writers := []Writer{
        &File{name: "file1.txt"},
        &Buffer{},
        &File{name: "file2.txt"},
    }
    
    for i, writer := range writers {
        data := []byte(fmt.Sprintf("Data from writer %d", i))
        writer.Write(data)
        fmt.Printf("写入到 %T: %s\n", writer, string(data))
    }
    
    // 6. 空接口的使用
    var any Any
    any = 42
    fmt.Printf("空接口存储int: %v\n", any)
    
    any = "hello"
    fmt.Printf("空接口存储string: %v\n", any)
    
    any = file
    fmt.Printf("空接口存储File: %v\n", any)
}

类型断言和类型选择

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main

import "fmt"

// 定义接口
type Shape interface {
    Area() float64
}

type Drawable interface {
    Draw()
}

// 实现接口的类型
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Draw() {
    fmt.Printf("绘制半径为 %.2f 的圆\n", c.Radius)
}

type Rectangle struct {
    Width, Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Draw() {
    fmt.Printf("绘制 %.2f x %.2f 的矩形\n", r.Width, r.Height)
}

type Triangle struct {
    Base, Height float64
}

func (t Triangle) Area() float64 {
    return 0.5 * t.Base * t.Height
}

// Triangle没有实现Draw方法

func main() {
    // 1. 基本类型断言
    var shape Shape = Circle{Radius: 5}
    
    // 安全的类型断言
    if circle, ok := shape.(Circle); ok {
        fmt.Printf("这是一个圆,半径: %.2f\n", circle.Radius)
    } else {
        fmt.Println("不是圆形")
    }
    
    // 不安全的类型断言(如果类型不匹配会panic)
    circle := shape.(Circle)
    fmt.Printf("直接断言的圆,半径: %.2f\n", circle.Radius)
    
    // 2. 类型断言失败的情况
    var shape2 Shape = Rectangle{Width: 10, Height: 5}
    
    if circle, ok := shape2.(Circle); ok {
        fmt.Printf("这是一个圆,半径: %.2f\n", circle.Radius)
    } else {
        fmt.Println("不是圆形")
    }
    
    // 3. 类型选择(type switch)
    shapes := []Shape{
        Circle{Radius: 3},
        Rectangle{Width: 4, Height: 6},
        Triangle{Base: 5, Height: 8},
    }
    
    for i, shape := range shapes {
        fmt.Printf("\n形状 %d:\n", i+1)
        
        switch s := shape.(type) {
        case Circle:
            fmt.Printf("圆形,半径: %.2f,面积: %.2f\n", s.Radius, s.Area())
        case Rectangle:
            fmt.Printf("矩形,宽: %.2f,高: %.2f,面积: %.2f\n", 
                s.Width, s.Height, s.Area())
        case Triangle:
            fmt.Printf("三角形,底: %.2f,高: %.2f,面积: %.2f\n", 
                s.Base, s.Height, s.Area())
        default:
            fmt.Printf("未知形状类型: %T\n", s)
        }
    }
    
    // 4. 接口到接口的类型断言
    fmt.Println("\n接口到接口的类型断言:")
    
    var drawable Drawable
    drawable = Circle{Radius: 2}
    
    // 检查Drawable是否也实现了Shape接口
    if shape, ok := drawable.(Shape); ok {
        fmt.Printf("Drawable也是Shape,面积: %.2f\n", shape.Area())
    }
    
    // 5. 空接口的类型断言
    fmt.Println("\n空接口的类型断言:")
    
    var any interface{} = "hello world"
    
    switch v := any.(type) {
    case nil:
        fmt.Println("值为nil")
    case int:
        fmt.Printf("整数: %d\n", v)
    case string:
        fmt.Printf("字符串: %s\n", v)
    case bool:
        fmt.Printf("布尔值: %t\n", v)
    case Circle:
        fmt.Printf("圆形: %+v\n", v)
    default:
        fmt.Printf("未知类型: %T,值: %v\n", v, v)
    }
    
    // 6. 检查接口是否为nil
    fmt.Println("\n检查接口是否为nil:")
    
    var nilShape Shape
    fmt.Printf("nilShape == nil: %t\n", nilShape == nil)
    
    var nilCircle *Circle
    nilShape = nilCircle
    fmt.Printf("nilShape == nil after assignment: %t\n", nilShape == nil)
    fmt.Printf("nilShape is nil interface: %t\n", nilShape == (*Circle)(nil))
    
    // 7. 多重接口断言
    fmt.Println("\n多重接口断言:")
    
    checkInterfaces := func(obj interface{}) {
        fmt.Printf("检查对象: %T\n", obj)
        
        if shape, ok := obj.(Shape); ok {
            fmt.Printf("  实现了Shape接口,面积: %.2f\n", shape.Area())
        }
        
        if drawable, ok := obj.(Drawable); ok {
            fmt.Printf("  实现了Drawable接口\n")
            drawable.Draw()
        }
        
        if _, ok := obj.(fmt.Stringer); ok {
            fmt.Printf("  实现了Stringer接口\n")
        }
    }
    
    checkInterfaces(Circle{Radius: 1})
    checkInterfaces(Rectangle{Width: 2, Height: 3})
    checkInterfaces(Triangle{Base: 4, Height: 5})
}

接口的高级用法

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
package main

import (
    "fmt"
    "io"
    "strings"
)

// 1. 函数式接口
type Handler func(string) string

func (h Handler) Handle(input string) string {
    return h(input)
}

// 2. 接口组合
type Closer interface {
    Close() error
}

type ReadCloser interface {
    io.Reader
    Closer
}

type WriteCloser interface {
    io.Writer
    Closer
}

type ReadWriteCloser interface {
    io.Reader
    io.Writer
    Closer
}

// 3. 实现多个接口的类型
type MyFile struct {
    name   string
    data   []byte
    pos    int
    closed bool
}

func (f *MyFile) Read(p []byte) (n int, err error) {
    if f.closed {
        return 0, fmt.Errorf("file is closed")
    }
    
    if f.pos >= len(f.data) {
        return 0, io.EOF
    }
    
    n = copy(p, f.data[f.pos:])
    f.pos += n
    return n, nil
}

func (f *MyFile) Write(p []byte) (n int, err error) {
    if f.closed {
        return 0, fmt.Errorf("file is closed")
    }
    
    f.data = append(f.data, p...)
    return len(p), nil
}

func (f *MyFile) Close() error {
    if f.closed {
        return fmt.Errorf("file already closed")
    }
    f.closed = true
    fmt.Printf("文件 %s 已关闭\n", f.name)
    return nil
}

func (f *MyFile) String() string {
    status := "open"
    if f.closed {
        status = "closed"
    }
    return fmt.Sprintf("MyFile{name: %s, status: %s, data: %s}", 
        f.name, status, string(f.data))
}

// 4. 接口适配器模式
type LegacyPrinter struct{}

func (lp *LegacyPrinter) OldPrint(text string) {
    fmt.Printf("[Legacy] %s\n", text)
}

type Printer interface {
    Print(string)
}

type PrinterAdapter struct {
    legacy *LegacyPrinter
}

func (pa *PrinterAdapter) Print(text string) {
    pa.legacy.OldPrint(text)
}

// 5. 策略模式
type SortStrategy interface {
    Sort([]int) []int
}

type BubbleSort struct{}

func (bs BubbleSort) Sort(data []int) []int {
    result := make([]int, len(data))
    copy(result, data)
    
    n := len(result)
    for i := 0; i < n-1; i++ {
        for j := 0; j < n-i-1; j++ {
            if result[j] > result[j+1] {
                result[j], result[j+1] = result[j+1], result[j]
            }
        }
    }
    return result
}

type QuickSort struct{}

func (qs QuickSort) Sort(data []int) []int {
    result := make([]int, len(data))
    copy(result, data)
    quickSort(result, 0, len(result)-1)
    return result
}

func quickSort(arr []int, low, high int) {
    if low < high {
        pi := partition(arr, low, high)
        quickSort(arr, low, pi-1)
        quickSort(arr, pi+1, high)
    }
}

func partition(arr []int, low, high int) int {
    pivot := arr[high]
    i := low - 1
    
    for j := low; j < high; j++ {
        if arr[j] < pivot {
            i++
            arr[i], arr[j] = arr[j], arr[i]
        }
    }
    arr[i+1], arr[high] = arr[high], arr[i+1]
    return i + 1
}

type Sorter struct {
    strategy SortStrategy
}

func (s *Sorter) SetStrategy(strategy SortStrategy) {
    s.strategy = strategy
}

func (s *Sorter) Sort(data []int) []int {
    return s.strategy.Sort(data)
}

func main() {
    // 1. 函数式接口
    fmt.Println("1. 函数式接口:")
    
    upperHandler := Handler(func(s string) string {
        return strings.ToUpper(s)
    })
    
    lowerHandler := Handler(func(s string) string {
        return strings.ToLower(s)
    })
    
    fmt.Printf("Upper: %s\n", upperHandler.Handle("hello"))
    fmt.Printf("Lower: %s\n", lowerHandler.Handle("WORLD"))
    
    // 2. 接口组合使用
    fmt.Println("\n2. 接口组合:")
    
    file := &MyFile{name: "test.txt"}
    
    // 作为Writer使用
    var writer io.Writer = file
    writer.Write([]byte("Hello, "))
    writer.Write([]byte("World!"))
    
    // 作为Reader使用
    var reader io.Reader = file
    buffer := make([]byte, 20)
    n, err := reader.Read(buffer)
    if err != nil && err != io.EOF {
        fmt.Printf("读取错误: %v\n", err)
    } else {
        fmt.Printf("读取内容: %s\n", string(buffer[:n]))
    }
    
    // 作为ReadWriteCloser使用
    var rwc ReadWriteCloser = file
    rwc.Write([]byte(" More data"))
    rwc.Close()
    
    // 3. 适配器模式
    fmt.Println("\n3. 适配器模式:")
    
    legacy := &LegacyPrinter{}
    adapter := &PrinterAdapter{legacy: legacy}
    
    var printer Printer = adapter
    printer.Print("使用适配器模式打印")
    
    // 4. 策略模式
    fmt.Println("\n4. 策略模式:")
    
    data := []int{64, 34, 25, 12, 22, 11, 90}
    fmt.Printf("原始数据: %v\n", data)
    
    sorter := &Sorter{}
    
    // 使用冒泡排序
    sorter.SetStrategy(BubbleSort{})
    bubbleSorted := sorter.Sort(data)
    fmt.Printf("冒泡排序: %v\n", bubbleSorted)
    
    // 使用快速排序
    sorter.SetStrategy(QuickSort{})
    quickSorted := sorter.Sort(data)
    fmt.Printf("快速排序: %v\n", quickSorted)
    
    // 5. 接口的动态性
    fmt.Println("\n5. 接口的动态性:")
    
    var shape interface{} = Circle{Radius: 5}
    
    // 动态检查和调用方法
    if s, ok := shape.(interface{ Area() float64 }); ok {
        fmt.Printf("面积: %.2f\n", s.Area())
    }
    
    if d, ok := shape.(interface{ Draw() }); ok {
        d.Draw()
    }
    
    // 6. 空接口作为通用容器
    fmt.Println("\n6. 空接口作为通用容器:")
    
    container := make([]interface{}, 0)
    container = append(container, 42)
    container = append(container, "hello")
    container = append(container, Circle{Radius: 3})
    container = append(container, true)
    
    for i, item := range container {
        fmt.Printf("Item %d: %v (type: %T)\n", i, item, item)
    }
}

// Circle类型定义(从前面的例子复用)
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Draw() {
    fmt.Printf("绘制半径为 %.2f 的圆\n", c.Radius)
}

接口的最佳实践

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
package main

import (
    "fmt"
    "io"
    "log"
    "strings"
)

// 1. 接口隔离原则 - 小而专一的接口
type Reader interface {
    Read([]byte) (int, error)
}

type Writer interface {
    Write([]byte) (int, error)
}

type Closer interface {
    Close() error
}

// 而不是一个大而全的接口
// type FileInterface interface {
//     Read([]byte) (int, error)
//     Write([]byte) (int, error)
//     Close() error
//     Seek(int64, int) (int64, error)
//     Stat() (FileInfo, error)
//     // ... 更多方法
// }

// 2. 依赖注入和接口
type Logger interface {
    Log(message string)
}

type ConsoleLogger struct{}

func (cl ConsoleLogger) Log(message string) {
    fmt.Printf("[LOG] %s\n", message)
}

type FileLogger struct {
    filename string
}

func (fl FileLogger) Log(message string) {
    fmt.Printf("[FILE:%s] %s\n", fl.filename, message)
}

type Service struct {
    logger Logger
}

func NewService(logger Logger) *Service {
    return &Service{logger: logger}
}

func (s *Service) DoSomething() {
    s.logger.Log("正在执行某些操作...")
    // 业务逻辑
    s.logger.Log("操作完成")
}

// 3. 接口作为参数,具体类型作为返回值
func ProcessData(r io.Reader) (*DataResult, error) {
    // 接受接口,提供灵活性
    data, err := io.ReadAll(r)
    if err != nil {
        return nil, err
    }
    
    // 返回具体类型,提供明确性
    return &DataResult{
        Data:   data,
        Length: len(data),
    }, nil
}

type DataResult struct {
    Data   []byte
    Length int
}

// 4. 接口的组合而非继承
type Validator interface {
    Validate() error
}

type Serializer interface {
    Serialize() ([]byte, error)
}

type Deserializer interface {
    Deserialize([]byte) error
}

type Model interface {
    Validator
    Serializer
    Deserializer
}

// 5. 使用接口进行测试
type Database interface {
    Save(data interface{}) error
    Find(id string) (interface{}, error)
}

type UserService struct {
    db Database
}

func (us *UserService) CreateUser(name string) error {
    user := map[string]string{"name": name}
    return us.db.Save(user)
}

// 真实的数据库实现
type PostgresDB struct{}

func (pdb PostgresDB) Save(data interface{}) error {
    fmt.Printf("保存到PostgreSQL: %v\n", data)
    return nil
}

func (pdb PostgresDB) Find(id string) (interface{}, error) {
    fmt.Printf("从PostgreSQL查找: %s\n", id)
    return map[string]string{"id": id, "name": "用户"}, nil
}

// 测试用的模拟实现
type MockDB struct {
    data map[string]interface{}
}

func NewMockDB() *MockDB {
    return &MockDB{data: make(map[string]interface{})}
}

func (mdb *MockDB) Save(data interface{}) error {
    // 模拟保存逻辑
    mdb.data["test"] = data
    return nil
}

func (mdb *MockDB) Find(id string) (interface{}, error) {
    if data, exists := mdb.data[id]; exists {
        return data, nil
    }
    return nil, fmt.Errorf("not found")
}

// 6. 错误处理接口
type CustomError interface {
    error
    Code() int
    Details() map[string]interface{}
}

type ValidationError struct {
    message string
    code    int
    details map[string]interface{}
}

func (ve ValidationError) Error() string {
    return ve.message
}

func (ve ValidationError) Code() int {
    return ve.code
}

func (ve ValidationError) Details() map[string]interface{} {
    return ve.details
}

func main() {
    // 1. 依赖注入示例
    fmt.Println("1. 依赖注入:")
    
    // 使用控制台日志
    consoleService := NewService(ConsoleLogger{})
    consoleService.DoSomething()
    
    // 使用文件日志
    fileService := NewService(FileLogger{filename: "app.log"})
    fileService.DoSomething()
    
    // 2. 接口作为参数
    fmt.Println("\n2. 接口作为参数:")
    
    // 可以传入任何实现了io.Reader的类型
    stringReader := strings.NewReader("Hello, World!")
    result, err := ProcessData(stringReader)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("处理结果: 长度=%d, 数据=%s\n", result.Length, string(result.Data))
    
    // 3. 测试中使用接口
    fmt.Println("\n3. 测试中使用接口:")
    
    // 生产环境
    prodService := &UserService{db: PostgresDB{}}
    prodService.CreateUser("张三")
    
    // 测试环境
    mockDB := NewMockDB()
    testService := &UserService{db: mockDB}
    testService.CreateUser("测试用户")
    
    // 验证测试结果
    if data, exists := mockDB.data["test"]; exists {
        fmt.Printf("测试验证: %v\n", data)
    }
    
    // 4. 自定义错误接口
    fmt.Println("\n4. 自定义错误接口:")
    
    validateUser := func(name string) error {
        if name == "" {
            return ValidationError{
                message: "用户名不能为空",
                code:    400,
                details: map[string]interface{}{
                    "field": "name",
                    "rule":  "required",
                },
            }
        }
        return nil
    }
    
    if err := validateUser(""); err != nil {
        if customErr, ok := err.(CustomError); ok {
            fmt.Printf("错误码: %d\n", customErr.Code())
            fmt.Printf("错误信息: %s\n", customErr.Error())
            fmt.Printf("错误详情: %v\n", customErr.Details())
        }
    }
    
    // 5. 接口的零值检查
    fmt.Println("\n5. 接口的零值检查:")
    
    var logger Logger
    if logger == nil {
        fmt.Println("Logger接口为nil")
        logger = ConsoleLogger{}
    }
    logger.Log("现在可以安全使用了")
    
    // 6. 接口断言的最佳实践
    fmt.Println("\n6. 接口断言的最佳实践:")
    
    checkCapabilities := func(obj interface{}) {
        fmt.Printf("检查对象: %T\n", obj)
        
        // 安全的类型断言
        if writer, ok := obj.(io.Writer); ok {
            fmt.Println("  支持写入操作")
            writer.Write([]byte("test"))
        }
        
        if closer, ok := obj.(io.Closer); ok {
            fmt.Println("  支持关闭操作")
            closer.Close()
        }
        
        if stringer, ok := obj.(fmt.Stringer); ok {
            fmt.Printf("  字符串表示: %s\n", stringer.String())
        }
    }
    
    checkCapabilities(&strings.Builder{})
    checkCapabilities(strings.NewReader("test"))
}

总结

  1. 接口定义

    • 定义方法签名的集合
    • 隐式实现,无需显式声明
    • 支持接口组合
    • 空接口可以存储任何类型
  2. 类型断言

    • 安全断言:value, ok := interface.(Type)
    • 直接断言:value := interface.(Type)(可能panic)
    • 类型选择:switch v := interface.(type)
  3. 接口特性

    • 接口是引用类型
    • 接口变量存储具体类型和值
    • 接口可以为nil
    • 支持多态
  4. 设计原则

    • 接口隔离原则:小而专一
    • 依赖倒置:依赖接口而非具体实现
    • 接受接口,返回具体类型
    • 在使用处定义接口
  5. 最佳实践

    • 使用接口进行依赖注入
    • 接口用于测试和模拟
    • 合理使用空接口
    • 安全的类型断言
    • 接口组合而非继承
updatedupdated2025-09-202025-09-20