0Pricing
Go Academy · 课时

标准库核心接口

fmt.Stringer、io.Reader、io.Writer

标准库核心接口 是 CoddyKit 上的免费 Go Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

fmt.Stringer

fmt.Stringer 只有一个方法:String() string。实现它,可以控制您的类型在使用 fmt.Println 和 %v 时的显示方式:

package main
import "fmt"

type Color int
const (Red Color = iota; Green; Blue)
func (c Color) String() string {
    return []string{"Red","Green","Blue"}[c]
}

func main() {
    fmt.Println(Red, Green, Blue) // Red Green Blue
}

错误接口

内置的 error 接口只有一个方法:Error() string。任何实现了该接口的类型都可以用作错误:

package main
import "fmt"

type ValidationError struct{ Field, Msg string }
func (e *ValidationError) Error() string {
    return e.Field + ": " + e.Msg
}

func validate(age int) error {
    if age < 0 { return &ValidationError{"age", "must be non-negative"} }
    return nil
}

func main() {
    fmt.Println(validate(-1))
}

io.Reader

io.Reader 只有一个方法:Read(p []byte) (n int, err error)。文件、HTTP 请求体、字符串和缓冲区都实现了它:

package main
import ("fmt"; "strings")

func countBytes(r interface{ Read([]byte)(int,error) }) int {
    buf := make([]byte, 512)
    total := 0
    for {
        n, err := r.Read(buf)
        total += n
        if err != nil { break }
    }
    return total
}

func main() {
    r := strings.NewReader("hello world")
    fmt.Println(countBytes(r)) // 11
}

io.Writer

io.Writer 只有一个方法:Write(p []byte) (n int, err error)。fmt.Fprintf、日志记录、HTTP 响应写入器等都会使用它:

package main
import ("bytes"; "fmt")

func main() {
    var buf bytes.Buffer
    fmt.Fprintf(&buf, "Hello, %s!", "Go")
    fmt.Println(buf.String()) // Hello, Go!
}

io.ReadWriter 与 io.Closer

标准库会将小型接口组合成更大的接口:

package main
import "io"

// io.ReadWriter = io.Reader + io.Writer
// io.ReadCloser = io.Reader + io.Closer
// io.ReadWriteCloser = all three

func process(rw io.ReadWriter) {
    buf := make([]byte, 8)
    rw.Read(buf)
    rw.Write(buf)
}

func main() { _ = process }

sort.Interface

sort.Interface 要求实现 Len() int、Less(i, j int) bool 和 Swap(i, j int):

package main
import ("fmt"; "sort")

type ByLength []string
func (b ByLength) Len() int           { return len(b) }
func (b ByLength) Less(i, j int) bool { return len(b[i]) < len(b[j]) }
func (b ByLength) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }

func main() {
    fruits := ByLength{"banana","apple","kiwi"}
    sort.Sort(fruits)
    fmt.Println([]string(fruits)) // [kiwi apple banana]
}

http.Handler

http.Handler 只有一个方法:ServeHTTP(ResponseWriter, *Request)。Go 的整个 HTTP 栈都构建在这个单一接口之上:

package main
import ("fmt"; "net/http")

type Hello struct{}
func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Hello, World!")
}

func main() {
    http.ListenAndServe(":8080", Hello{})
}

fmt.GoStringer

实现 GoString() string,以控制您的类型在 %#v(Go 语法)表示形式下的输出:

package main
import "fmt"

type Version struct{ Major, Minor int }
func (v Version) GoString() string {
    return fmt.Sprintf("Version{%d, %d}", v.Major, v.Minor)
}

func main() {
    fmt.Printf("%#v\n", Version{1, 18}) // Version{1, 18}
}

encoding.TextMarshaler

实现 MarshalText() ([]byte, error) 和 UnmarshalText([]byte) error,以支持自定义文本编码(JSON 字符串、YAML 等):

package main
import "fmt"

type Status int
const (Active Status = iota; Inactive)
func (s Status) MarshalText() ([]byte, error) {
    if s == Active { return []byte("active"), nil }
    return []byte("inactive"), nil
}

func main() {
    s := Active
    b, _ := s.MarshalText()
    fmt.Println(string(b)) // active
}

组合标准接口

使用 io.TeeReader、io.MultiWriter 等组合标准接口,无需编写任何新类型即可构建功能强大的流水线:

package main
import ("bytes"; "fmt"; "io"; "strings")

func main() {
    r := strings.NewReader("hello")
    var buf bytes.Buffer
    tee := io.TeeReader(r, &buf)
    io.ReadAll(tee)
    fmt.Println(buf.String()) // hello
}

快速检查

类型必须实现哪个接口,才能在 Go 中用作错误?

回顾

标准库中的关键接口:

  • fmt.Stringer——自定义打印表示
  • error——错误值
  • io.Reader / io.Writer——流式输入输出
  • sort.Interface——自定义排序
  • http.Handler——HTTP 请求处理

练习提示

为 []Person 实现 sort.Interface(其中 Person 具有 Name 和 Age 字段),以按年龄降序排序。打印排序后的列表。

常见问题解答

「标准库核心接口」课时是免费的吗?

是的 — 「标准库核心接口」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「标准库核心接口」这节课中我会学到什么?

fmt.Stringer、io.Reader、io.Writer 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「标准库核心接口」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义和实现接口
  2. 标准库核心接口
  3. 类型断言与类型 switch
  4. 接口组合与最佳实践
← 返回 Go Academy