第11章 - 标准库详解
Go 的标准库设计精良、功能强大,许多生产级程序仅依赖标准库即可完成。本章介绍最常用的标准库包,掌握它们能极大提升开发效率。完整文档可在 https://pkg.go.dev/std 查阅。
11.1 fmt:格式化 I/O
fmt 提供格式化输入输出功能:
fmt.Println("简单输出")
fmt.Printf("格式化: %d %s\n", 42, "hello")
s := fmt.Sprintf("拼接到字符串: %v", data) // 返回字符串而非打印
fmt.Fprintf(os.Stderr, "写到指定 Writer\n") // 输出到任意 io.Writer
// 输入
var name string
fmt.Scanln(&name)
11.2 strings:字符串处理
import "strings"
strings.Contains("hello", "ell") // true
strings.HasPrefix("golang", "go") // true
strings.HasSuffix("file.go", ".go") // true
strings.Index("chicken", "ken") // 4
strings.Replace("aaa", "a", "b", 2) // "bba"(替换前 2 个)
strings.ReplaceAll("aaa", "a", "b") // "bbb"
strings.Split("a,b,c", ",") // ["a" "b" "c"]
strings.Join([]string{"a", "b"}, "-") // "a-b"
strings.ToUpper("go") // "GO"
strings.ToLower("GO") // "go"
strings.TrimSpace(" hi ") // "hi"
strings.Trim("[hi]", "[]") // "hi"
strings.Repeat("ab", 3) // "ababab"
strings.Fields(" a b c ") // ["a" "b" "c"],按空白分割
11.2.1 strings.Builder 高效拼接
频繁拼接字符串时,直接用 + 会产生大量临时对象。strings.Builder 通过缓冲避免重复分配,性能更优:
var b strings.Builder
for i := 0; i < 1000; i++ {
b.WriteString("x")
}
result := b.String()
11.3 strconv:字符串与基本类型转换
import "strconv"
n, err := strconv.Atoi("123") // string -> int
s := strconv.Itoa(123) // int -> string
f, err := strconv.ParseFloat("3.14", 64)
b, err := strconv.ParseBool("true")
i, err := strconv.ParseInt("ff", 16, 64) // 按 16 进制解析
str := strconv.FormatInt(255, 16) // "ff"
quoted := strconv.Quote("hi\n") // "\"hi\\n\""
11.4 strconv 与 errors
errors 包提供错误创建与处理(详见第 7 章):errors.New、errors.Is、errors.As、errors.Unwrap、fmt.Errorf 配合 %w。
11.5 time:时间与日期
import "time"
now := time.Now()
fmt.Println(now.Year(), now.Month(), now.Day())
fmt.Println(now.Unix()) // 时间戳(秒)
// 格式化:Go 使用特定的参考时间 2006-01-02 15:04:05
fmt.Println(now.Format("2006-01-02 15:04:05"))
// 解析
t, err := time.Parse("2006-01-02", "2024-03-15")
// 时间运算
later := now.Add(2 * time.Hour)
diff := later.Sub(now) // Duration
fmt.Println(now.Before(later)) // true
// 定时器
time.Sleep(time.Second)
timer := time.NewTimer(3 * time.Second)
ticker := time.NewTicker(time.Second) // 周期性触发
记忆技巧:Go 的时间格式化模板使用固定参考时间
Mon Jan 2 15:04:05 MST 2006(对应数字 1 2 3 4 5 6 7),而非YYYY-MM-DD。
11.6 os:操作系统交互
import "os"
args := os.Args // 命令行参数,args[0] 是程序名
val := os.Getenv("HOME") // 读取环境变量
os.Setenv("KEY", "value")
os.Exit(1) // 退出程序
// 文件操作
f, err := os.Open("file.txt") // 只读打开
f, err := os.Create("new.txt") // 创建/截断
data, err := os.ReadFile("file.txt") // 一次性读取全部
err := os.WriteFile("out.txt", data, 0644)
os.Remove("file.txt")
os.Mkdir("dir", 0755)
os.MkdirAll("a/b/c", 0755)
11.7 io 与 bufio:I/O 抽象
io 包定义了 Reader/Writer 等核心接口。bufio 提供带缓冲的读写,减少系统调用:
import (
"bufio"
"os"
)
f, _ := os.Open("file.txt")
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() { // 逐行读取
line := scanner.Text()
fmt.Println(line)
}
writer := bufio.NewWriter(os.Stdout)
writer.WriteString("buffered\n")
writer.Flush() // 必须 Flush 才会真正写出
11.8 encoding/json:JSON 处理
JSON 是最常用的数据交换格式。Go 通过结构体标签控制序列化:
import "encoding/json"
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"` // 为空时省略
pwd string // 未导出字段不会被序列化
}
// 序列化(Marshal)
user := User{Name: "Alice", Age: 30}
data, err := json.Marshal(user) // {"name":"Alice","age":30}
data, err = json.MarshalIndent(user, "", " ") // 带缩进
// 反序列化(Unmarshal)
var u User
err = json.Unmarshal(data, &u)
// 处理任意 JSON
var result map[string]any
json.Unmarshal(data, &result)
11.9 net/http:HTTP 客户端与服务端
详见第 15 章。这里给出最简示例:
// 客户端
resp, err := http.Get("https://api.example.com")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
// 服务端
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello")
})
http.ListenAndServe(":8080", nil)
11.10 sort:排序
import "sort"
nums := []int{3, 1, 2}
sort.Ints(nums) // 升序
sort.Strings([]string{"c", "a"})
sort.Float64s(floats)
// 自定义排序
people := []Person{...}
sort.Slice(people, func(i, j int) bool {
return people[i].Age < people[j].Age
})
// 二分查找(要求已排序)
idx := sort.SearchInts(nums, 2)
11.11 regexp:正则表达式
import "regexp"
re := regexp.MustCompile(`\d+`)
re.MatchString("abc123") // true
re.FindString("abc123def") // "123"
re.FindAllString("a1b2c3", -1) // ["1" "2" "3"]
re.ReplaceAllString("a1b2", "X") // "aXbX"
11.12 slices 与 maps(Go 1.21+)
Go 1.21 将常用的泛型集合操作纳入标准库:
import (
"slices"
"maps"
)
s := []int{3, 1, 2}
slices.Sort(s) // [1 2 3]
slices.Contains(s, 2) // true
slices.Index(s, 2) // 1
slices.Max(s) // 3
slices.Reverse(s)
m := map[string]int{"a": 1, "b": 2}
keys := slices.Collect(maps.Keys(m)) // 提取所有键
maps.Clone(m) // 浅拷贝
11.13 log 与 log/slog:日志
import "log"
log.Println("普通日志")
log.Printf("格式化: %d", 42)
log.Fatal("致命错误") // 打印后调用 os.Exit(1)
// Go 1.21+ 的结构化日志 slog
import "log/slog"
slog.Info("用户登录", "userID", 123, "ip", "1.2.3.4")
slog.Error("操作失败", "err", err)
slog 提供结构化日志,输出可为文本或 JSON 格式,便于日志系统采集分析。
11.14 其他常用包速览
| 包 | 用途 |
|---|---|
bytes |
字节切片操作,bytes.Buffer 高效拼接 |
bufio |
带缓冲 I/O |
path/filepath |
跨平台文件路径处理 |
flag |
命令行参数解析 |
math / math/rand |
数学函数与随机数 |
encoding/base64 |
Base64 编码 |
crypto/md5、crypto/sha256 |
哈希算法 |
net/url |
URL 解析 |
container/list、container/heap |
链表、堆 |
unicode/utf8 |
UTF-8 处理 |
11.15 本章小结
本章介绍了 Go 标准库中最常用的包:fmt、strings、strconv、time、os、io/bufio、encoding/json、net/http、sort、regexp,以及 Go 1.21 新增的 slices/maps 和结构化日志 slog。Go 标准库覆盖面广、质量高,熟练使用它们是高效开发的前提。建议养成查阅 pkg.go.dev 官方文档的习惯。
下一章我们将学习测试、基准测试与性能分析。