第20章 接口实现

第20章 接口实现

Go语言的接口实现机制是"隐式的",不需要implements关键字。只要方法签名对上了,编译器就会认可你"实现了"那个接口。这种设计叫做鸭子类型(Duck Typing)——“如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。”

20.1 隐式实现原理

20.1.1 什么是隐式实现

在其他语言(如Java)中,你要实现一个接口,得显式声明。但在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
package main

import "fmt"

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

type File struct {
    name string
}

func (f *File) Write(p []byte) (n int, err error) {
    fmt.Printf("[File] 写入文件 %s: %s\n", f.name, string(p)) // [File] 写入文件 test.txt: Hello, Go!
    return len(p), nil
}

type StringWriter struct{}

func (s *StringWriter) Write(p []byte) (n int, err error) {
    fmt.Printf("[StringWriter] 写入字符串: %s\n", string(p)) // [StringWriter] 写入字符串: Another message
    return len(p), nil
}

func main() {
    var w Writer = &File{name: "test.txt"}
    w.Write([]byte("Hello, Go!"))

    var sw Writer = &StringWriter{}
    sw.Write([]byte("Another message"))
}

20.1.2 方法匹配规则

Go的接口实现要求方法完全匹配

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

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

type RightReader struct{}

func (r *RightReader) Read(p []byte) (n int, err error) {
    copy(p, []byte("correct data"))
    return len("correct data"), nil
}

func main() {
    var r Reader = &RightReader{}
    buf := make([]byte, 100)
    n, _ := r.Read(buf)
    fmt.Printf("读取了 %d 字节: %s\n", n, string(buf[:n])) // 读取了 12 字节: correct data
}

20.2 实现方式:值接收者 vs 指针接收者

20.2.1 值接收者实现

使用值接收者定义的方法,值类型和指针类型都算实现了接口:

 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
package main

import "fmt"

type ReadOnly interface {
    Read(p []byte) (n int, err error)
}

type Document struct {
    content string
}

func (d Document) Read(p []byte) (n int, err error) {
    copy(p, d.content)
    return len(d.content), nil
}

func main() {
    doc := Document{content: "Hello, World!"}
    var ro1 ReadOnly = doc
    buf := make([]byte, 100)
    n, _ := ro1.Read(buf)
    fmt.Printf("值类型赋值,读取内容: %s\n", string(buf[:n])) // 值类型赋值,读取内容: Hello, World!

    doc2 := Document{content: "Pointer case"}
    var ro2 ReadOnly = &doc2
    n, _ = ro2.Read(buf)
    fmt.Printf("指针类型赋值,读取内容: %s\n", string(buf[:n])) // 指针类型赋值,读取内容: Pointer case
}

20.2.2 指针接收者实现

使用指针接收者定义的方法,只有指针类型实现了接口:

 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
package main

import "fmt"

type Writable interface {
    Write(p []byte) (n int, err error)
}

type Buffer struct {
    data []byte
}

func (b *Buffer) Write(p []byte) (n int, err error) {
    b.data = append(b.data, p...)
    fmt.Printf("[Buffer] 写入 %d 字节\n", len(p)) // [Buffer] 写入 7 字节
    return len(p), nil
}

func main() {
    buf := &Buffer{}
    var w Writable = buf

    w.Write([]byte("Hello, "))
    w.Write([]byte("World!"))

    fmt.Printf("\nBuffer内容: %s\n", string(buf.data)) // Buffer内容: Hello, World!
}

20.2.3 方法集规则

接收者类型值接收者方法指针接收者方法
值类型 T
指针类型 *T
 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
package main

import "fmt"

type Operations interface {
    Process()
    GetValue() int
}

type Counter struct {
    value int
}

func (c Counter) GetValue() int {
    return c.value
}

func (c *Counter) Process() {
    c.value++
}

func main() {
    var ops1 Operations = &Counter{value: 10}
    ops1.Process()
    fmt.Printf("指针赋值: %d\n", ops1.GetValue()) // 指针赋值: 11
}

20.3 接口实现的实际应用

20.3.1 同一类型实现多个接口

 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
package main

import "fmt"

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

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

type Closer interface {
    Close() error
}

type File struct {
    name string
    data []byte
}

func (f *File) Read(p []byte) (n int, err error) {
    copy(p, f.data)
    fmt.Printf("[File.Read] 读取文件 %s\n", f.name) // [File.Read] 读取文件 data.txt
    return len(f.data), nil
}

func (f *File) Write(p []byte) (n int, err error) {
    f.data = append(f.data, p...)
    fmt.Printf("[File.Write] 写入文件 %s: %s\n", f.name, string(p)) // [File.Write] 写入文件 data.txt: Hello
    return len(p), nil
}

func (f *File) Close() error {
    fmt.Printf("[File.Close] 关闭文件 %s\n", f.name) // [File.Close] 关闭文件 data.txt
    return nil
}

func main() {
    f := &File{name: "data.txt", data: []byte("Hello")}

    var r Reader = f
    var w Writer = f
    var c Closer = f

    r.Read(make([]byte, 100))
    w.Write([]byte(" World"))
    c.Close()
}

20.3.2 验证接口实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import "io"

type NullWriter struct{}

func (n *NullWriter) Write(p []byte) (int, error) {
    return len(p), nil
}

var _ io.Writer = (*NullWriter)(nil)

func main() {
    w := &NullWriter{}
    n, _ := w.Write([]byte("test"))
    println("写入字节数:", n) // 写入字节数: 4
}

本章小结

本章我们学习了Go接口的隐式实现机制:

核心原理:

  • Go使用隐式接口实现,不需要implements关键字
  • 只要方法签名匹配,编译器就认为类型实现了接口

方法集规则:

  • 值类型T只能实现值接收者方法
  • 指针类型*T可以实现所有方法

实用技巧:

  • 使用var _ Interface = (*Type)(nil)进行编译时接口验证
  • 同一类型可以实现多个接口
最后修改 March 20, 2026: 新增Go基础部分 (8cce995)