Go标准库精选
约 1949 字大约 7 分钟
gostdlib
2025-04-29
概述
Go的标准库是其最大的竞争优势之一,提供了从HTTP服务到加密算法、从JSON编解码到数据库驱动的全面支持。"电池已包含"(batteries included)的设计理念使得大多数Go项目无需引入第三方依赖即可完成常见功能。本文精选标准库中最重要的包,介绍其核心API、使用模式和最佳实践。
net/http:HTTP客户端与服务器
HTTP服务器
package main
import (
"encoding/json"
"log"
"net/http"
"time"
)
func main() {
mux := http.NewServeMux()
// Go 1.22+增强的路由模式
mux.HandleFunc("GET /api/users/{id}", getUser)
mux.HandleFunc("POST /api/users", createUser)
mux.HandleFunc("GET /health", healthCheck)
// 生产级Server配置
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}
log.Printf("Server starting on %s", srv.Addr)
log.Fatal(srv.ListenAndServe())
}
func getUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id") // Go 1.22+
user := map[string]string{"id": id, "name": "Alice"}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}HTTP客户端
// 创建自定义客户端(不要使用http.DefaultClient)
client := &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
}
// 发送请求
resp, err := client.Get("https://api.example.com/data")
if err != nil {
return err
}
defer resp.Body.Close()
// 限制读取大小防止OOM
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) // 1MBencoding/json:JSON编解码
// 结构体标签控制JSON序列化
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"` // 空值省略
Password string `json:"-"` // 永不序列化
CreatedAt time.Time `json:"created_at"`
}
// 序列化
user := User{ID: 1, Name: "Alice"}
data, err := json.Marshal(user)
// {"id":1,"name":"Alice","created_at":"0001-01-01T00:00:00Z"}
// 反序列化
var u User
err = json.Unmarshal(data, &u)
// 流式编解码(大数据量)
decoder := json.NewDecoder(reader)
decoder.DisallowUnknownFields() // 严格模式
err = decoder.Decode(&u)
encoder := json.NewEncoder(writer)
encoder.SetIndent("", " ") // 格式化输出
err = encoder.Encode(u)
// 处理动态JSON
var raw json.RawMessage
err = json.Unmarshal(data, &raw) // 延迟解析
var m map[string]interface{}
err = json.Unmarshal(data, &m) // 解析为map自定义JSON序列化
type Duration struct {
time.Duration
}
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
dur, err := time.ParseDuration(s)
if err != nil {
return err
}
d.Duration = dur
return nil
}database/sql:数据库接口
import (
"database/sql"
_ "github.com/lib/pq" // PostgreSQL驱动
)
// 打开连接池(不是单个连接)
db, err := sql.Open("postgres", "postgres://user:pass@localhost/mydb?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 配置连接池
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
// 查询
rows, err := db.QueryContext(ctx, "SELECT id, name FROM users WHERE age > $1", 18)
if err != nil {
return err
}
defer rows.Close()
var users []User
for rows.Next() {
var u User
if err := rows.Scan(&u.ID, &u.Name); err != nil {
return err
}
users = append(users, u)
}
if err := rows.Err(); err != nil {
return err
}
// 单行查询
var name string
err = db.QueryRowContext(ctx, "SELECT name FROM users WHERE id = $1", 1).Scan(&name)
if err == sql.ErrNoRows {
// 未找到
} else if err != nil {
return err
}
// 事务
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback() // 安全回滚(Commit后调用无害)
_, err = tx.ExecContext(ctx, "UPDATE accounts SET balance = balance - $1 WHERE id = $2", amount, fromID)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, "UPDATE accounts SET balance = balance + $1 WHERE id = $2", amount, toID)
if err != nil {
return err
}
return tx.Commit()context:请求生命周期管理
// context的核心用途:
// 1. 传递取消信号
// 2. 传递截止时间
// 3. 传递请求级别的值
// 超时控制
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
result, err := db.QueryContext(ctx, "SELECT ...")
// 如果查询超过5秒,自动取消
// 取消传播
ctx, cancel := context.WithCancel(context.Background())
go func() {
// 检测到需要取消时
cancel()
}()
select {
case <-ctx.Done():
fmt.Println("cancelled:", ctx.Err())
case result := <-doWork(ctx):
fmt.Println("result:", result)
}
// 传值(谨慎使用,仅用于请求级别元数据)
type ctxKey string
const requestIDKey ctxKey = "request_id"
ctx = context.WithValue(ctx, requestIDKey, "req-123")
reqID := ctx.Value(requestIDKey).(string)io:I/O抽象
// 核心接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 组合使用
func processData(r io.Reader, w io.Writer) error {
// 高效拷贝
_, err := io.Copy(w, r)
return err
}
// 常用辅助函数
data, err := io.ReadAll(reader) // 读取所有内容
limited := io.LimitReader(r, 1<<20) // 限制读取量
tee := io.TeeReader(r, w) // 读取同时写入
multi := io.MultiReader(r1, r2, r3) // 串联多个reader
multi := io.MultiWriter(w1, w2) // 同时写入多个writer
piped := io.Pipe() // 同步管道sync:同步原语
// WaitGroup:等待一组goroutine完成
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
doWork(id)
}(i)
}
wg.Wait()
// Once:一次性初始化
var once sync.Once
var instance *Database
func GetDB() *Database {
once.Do(func() {
instance = connectDB()
})
return instance
}
// Map:并发安全的map
var cache sync.Map
cache.Store("key", "value")
val, ok := cache.Load("key")
cache.Range(func(key, value interface{}) bool {
fmt.Println(key, value)
return true // 返回false停止遍历
})time:时间处理
// 时间创建和格式化
now := time.Now()
t := time.Date(2025, 4, 29, 12, 0, 0, 0, time.UTC)
// Go的独特格式化方式:使用参考时间
// Mon Jan 2 15:04:05 MST 2006 (1 2 3 4 5 6 7)
formatted := now.Format("2006-01-02 15:04:05")
parsed, err := time.Parse("2006-01-02", "2025-04-29")
// 定时器
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
<-timer.C // 等待5秒
// 周期性执行
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for range ticker.C {
doPeriodicWork()
}
// 超时模式
select {
case result := <-longTask():
process(result)
case <-time.After(10 * time.Second):
log.Println("timeout")
}os:操作系统交互
// 文件操作
f, err := os.Create("output.txt")
if err != nil {
return err
}
defer f.Close()
f.WriteString("Hello\n")
data, err := os.ReadFile("config.json") // Go 1.16+
err = os.WriteFile("out.txt", data, 0644)
// 环境变量
val := os.Getenv("HOME")
val, ok := os.LookupEnv("APP_KEY")
// 进程
os.Exit(1) // 不会执行defer
// 目录操作
entries, err := os.ReadDir(".")
for _, e := range entries {
info, _ := e.Info()
fmt.Println(e.Name(), info.Size())
}sort:排序
// 内置排序
sort.Ints([]int{3, 1, 2})
sort.Strings([]string{"b", "a", "c"})
// 自定义排序
sort.Slice(users, func(i, j int) bool {
return users[i].Age < users[j].Age
})
// 稳定排序(保持相等元素的相对顺序)
sort.SliceStable(users, func(i, j int) bool {
return users[i].Name < users[j].Name
})
// Go 1.21+ slices包(泛型)
import "slices"
slices.Sort(nums)
slices.SortFunc(users, func(a, b User) int {
return cmp.Compare(a.Age, b.Age)
})
idx, found := slices.BinarySearch(sorted, target)regexp:正则表达式
// 编译正则(推荐使用MustCompile在init中编译)
re := regexp.MustCompile(`(\w+)@(\w+)\.(\w+)`)
// 匹配
matched := re.MatchString("user@example.com") // true
// 查找
match := re.FindString(text) // 第一个匹配
matches := re.FindAllString(text, -1) // 所有匹配
// 子匹配(捕获组)
groups := re.FindStringSubmatch("user@example.com")
// groups[0] = "user@example.com"
// groups[1] = "user"
// groups[2] = "example"
// groups[3] = "com"
// 替换
result := re.ReplaceAllString(text, "REDACTED")
// 性能注意:
// Go的regexp使用RE2引擎,保证O(n)时间复杂度
// 但比PCRE在某些模式上更慢
// 对于简单匹配,strings包的函数更快标准库使用原则
总结
| 包 | 用途 | 核心API |
|---|---|---|
| net/http | HTTP服务 | ServeMux, Client, Server |
| encoding/json | JSON编解码 | Marshal/Unmarshal, Encoder/Decoder |
| database/sql | 数据库 | Open, Query, Exec, Tx |
| context | 生命周期 | WithTimeout, WithCancel, WithValue |
| io | I/O抽象 | Reader, Writer, Copy, Pipe |
| sync | 同步原语 | Mutex, WaitGroup, Once, Pool |
| time | 时间处理 | Now, Parse, Timer, Ticker |
| os | 系统交互 | ReadFile, Create, Getenv |
| sort/slices | 排序 | Sort, SliceStable, BinarySearch |
| regexp | 正则 | Compile, FindString, ReplaceAll |
Go标准库的设计哲学是简洁、正交、可组合。io.Reader/io.Writer接口是整个标准库的组合核心,几乎所有I/O相关的包都围绕这两个接口构建。掌握标准库是成为高效Go开发者的基础。
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于