标准库精讲
2026/3/20大约 9 分钟
标准库精讲
一、标准库概览
Go 标准库功能丰富,覆盖大部分开发需求,是 Go 生态的核心优势。
运维常用标准库
├── 基础处理
│ ├── fmt - 格式化 I/O
│ ├── strings - 字符串操作
│ ├── strconv - 字符串转换
│ ├── regexp - 正则表达式
│ └── unicode - Unicode 处理
├── 系统操作
│ ├── os - 操作系统功能
│ ├── os/exec - 执行外部命令
│ ├── path/filepath - 文件路径处理
│ └── runtime - 运行时信息
├── I/O 操作
│ ├── io - I/O 原语
│ ├── io/fs - 文件系统接口
│ ├── bufio - 缓冲 I/O
│ └── embed - 嵌入静态文件
├── 时间日期
│ └── time - 时间处理
├── 数据格式
│ ├── encoding/json - JSON
│ ├── encoding/xml - XML
│ ├── encoding/csv - CSV
│ └── encoding/base64 - Base64
├── 网络相关
│ ├── net - 网络原语
│ ├── net/http - HTTP 客户端/服务端
│ └── net/url - URL 解析
├── 日志调试
│ ├── log - 日志
│ └── log/slog - 结构化日志(Go 1.21+)
├── 加密安全
│ ├── crypto/* - 加密算法
│ └── hash/* - 哈希算法
└── 数据结构
├── container/list - 双向链表
├── container/heap - 堆
└── container/ring - 环形链表
二、fmt 包
2.1 格式化输出
package main
import (
"fmt"
"os"
)
func main() {
// ========== Print 系列 ==========
fmt.Print("Hello ") // 不换行
fmt.Println("World") // 换行
fmt.Printf("数字: %d\n", 42) // 格式化
// ========== Sprint 系列:返回字符串 ==========
s1 := fmt.Sprint("Hello", " ", "World")
s2 := fmt.Sprintf("Port: %d", 8080)
s3 := fmt.Sprintln("Line with newline")
fmt.Println(s1, s2, s3)
// ========== Fprint 系列:写入 io.Writer ==========
fmt.Fprint(os.Stdout, "写入标准输出\n")
fmt.Fprintf(os.Stderr, "错误: %s\n", "something went wrong")
// ========== 常用格式化动词 ==========
type Server struct {
Name string
Port int
}
srv := Server{"web-01", 8080}
// 通用
fmt.Printf("%%v: %v\n", srv) // {web-01 8080}
fmt.Printf("%%+v: %+v\n", srv) // {Name:web-01 Port:8080}
fmt.Printf("%%#v: %#v\n", srv) // main.Server{Name:"web-01", Port:8080}
fmt.Printf("%%T: %T\n", srv) // main.Server
// 整数
n := 255
fmt.Printf("%%d: %d, %%b: %b, %%o: %o, %%x: %x\n", n, n, n, n)
// 浮点
f := 3.14159
fmt.Printf("%%f: %f, %%.2f: %.2f, %%e: %e\n", f, f, f)
// 字符串
s := "hello"
fmt.Printf("%%s: %s, %%q: %q, %%x: %x\n", s, s, s)
// 宽度和精度
fmt.Printf("|%10s|%-10s|%10.5s|\n", "abc", "abc", "abcdefgh")
fmt.Printf("|%10d|%-10d|%010d|\n", 42, 42, 42)
}
2.2 格式化输入
package main
import (
"fmt"
"strings"
)
func main() {
// Scanf:从标准输入读取
// var name string
// var age int
// fmt.Print("请输入姓名和年龄: ")
// fmt.Scanf("%s %d", &name, &age)
// Sscanf:从字符串读取
input := "web-01 8080 running"
var name string
var port int
var status string
fmt.Sscanf(input, "%s %d %s", &name, &port, &status)
fmt.Printf("Server: %s, Port: %d, Status: %s\n", name, port, status)
// Fscanf:从 io.Reader 读取
r := strings.NewReader("192.168.1.100 22")
var ip string
var sshPort int
fmt.Fscanf(r, "%s %d", &ip, &sshPort)
fmt.Printf("IP: %s, SSH Port: %d\n", ip, sshPort)
}
三、strings 包
package main
import (
"fmt"
"strings"
)
func main() {
// ========== 查找判断 ==========
s := "/var/log/nginx/access.log"
fmt.Println("Contains 'nginx':", strings.Contains(s, "nginx"))
fmt.Println("HasPrefix '/var':", strings.HasPrefix(s, "/var"))
fmt.Println("HasSuffix '.log':", strings.HasSuffix(s, ".log"))
fmt.Println("Index 'nginx':", strings.Index(s, "nginx"))
fmt.Println("LastIndex '/':", strings.LastIndex(s, "/"))
fmt.Println("Count '/':", strings.Count(s, "/"))
// ========== 分割合并 ==========
parts := strings.Split(s, "/")
fmt.Println("Split:", parts) // ["", "var", "log", "nginx", "access.log"]
// 分割成最多 N 段
parts2 := strings.SplitN(s, "/", 3)
fmt.Println("SplitN(3):", parts2) // ["", "var", "log/nginx/access.log"]
// 合并
hosts := []string{"web-01", "web-02", "web-03"}
fmt.Println("Join:', ':", strings.Join(hosts, ", "))
// ========== 替换 ==========
config := "host=localhost port=3306"
fmt.Println("Replace:", strings.Replace(config, "localhost", "10.0.0.1", 1))
fmt.Println("ReplaceAll:", strings.ReplaceAll(config, " ", "\n"))
// ========== 大小写 ==========
fmt.Println("ToUpper:", strings.ToUpper("hello"))
fmt.Println("ToLower:", strings.ToLower("HELLO"))
fmt.Println("ToTitle:", strings.ToTitle("hello world"))
// ========== 修剪 ==========
padded := " hello world "
fmt.Println("TrimSpace:", strings.TrimSpace(padded))
fmt.Println("Trim:", strings.Trim("///path///", "/"))
fmt.Println("TrimPrefix:", strings.TrimPrefix("/api/v1/users", "/api"))
fmt.Println("TrimSuffix:", strings.TrimSuffix("config.yaml", ".yaml"))
// ========== 重复 ==========
fmt.Println(strings.Repeat("=", 40))
// ========== Fields:按空白分割 ==========
line := " cpu 75.5 memory 60.2 "
fields := strings.Fields(line)
fmt.Println("Fields:", fields) // ["cpu", "75.5", "memory", "60.2"]
// ========== Builder:高效拼接 ==========
var builder strings.Builder
builder.WriteString("server {\n")
builder.WriteString(" listen 80;\n")
builder.WriteString(" server_name example.com;\n")
builder.WriteString("}\n")
fmt.Println(builder.String())
// ========== Replacer:批量替换 ==========
replacer := strings.NewReplacer(
"${HOST}", "localhost",
"${PORT}", "8080",
"${ENV}", "production",
)
template := "http://${HOST}:${PORT} (${ENV})"
fmt.Println(replacer.Replace(template))
}
四、os 包
4.1 文件操作
package main
import (
"fmt"
"io"
"os"
)
func main() {
// ========== 环境变量 ==========
fmt.Println("PATH:", os.Getenv("PATH"))
fmt.Println("HOME:", os.Getenv("HOME"))
// 设置环境变量
os.Setenv("MY_APP_DEBUG", "true")
fmt.Println("MY_APP_DEBUG:", os.Getenv("MY_APP_DEBUG"))
// 所有环境变量
for _, env := range os.Environ()[:3] {
fmt.Println(env)
}
// ========== 命令行参数 ==========
fmt.Println("程序名:", os.Args[0])
fmt.Println("参数:", os.Args[1:])
// ========== 工作目录 ==========
wd, _ := os.Getwd()
fmt.Println("当前目录:", wd)
// os.Chdir("/tmp") // 改变工作目录
// ========== 文件信息 ==========
info, err := os.Stat("/etc/hosts")
if err != nil {
if os.IsNotExist(err) {
fmt.Println("文件不存在")
} else {
fmt.Println("错误:", err)
}
} else {
fmt.Printf("文件: %s, 大小: %d, 权限: %v, 修改时间: %v\n",
info.Name(), info.Size(), info.Mode(), info.ModTime())
}
// ========== 读写文件 ==========
// 读取整个文件
content, err := os.ReadFile("/etc/hosts")
if err == nil {
fmt.Printf("文件内容:\n%s\n", content[:100]) // 只打印前 100 字节
}
// 写入文件
data := []byte("Hello, World!\n")
os.WriteFile("/tmp/test.txt", data, 0644)
// 打开文件
file, err := os.Open("/etc/hosts")
if err == nil {
defer file.Close()
buf := make([]byte, 64)
n, _ := file.Read(buf)
fmt.Printf("读取 %d 字节\n", n)
}
// 创建文件
newFile, err := os.Create("/tmp/newfile.txt")
if err == nil {
defer newFile.Close()
newFile.WriteString("Hello from Go\n")
}
// ========== 目录操作 ==========
os.Mkdir("/tmp/testdir", 0755)
os.MkdirAll("/tmp/a/b/c", 0755) // 递归创建
os.Remove("/tmp/testdir") // 删除文件或空目录
os.RemoveAll("/tmp/a") // 递归删除
// 读取目录
entries, _ := os.ReadDir("/tmp")
for _, entry := range entries[:5] {
info, _ := entry.Info()
fmt.Printf("%s %8d %s\n",
info.Mode(), info.Size(), entry.Name())
}
}
4.2 os/exec 执行命令
package main
import (
"bytes"
"context"
"fmt"
"os/exec"
"time"
)
func main() {
// ========== 简单执行 ==========
// 获取输出
output, err := exec.Command("date").Output()
if err != nil {
fmt.Println("错误:", err)
}
fmt.Printf("日期: %s", output)
// ========== 带参数 ==========
out, _ := exec.Command("ls", "-la", "/tmp").Output()
fmt.Printf("目录列表:\n%s\n", out[:200])
// ========== 管道输入 ==========
cmd := exec.Command("grep", "root")
cmd.Stdin = bytes.NewBufferString("root:x:0:0:root\nnobody:x:65534:65534")
out, _ = cmd.Output()
fmt.Printf("Grep 结果: %s\n", out)
// ========== 分别获取 stdout 和 stderr ==========
cmd = exec.Command("ls", "/nonexistent")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err = cmd.Run()
if err != nil {
fmt.Printf("错误: %v, stderr: %s\n", err, stderr.String())
}
// ========== 超时控制 ==========
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
cmd = exec.CommandContext(ctx, "sleep", "10")
err = cmd.Run()
if ctx.Err() == context.DeadlineExceeded {
fmt.Println("命令超时")
}
// ========== 检查命令是否存在 ==========
path, err := exec.LookPath("docker")
if err != nil {
fmt.Println("docker 未安装")
} else {
fmt.Println("docker 路径:", path)
}
// ========== 运维场景:批量执行命令 ==========
commands := []struct {
name string
args []string
}{
{"uname", []string{"-a"}},
{"uptime", nil},
{"df", []string{"-h"}},
}
for _, c := range commands {
out, err := exec.Command(c.name, c.args...).Output()
if err != nil {
fmt.Printf("[%s] 错误: %v\n", c.name, err)
continue
}
fmt.Printf("[%s]\n%s\n", c.name, out)
}
}
五、time 包
package main
import (
"fmt"
"time"
)
func main() {
// ========== 当前时间 ==========
now := time.Now()
fmt.Println("当前时间:", now)
fmt.Println("时间戳(秒):", now.Unix())
fmt.Println("时间戳(毫秒):", now.UnixMilli())
fmt.Println("时间戳(纳秒):", now.UnixNano())
// ========== 时间组成 ==========
fmt.Printf("年: %d, 月: %d, 日: %d\n", now.Year(), now.Month(), now.Day())
fmt.Printf("时: %d, 分: %d, 秒: %d\n", now.Hour(), now.Minute(), now.Second())
fmt.Printf("星期: %s, 一年中第 %d 天\n", now.Weekday(), now.YearDay())
// ========== 时间格式化(Go 特有的参考时间)==========
// 参考时间: 2006-01-02 15:04:05 -0700 MST
fmt.Println("格式化:")
fmt.Println(" RFC3339:", now.Format(time.RFC3339))
fmt.Println(" 自定义:", now.Format("2006-01-02 15:04:05"))
fmt.Println(" 日期:", now.Format("2006/01/02"))
fmt.Println(" 时间:", now.Format("15:04:05"))
fmt.Println(" 带毫秒:", now.Format("2006-01-02 15:04:05.000"))
// ========== 解析时间字符串 ==========
t, err := time.Parse("2006-01-02 15:04:05", "2024-01-15 10:30:00")
if err == nil {
fmt.Println("解析结果:", t)
}
// 带时区解析
loc, _ := time.LoadLocation("Asia/Shanghai")
t2, _ := time.ParseInLocation("2006-01-02 15:04:05", "2024-01-15 10:30:00", loc)
fmt.Println("上海时间:", t2)
// ========== 时间计算 ==========
// 加减时间
tomorrow := now.Add(24 * time.Hour)
yesterday := now.Add(-24 * time.Hour)
fmt.Println("明天:", tomorrow.Format("2006-01-02"))
fmt.Println("昨天:", yesterday.Format("2006-01-02"))
// 加年月日
nextMonth := now.AddDate(0, 1, 0)
nextYear := now.AddDate(1, 0, 0)
fmt.Println("下个月:", nextMonth.Format("2006-01-02"))
fmt.Println("明年:", nextYear.Format("2006-01-02"))
// 时间差
duration := tomorrow.Sub(now)
fmt.Printf("时间差: %v (%.2f 小时)\n", duration, duration.Hours())
// ========== 时间比较 ==========
t1 := time.Now()
t2 = t1.Add(time.Hour)
fmt.Println("t1.Before(t2):", t1.Before(t2))
fmt.Println("t1.After(t2):", t1.After(t2))
fmt.Println("t1.Equal(t1):", t1.Equal(t1))
// ========== 定时器 ==========
// 单次定时
timer := time.NewTimer(100 * time.Millisecond)
<-timer.C
fmt.Println("Timer 触发")
// time.After 简写
<-time.After(100 * time.Millisecond)
fmt.Println("After 触发")
// 周期定时
ticker := time.NewTicker(200 * time.Millisecond)
count := 0
for range ticker.C {
count++
fmt.Println("Tick", count)
if count >= 3 {
ticker.Stop()
break
}
}
// ========== 运维场景:计时 ==========
start := time.Now()
time.Sleep(100 * time.Millisecond) // 模拟操作
elapsed := time.Since(start)
fmt.Printf("操作耗时: %v\n", elapsed)
}
六、encoding/json 包
package main
import (
"encoding/json"
"fmt"
)
// 结构体定义
type Server struct {
Name string `json:"name"`
Host string `json:"host"`
Port int `json:"port"`
Tags []string `json:"tags,omitempty"`
IsActive bool `json:"is_active"`
privateKey string // 不导出
}
type Config struct {
Version string `json:"version"`
Servers []Server `json:"servers"`
}
func main() {
// ========== 序列化(Marshal)==========
server := Server{
Name: "web-01",
Host: "192.168.1.100",
Port: 8080,
Tags: []string{"production", "frontend"},
IsActive: true,
}
// 紧凑格式
data, _ := json.Marshal(server)
fmt.Println("紧凑 JSON:", string(data))
// 格式化输出
data, _ = json.MarshalIndent(server, "", " ")
fmt.Println("格式化 JSON:")
fmt.Println(string(data))
// ========== 反序列化(Unmarshal)==========
jsonStr := `{
"name": "db-01",
"host": "10.0.0.50",
"port": 3306,
"is_active": true
}`
var srv Server
json.Unmarshal([]byte(jsonStr), &srv)
fmt.Printf("反序列化: %+v\n", srv)
// ========== 处理嵌套结构 ==========
configJSON := `{
"version": "1.0",
"servers": [
{"name": "web-01", "host": "10.0.0.1", "port": 80, "is_active": true},
{"name": "web-02", "host": "10.0.0.2", "port": 80, "is_active": true}
]
}`
var config Config
json.Unmarshal([]byte(configJSON), &config)
fmt.Printf("配置: %+v\n", config)
// ========== 处理动态 JSON(map)==========
dynamicJSON := `{"name": "test", "count": 42, "enabled": true}`
var m map[string]interface{}
json.Unmarshal([]byte(dynamicJSON), &m)
// 类型断言获取值
if name, ok := m["name"].(string); ok {
fmt.Println("Name:", name)
}
if count, ok := m["count"].(float64); ok { // JSON 数字默认是 float64
fmt.Println("Count:", int(count))
}
// ========== json.RawMessage(延迟解析)==========
type Event struct {
Type string `json:"type"`
Payload json.RawMessage `json:"payload"`
}
eventJSON := `{"type": "alert", "payload": {"level": "critical", "message": "CPU high"}}`
var event Event
json.Unmarshal([]byte(eventJSON), &event)
fmt.Println("Event Type:", event.Type)
fmt.Println("Payload (raw):", string(event.Payload))
// ========== 自定义序列化 ==========
// 实现 json.Marshaler 和 json.Unmarshaler 接口
}
七、log/slog 结构化日志(Go 1.21+)
package main
import (
"context"
"log/slog"
"os"
)
func main() {
// ========== 默认日志 ==========
slog.Info("服务启动")
slog.Warn("配置未找到,使用默认值")
slog.Error("连接失败", "host", "10.0.0.1", "port", 3306)
// ========== 带属性的日志 ==========
slog.Info("请求处理完成",
"method", "GET",
"path", "/api/users",
"status", 200,
"duration_ms", 45,
)
// ========== JSON 格式输出 ==========
jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
})
jsonLogger := slog.New(jsonHandler)
jsonLogger.Info("JSON 格式日志",
"server", "web-01",
"cpu", 75.5,
)
// ========== 带上下文的日志 ==========
ctx := context.Background()
logger := slog.With("request_id", "req-12345")
logger.InfoContext(ctx, "处理请求", "user_id", 42)
// ========== 日志分组 ==========
slog.Info("服务器状态",
slog.Group("server",
slog.String("name", "web-01"),
slog.String("ip", "10.0.0.1"),
),
slog.Group("metrics",
slog.Float64("cpu", 75.5),
slog.Float64("memory", 60.2),
),
)
// ========== 自定义日志级别 ==========
opts := &slog.HandlerOptions{
Level: slog.LevelDebug,
}
handler := slog.NewTextHandler(os.Stdout, opts)
debugLogger := slog.New(handler)
debugLogger.Debug("调试信息", "detail", "verbose output")
}
八、path/filepath 包
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
// ========== 路径操作 ==========
path := "/var/log/nginx/access.log"
fmt.Println("Dir:", filepath.Dir(path)) // /var/log/nginx
fmt.Println("Base:", filepath.Base(path)) // access.log
fmt.Println("Ext:", filepath.Ext(path)) // .log
// 分离扩展名
name := filepath.Base(path)
ext := filepath.Ext(name)
nameWithoutExt := name[:len(name)-len(ext)]
fmt.Println("文件名(无扩展名):", nameWithoutExt)
// ========== 路径拼接 ==========
logDir := "/var/log"
logFile := filepath.Join(logDir, "app", "error.log")
fmt.Println("Join:", logFile)
// ========== 清理路径 ==========
messy := "/var//log/../log/./nginx/access.log"
fmt.Println("Clean:", filepath.Clean(messy))
// ========== 绝对路径 ==========
abs, _ := filepath.Abs("./config.yaml")
fmt.Println("Abs:", abs)
// ========== 相对路径 ==========
rel, _ := filepath.Rel("/var/log", "/var/log/nginx/access.log")
fmt.Println("Rel:", rel) // nginx/access.log
// ========== 匹配模式 ==========
matched, _ := filepath.Match("*.log", "access.log")
fmt.Println("Match *.log:", matched)
// ========== 遍历目录 ==========
fmt.Println("\n遍历 /tmp:")
count := 0
filepath.Walk("/tmp", func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil // 跳过错误
}
count++
if count > 5 {
return filepath.SkipDir // 停止遍历
}
if info.IsDir() {
fmt.Printf("[D] %s\n", path)
} else {
fmt.Printf("[F] %s (%d bytes)\n", path, info.Size())
}
return nil
})
// Go 1.16+ WalkDir(更高效)
filepath.WalkDir("/tmp", func(path string, d os.DirEntry, err error) error {
// 类似 Walk,但 d 是 DirEntry 类型
return nil
})
// ========== Glob 模式匹配 ==========
logs, _ := filepath.Glob("/var/log/*.log")
fmt.Println("\n/var/log/*.log:")
for _, log := range logs {
fmt.Println(" ", log)
}
}
九、本章小结
| 包名 | 主要用途 | 常用函数 |
|---|---|---|
| fmt | 格式化 I/O | Printf, Sprintf, Scanf |
| strings | 字符串处理 | Split, Join, Contains, Replace |
| strconv | 类型转换 | Atoi, Itoa, ParseInt, FormatFloat |
| os | 系统操作 | Open, Create, ReadFile, Getenv |
| os/exec | 执行命令 | Command, Run, Output |
| io | I/O 原语 | Copy, ReadAll, Pipe |
| time | 时间处理 | Now, Parse, Format, Sleep |
| encoding/json | JSON 处理 | Marshal, Unmarshal |
| log/slog | 结构化日志 | Info, Error, With |
| path/filepath | 路径处理 | Join, Dir, Base, Walk |
运维开发建议
- 使用
os/exec执行命令时务必设置超时 - JSON 处理优先使用结构体,保证类型安全
- 日志优先使用
log/slog结构化日志 - 文件路径处理使用
filepath保证跨平台兼容