GoLang 标准库速查:高频包与实战用法
覆盖 Go 日常开发最常用的标准库:strings/bytes 字符串处理、io 接口体系、os 文件操作、net/http 网络服务,以及测试规范速查。
相关文章:GoLang 简介 · GoLang 类型系统与数据结构深度 · GoLang 并发编程 · GoLang 错误处理与 panic-defer · GoLang 工程实践
目录
| 章节 | 说明 |
|---|---|
| strings 包 | 字符串查找、分割、替换、构建 |
| bytes 包 | 字节切片操作,bytes.Buffer |
| io 包:接口体系 | Reader/Writer 核心接口及工具函数 |
| bufio 包 | 带缓冲的读写,逐行读取 |
| os 包 | 文件操作、环境变量、进程信号 |
| net/http 包 | HTTP 服务端与客户端 |
| testing 包 | 单元测试、基准测试、示例测试 |
| unicode 与字符编码 | rune、UTF-8、字符串遍历 |
strings 包
import "strings"
s := "Hello, World"
// 查找
strings.Contains(s, "World") // true
strings.HasPrefix(s, "Hello") // true
strings.HasSuffix(s, "World") // true
strings.Index(s, "World") // 7(字节位置)
strings.Count(s, "l") // 3
// 变换
strings.ToUpper(s) // "HELLO, WORLD"
strings.ToLower(s) // "hello, world"
strings.TrimSpace(" hello ") // "hello"
strings.Trim("##hello##", "#") // "hello"
strings.TrimLeft("##hello##", "#") // "hello##"
strings.Replace(s, "World", "Go", 1) // 替换1次
strings.ReplaceAll(s, "l", "L") // 替换所有
// 分割与拼接
parts := strings.Split("a,b,c", ",") // ["a", "b", "c"]
strings.Join(parts, "-") // "a-b-c"
strings.Fields(" foo bar baz ") // ["foo", "bar", "baz"](按空白分割)
// 数字转换
strings.Repeat("ab", 3) // "ababab"
strings.Builder(高效拼接)
var b strings.Builder
for i := 0; i < 5; i++ {
fmt.Fprintf(&b, "item%d,", i)
}
result := b.String()
// ✅ 比 += 拼接性能好(避免大量内存分配)
strings.Reader
r := strings.NewReader("hello world")
// 实现了 io.Reader、io.Seeker 等接口,可用于需要 Reader 的地方
bytes 包
bytes 包与 strings 包几乎镜像,但操作对象是 []byte:
import "bytes"
b := []byte("Hello, World")
bytes.Contains(b, []byte("World")) // true
bytes.ToUpper(b) // []byte("HELLO, WORLD")
bytes.Split(b, []byte(",")) // 分割
bytes.Buffer(读写缓冲区)
var buf bytes.Buffer
// 写入
buf.WriteString("Hello")
buf.WriteByte(',')
buf.Write([]byte(" World"))
fmt.Fprintf(&buf, " %d", 2024)
// 读取
fmt.Println(buf.String()) // "Hello, World 2024"
// 用于高效拼接 JSON、SQL 等
bytes.Buffer 实现了:
- 写接口:
io.Writer、io.ByteWriter、io.StringWriter - 读接口:
io.Reader、io.ByteReader、io.RuneReader、io.WriterTo
io 包:接口体系
核心接口
// 最基础的两个接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 常用扩展接口
type ReadWriter interface { Reader; Writer }
type Closer interface { Close() error }
type Seeker interface { Seek(offset int64, whence int) (int64, error) }
type ReadCloser interface { Reader; Closer }
type WriteCloser interface { Writer; Closer }
常用工具函数
import "io"
// 复制:从 src 读取直到 EOF,写入 dst
written, err := io.Copy(dst, src)
// 限量复制
written, err = io.CopyN(dst, src, 100)
// 读取全部内容到内存(谨慎用于大文件)
data, err := io.ReadAll(r)
// 多 Reader 串联(像拼接文件)
r := io.MultiReader(r1, r2, r3)
// 多 Writer 广播(写入一个同时写入多个)
w := io.MultiWriter(w1, w2, w3)
// 丢弃写入(用于性能测试)
io.Discard
// 管道(无需中间缓冲,连接 Writer 和 Reader)
pr, pw := io.Pipe()
go func() { pw.Write([]byte("data")); pw.Close() }()
data, _ = io.ReadAll(pr)
接口满足关系(常用类型)
| 类型 | 实现的接口 |
|---|---|
*bytes.Buffer | Reader、Writer、ByteReader、RuneReader 等 |
*strings.Reader | Reader、ReaderAt、ByteReader、RuneReader、Seeker 等 |
*strings.Builder | Writer、ByteWriter |
*os.File | Reader、Writer、Seeker、Closer |
bufio 包
为 io.Reader 和 io.Writer 添加缓冲层,减少系统调用次数:
bufio.Reader
import "bufio"
r := bufio.NewReader(os.Stdin) // 默认缓冲 4096 字节
// 逐行读取
line, err := r.ReadString('\n') // 读到换行符(含)
line, isPrefix, err := r.ReadLine() // 不含换行符
// 用 Scanner 更方便
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
_ = line
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
bufio.Writer
w := bufio.NewWriter(file)
w.WriteString("Hello\n")
w.Flush() // 必须调用 Flush 才能将缓冲区内容写入底层
// 或用 defer w.Flush()
bufio.Scanner 的分割函数
scanner := bufio.NewScanner(r)
// 默认按行分割(ScanLines)
// 也可以按单词、字节、rune 分割
scanner.Split(bufio.ScanWords) // 按空白分割单词
os 包
文件操作
import "os"
// 打开文件(只读)
f, err := os.Open("file.txt")
defer f.Close()
// 创建/覆盖文件
f, err = os.Create("output.txt")
// 更灵活的打开方式
f, err = os.OpenFile("file.txt",
os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
// 读取全部内容
data, err := os.ReadFile("file.txt")
// 写入全部内容
err = os.WriteFile("output.txt", []byte("hello"), 0644)
// 文件信息
info, err := os.Stat("file.txt")
fmt.Println(info.Size(), info.IsDir(), info.ModTime())
// 创建目录
os.Mkdir("dir", 0755)
os.MkdirAll("a/b/c", 0755) // 递归创建
// 删除
os.Remove("file.txt")
os.RemoveAll("dir") // 递归删除
// 重命名/移动
os.Rename("old.txt", "new.txt")
环境变量
// 读取
val := os.Getenv("HOME")
val, exists := os.LookupEnv("HOME") // 区分"不存在"和"值为空"
// 设置(仅当前进程)
os.Setenv("MY_VAR", "value")
// 所有环境变量
envs := os.Environ() // []string,格式 "KEY=VALUE"
命令行参数
os.Args // []string,os.Args[0] 是程序名
// 更完善的 flag 解析用 flag 包
import "flag"
name := flag.String("name", "world", "who to greet")
flag.Parse()
fmt.Println("Hello,", *name)
net/http 包
HTTP 服务端
import "net/http"
// 注册路由(使用默认 ServeMux)
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
// 读取请求
query := r.URL.Query().Get("name")
r.ParseForm()
body, _ := io.ReadAll(r.Body)
// 写入响应
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"message":"hello %s"}`, query)
})
// 启动服务
log.Fatal(http.ListenAndServe(":8080", nil))
// 使用自定义 ServeMux(推荐,避免全局状态)
mux := http.NewServeMux()
mux.HandleFunc("/api/users", usersHandler)
server := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
log.Fatal(server.ListenAndServe())
HTTP 客户端
// 简单 GET
resp, err := http.Get("https://example.com/api")
if err != nil { ... }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
// 使用自定义 Client(推荐,避免使用 DefaultClient)
client := &http.Client{
Timeout: 10 * time.Second,
}
// POST JSON
data, _ := json.Marshal(payload)
resp, err = client.Post("https://api.example.com/data",
"application/json", bytes.NewReader(data))
// 带 Header 的请求
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err = client.Do(req)
testing 包
单元测试
// 文件名:xxx_test.go(必须以 _test.go 结尾)
package mypackage
import "testing"
// 函数名必须以 Test 开头,参数为 *testing.T
func TestAdd(t *testing.T) {
got := Add(2, 3)
want := 5
if got != want {
t.Errorf("Add(2,3) = %d, want %d", got, want)
}
}
// 表驱动测试(推荐)
func TestAddTable(t *testing.T) {
tests := []struct {
name string
a, b int
want int
}{
{"positive", 2, 3, 5},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Add(tt.a, tt.b); got != tt.want {
t.Errorf("Add(%d,%d) = %d, want %d", tt.a, tt.b, got, tt.want)
}
})
}
}
基准测试
// 函数名以 Benchmark 开头
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}
// 运行:go test -bench=. -benchmem
示例测试
// 函数名以 Example 开头,通过注释验证输出
func ExampleAdd() {
fmt.Println(Add(2, 3))
// Output:
// 5
}
常用测试命令
go test ./... # 运行所有测试
go test -v ./... # 详细输出
go test -run TestAdd ./... # 只运行匹配的测试
go test -bench=. -benchmem ./... # 运行基准测试
go test -cover ./... # 覆盖率统计
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out # 覆盖率可视化
go test -race ./... # 开启竞态检测(必备!)
unicode 与字符编码
Go 字符串与 rune
s := "Hello, 世界"
// 按字节遍历(byte = uint8)
for i := 0; i < len(s); i++ {
fmt.Printf("%x ", s[i]) // len(s) = 13(中文每字 3 字节 UTF-8)
}
// 按字符(rune)遍历(正确处理多字节字符)
for i, r := range s {
fmt.Printf("s[%d] = %c (%U)\n", i, r, r)
}
// rune = int32,表示 Unicode 码点
// 字符串长度
len(s) // 13(字节数)
len([]rune(s)) // 9(字符数)
utf8.RuneCountInString(s) // 9(更高效,不分配内存)
字符串与 []byte/[]rune 转换
s := "Hello, 世界"
b := []byte(s) // 复制内存,[]byte 可修改
s2 := string(b) // 复制回字符串
r := []rune(s) // 按字符切割,r[7] = '世'
s3 := string(r)
// 单个 rune 转字符串
ch := '世'
fmt.Println(string(ch)) // "世"
fmt.Println(string(20316)) // "世"(Unicode 码点 U+4E16)
unicode 包常用函数
import "unicode"
unicode.IsLetter('A') // true
unicode.IsDigit('5') // true
unicode.IsSpace(' ') // true
unicode.IsUpper('A') // true
unicode.ToLower('A') // 'a'
unicode.ToUpper('a') // 'A'
参考资料
- 《Go 语言核心 36 讲》— 第 36-49 讲(郝林)
- Go standard library
- Go testing package
- Strings, bytes, runes and characters in Go
评论 (0)