fmt.Stringer 接口
本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 75 课,共 107 课。
fmt.Stringer 接口决定打印时你的类型如何显示。它是 Go 中最常实现的接口之一,定义在 fmt 包中:
type Stringer interface {
String() string
}将值传递给 fmt.Println、使用 %v 的 fmt.Printf 或类似函数时,Go 会检查该类型是否实现了 Stringer。如果实现了,Go 就会调用 String() 方法来获取文本表示。
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}如果没有 String() 方法,打印时会显示默认的结构体格式:{23.5}。通过实现 Stringer,你可以精确控制类型的呈现方式。
这对于原始字段值无法清楚表达含义的类型尤其有用。Duration 类型可以显示为“2h 30m”,而不是显示原始纳秒数;User 类型则可以显示格式化后的名称,而不是显示它的所有字段。
挑战
简单让我们构建一个时间跟踪系统,以人们容易理解的格式显示时长!你将实现 fmt.Stringer 接口,控制打印自定义类型时的显示方式。
你将把代码分放在两个文件中:
duration.go:定义与时间相关的类型,并为它们设置自定义字符串表示形式。创建一个
Duration结构体,用整数存储总分钟数。实现String()方法,让它在打印时以易读的格式显示时长。例如,150 分钟显示为2h 30m,45 分钟显示为0h 45m。小时和分钟都必须始终显示。创建一个
Task结构体,包含Name(字符串)和Time(Duration)字段。在 Task 上实现String(),按[Name]: [duration]格式显示,其中时长使用其自身的 String 方法。main.go:创建并显示任务及其时长。读取任务数量,然后为每个任务读取名称和分钟数。创建 Task 实例,并使用
fmt.Println直接打印每个实例:Stringer 接口会自动处理格式。打印完所有任务后,计算并按以下格式打印所有任务的总时长:
Total: [duration]
输入内容如下:
- 第 1 行:任务数量
- 后续各行:任务名称和分钟数(每个任务占两行)
例如,给定:
3
Code Review
90
Meeting
45
Documentation
120输出应为:
Code Review: 1h 30m
Meeting: 0h 45m
Documentation: 2h 0m
Total: 4h 15m再例如,给定:
2
Design
180
Testing
65输出应为:
Design: 3h 0m
Testing: 1h 5m
Total: 4h 5m实现 Stringer 后,你的类型就能与 Go 的打印函数无缝配合。你不会再看到像 {90} 这样的原始结构体字段,而是能得到对用户有意义的输出。
亲手试试
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 读取任务数量
line, _ := reader.ReadString('\n')
numTasks, _ := strconv.Atoi(strings.TrimSpace(line))
// TODO:创建一个切片来存储任务
// TODO:记录总分钟数
for i := 0; i < numTasks; i++ {
// 读取任务名称
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// 读取任务时长,单位为分钟
minutesLine, _ := reader.ReadString('\n')
minutes, _ := strconv.Atoi(strings.TrimSpace(minutesLine))
// TODO:用名称和 Duration 创建一个 Task
// TODO:输出任务(fmt.Println 会使用 Stringer 接口)
// TODO:将分钟数加到总分钟数中
_ = name
_ = minutes
}
// TODO:按 "Total: Xh Ym" 格式输出总时长
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Go 在线编译器