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 的理念:接口小而专注,通过隐式实现解锁强大的行为。
挑战
简单让我们构建一个温度监控系统,使用 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() 方法)
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Go 在线编译器