Menu
CoddyTech

Stringer 和 Error 接口

本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 32 课,共 107 课。

Go 的标准库定义了两个你会经常使用的接口:fmt.Stringer 和 error。它们都是简单的单方法接口,能让你的类型与 Go 内置功能强大地集成。

Stringer 接口位于 fmt 包中,只需要一个方法:

type Stringer interface {
    String() string
}

在你的类型上实现 String() 后,像 fmt.Println 这样的函数会自动使用它来显示你的值:

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // Alice(30 岁)
}

错误接口同样很简单,只需要一个返回字符串的 Error() 方法:

type error interface {
    Error() string
}

在 Go 中,任何具有 Error() 方法的类型都可以用作错误值。这样你就可以创建包含更多上下文信息的自定义错误类型:

type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func main() {
    err := ValidationError{Field: "email", Message: "invalid format"}
    fmt.Println(err)  // email: invalid format
}

这两个接口体现了 Go 的理念:接口小而专注,通过隐式实现解锁强大的行为。

challenge icon

挑战

简单

让我们构建一个温度监控系统,使用 Stringer 和 error 接口提供易读的输出,并进行有意义的错误处理。

你需要将代码分成两个文件:

  • temperature.go:创建一个包含 Value(float64)和 Unit(string)字段的 Temperature 结构体。实现 String() 方法,使打印时以易读的格式显示温度。还要创建一个包含 Temp(float64)和 Reason(string)字段的 TemperatureError 结构体,并实现 Error() 方法,以提供描述性错误消息。
  • main.go:创建一个名为 ValidateTemperature 的函数,该函数接收一个 Temperature,并在温度无效时返回错误。低于绝对零度的温度无效(摄氏温度为 -273.15,华氏温度为 -459.67)。如果温度有效,该函数返回 nil。从输入中读取温度数据,创建一个 Temperature,验证它,并打印相应的输出。

输入如下:

  • 第 1 行:温度值(浮点数)
  • 第 2 行:单位(C 表示摄氏度,F 表示华氏度)

你的 String() 方法应返回以下格式:

[Value] degrees [Unit]

其中,Unit 应根据输入使用完整单词 "Celsius" 或 "Fahrenheit"。

你的 Error() 方法应返回以下格式:

invalid temperature [Temp]: [Reason]

如果温度有效,使用 fmt.Println 打印 Temperature(它会使用你的 String() 方法)。如果温度无效,则打印错误(它会使用你的 Error() 方法)。

例如,给定 25.5 和 C,输出应为:

25.5 degrees Celsius

给定 -500 和 F,输出应为:

invalid temperature -500: below absolute zero

温度过低时,使用 "below absolute zero" 作为原因。

亲手试试

package main

import (
	"fmt"
)

// ValidateTemperature 检查温度是否有效
// 如果温度低于绝对零度,则返回错误
// 绝对零度:摄氏度为 -273.15,华氏度为 -459.67
func ValidateTemperature(t Temperature) error {
	// TODO:实现验证逻辑
	// 根据单位检查温度是否低于绝对零度
	// 如果无效,返回 TemperatureError;如果有效,返回 nil
	return nil
}

func main() {
	var value float64
	var unit string
	fmt.Scanln(&value)
	fmt.Scanln(&unit)

	// TODO:用输入值创建一个 Temperature 结构体

	// TODO:使用 ValidateTemperature 验证温度

	// TODO:如果有错误,打印错误
	// 否则,打印温度(这会使用 String() 方法)
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Go 在线编译器