Go 标准库
本文按包介绍高频 API。每个 API 都配有独立示例;示例明确导入包并可单独保存为 .go 文件运行。网络、数据库、操作系统、测试及实验性 API 的运行前提会另行说明。
fmt:格式化输入输出
常用 API:fmt.Print、fmt.Println、fmt.Printf、fmt.Sprintf、 fmt.Errorf、fmt.Fprint、fmt.Scan、fmt.Sscan。
fmt.Print
fmt.Print 将参数写到标准输出,且不会自动追加换行符。
package main
import "fmt"
func main() {
// 不会自动换行。
// Hello, Go
fmt.Print("Hello, Go\n")
}fmt.Println
fmt.Println 将参数写到标准输出,并在末尾自动换行。
package main
import "fmt"
func main() {
// 会在参数间加空格并换行。
// Go 2026
fmt.Println("Go", 2026)
}fmt.Printf
fmt.Printf 按格式字符串格式化参数并写到标准输出。
package main
import "fmt"
func main() {
// 按格式字符串输出。
// 语言=Go,版本=1
fmt.Printf("语言=%s,版本=%d\n", "Go", 1)
}fmt.Sprintf
fmt.Sprintf 按格式字符串处理参数并返回结果字符串。
package main
import "fmt"
func main() {
// 返回格式化后的字符串。
message := fmt.Sprintf("%s-%03d", "item", 7)
// item-007
fmt.Println(message)
}fmt.Errorf
fmt.Errorf 按格式字符串创建错误,并可用 %w 包装原错误。
package main
import (
"errors"
"fmt"
)
func main() {
base := errors.New("连接失败")
// %w 用于包装原始错误。
err := fmt.Errorf("读取配置:%w", base)
// 读取配置:连接失败
fmt.Println(err)
}fmt.Fprint
fmt.Fprint 将参数格式化后写入指定的 io.Writer。
package main
import (
"fmt"
"os"
)
func main() {
// 写入 Writer
fmt.Fprint(os.Stdout, "写入 Writer\n")
}fmt.Scan
fmt.Scan 从标准输入扫描文本,并写入对应的目标变量。
package main
import "fmt"
func main() {
var name string
// 从标准输入读取;运行后请输入一个单词。
fmt.Scan(&name)
// 输出示例:Go(实际值取决于标准输入)
fmt.Println(name)
}fmt.Sscan
fmt.Sscan 从给定字符串扫描值,并写入对应的目标变量。
package main
import "fmt"
func main() {
var a, b int
// 从给定字符串中扫描值。
fmt.Sscan("10 20", &a, &b)
// 30
fmt.Println(a + b)
}html:HTML 文本转义
常用 API:html.EscapeString、html.UnescapeString。
html.EscapeString
html.EscapeString 用于转义 HTML 特殊字符。
package main
import (
"fmt"
"html"
)
func main() {
// 用于转义 HTML 特殊字符。
// <a href="?q=go&x=1">Go</a>。
fmt.Println(html.EscapeString(`<a href="?q=go&x=1">Go</a>`))
}html.UnescapeString
html.UnescapeString 用于还原 HTML 实体。
package main
import (
"fmt"
"html"
)
func main() {
// 用于还原 HTML 实体。
// <strong>Go</strong>
fmt.Println(html.UnescapeString("<strong>Go</strong>"))
}html/template:安全生成 HTML 模板
常用 API:template.New、Template.Parse、template.Must、Template.Execute、 Template.ExecuteTemplate。
template.New
template.New 用于创建具有指定名称的 HTML 模板。
package main
import (
"fmt"
"html/template"
)
func main() {
// 用于创建具有指定名称的 HTML 模板。
t := template.New("page")
// page
fmt.Println(t.Name())
}Template.Parse
Template.Parse 用于解析模板文本并关联到模板。
package main
import (
"fmt"
"html/template"
)
func main() {
t := template.New("page")
// Parse 是 html/template.Template 的方法,用于解析模板文本并关联到模板。
parsed, err := t.Parse(`<h1>{{.}}</h1>`)
if err != nil {
panic(err)
}
// page
fmt.Println(parsed.Name())
}template.Must
template.Must 解析失败时会 panic。
package main
import (
"fmt"
"html/template"
)
func main() {
// 解析失败时会 panic。
t := template.Must(template.New("page").Parse(`<p>{{.}}</p>`))
// page
fmt.Println(t.Name())
}Template.Execute
Template.Execute 会自动转义 HTML
package main
import (
"html/template"
"os"
)
func main() {
t := template.Must(template.New("page").Parse(`<p>{{.}}</p>`))
// Execute 会自动转义 HTML
if err := t.Execute(os.Stdout, `<script>alert(1)</script>`); err != nil {
panic(err)
}
}Template.ExecuteTemplate
Template.ExecuteTemplate 用于执行指定名称的模板。
package main
import (
"html/template"
"os"
)
func main() {
t := template.Must(template.New("root").Parse(`{{define "item"}}<b>{{.}}</b>{{end}}`))
// ExecuteTemplate 是 html/template.Template 的方法,用于执行指定名称的模板。
if err := t.ExecuteTemplate(os.Stdout, "item", "Go"); err != nil {
panic(err)
}
}net:网络地址与连接
常用 API:net.ParseIP、net.LookupHost、net.JoinHostPort、net.DialTimeout、 net.Listen。
net.ParseIP
net.ParseIP 不会发起网络请求。
package main
import (
"fmt"
"net"
)
func main() {
// 不会发起网络请求。
ip := net.ParseIP("192.0.2.1")
// 192.0.2.1
fmt.Println(ip)
}net.LookupHost
net.LookupHost 通过 DNS 查询主机名并返回对应的 IP 地址列表。
package main
import (
"fmt"
"net"
)
func main() {
// 需要可用的 DNS 与网络。
ips, err := net.LookupHost("example.com")
if err != nil {
panic(err)
}
// 输出示例:[93.184.216.34](实际 IP 列表及顺序取决于 DNS 与网络环境)
fmt.Println(ips)
}net.JoinHostPort
net.JoinHostPort 把主机和端口合成网络地址,并正确处理 IPv6 方括号。
package main
import (
"fmt"
"net"
)
func main() {
// 会正确处理 IPv6 方括号。
// [2001:db8::1]:443
fmt.Println(net.JoinHostPort("2001:db8::1", "443"))
}net.DialTimeout
net.DialTimeout 在指定超时内建立网络连接并返回连接对象。
package main
import (
"fmt"
"net"
"time"
)
func main() {
// 。
conn, err := net.DialTimeout("tcp", "example.com:80", 3*time.Second)
if err != nil {
panic(err)
}
defer conn.Close()
// 输出示例:93.184.216.34:80(实际地址取决于 DNS 与网络环境)
fmt.Println(conn.RemoteAddr())
}net.Listen
net.Listen 端口 0 让系统分配空闲端口。
package main
import (
"fmt"
"net"
)
func main() {
// 端口 0 让系统分配空闲端口。
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
panic(err)
}
defer listener.Close()
// 输出示例:127.0.0.1:54321(实际端口由操作系统分配)
fmt.Println(listener.Addr())
}flag:解析命令行参数
常用 API:flag.String、flag.Int、flag.Bool、flag.Parse、flag.Args。
flag.String
flag.String 返回字符串参数的指针。
package main
import (
"flag"
"fmt"
)
func main() {
// 返回字符串参数的指针。
name := flag.String("name", "world", "要问候的人")
flag.Parse()
// 输出示例:world(实际值取决于命令行参数)
fmt.Println(*name)
}flag.Int
flag.Int 定义整数命令行参数,并返回保存解析值的指针。
package main
import (
"flag"
"fmt"
)
func main() {
// 可用 go run . -count 3 测试。
count := flag.Int("count", 1, "次数")
flag.Parse()
// 输出示例:1(实际值取决于命令行参数)
fmt.Println(*count)
}flag.Bool
flag.Bool 定义布尔命令行参数,并返回保存解析值的指针。
package main
import (
"flag"
"fmt"
)
func main() {
// 声明布尔命令行参数。
verbose := flag.Bool("verbose", false, "详细输出")
flag.Parse()
// 输出示例:false(实际值取决于命令行参数)
fmt.Println(*verbose)
}flag.Parse
flag.Parse 解析 os.Args 中的参数。
package main
import (
"flag"
"fmt"
)
func main() {
// 解析 os.Args 中的参数。
flag.Parse()
// 参数解析完成
fmt.Println("参数解析完成")
}flag.Args
flag.Args 返回未被选项消费的位置参数。
package main
import (
"flag"
"fmt"
)
func main() {
flag.Parse()
// 返回未被选项消费的位置参数。
// 输出示例:[](实际内容取决于命令行参数)
fmt.Println(flag.Args())
}reflect:运行时反射操作
常用 API:reflect.TypeOf、reflect.ValueOf、reflect.DeepEqual、 reflect.MakeSlice。
reflect.TypeOf
reflect.TypeOf 返回值的动态类型。
package main
import (
"fmt"
"reflect"
)
func main() {
// 返回值的动态类型。
// map[string]int
fmt.Println(reflect.TypeOf(map[string]int{}))
}reflect.ValueOf
reflect.ValueOf Elem 取得指针指向的可设置值。
package main
import (
"fmt"
"reflect"
)
func main() {
name := "Go"
// Elem 取得指针指向的可设置值。
reflect.ValueOf(&name).Elem().SetString("Golang")
// Golang
fmt.Println(name)
}reflect.DeepEqual
reflect.DeepEqual 可深度比较切片等不可直接比较的值。
package main
import (
"fmt"
"reflect"
)
func main() {
// 可深度比较切片等不可直接比较的值。
// true
fmt.Println(reflect.DeepEqual([]int{1, 2}, []int{1, 2}))
}reflect.MakeSlice
reflect.MakeSlice 动态创建指定类型的切片。
package main
import (
"fmt"
"reflect"
)
func main() {
sliceType := reflect.TypeOf([]int{})
// 动态创建指定类型的切片。
value := reflect.MakeSlice(sliceType, 2, 4)
// [0 0]
fmt.Println(value.Interface())
}反射会绕过部分编译期类型检查,业务代码应优先使用接口和泛型。
log:记录程序日志
常用 API:log.Print、log.Printf、log.SetPrefix、log.SetFlags、log.New。
log.Print
log.Print 默认写入标准错误。
package main
import "log"
func main() {
// 默认写入标准错误。
log.Print("服务启动")
}log.Printf
log.Printf 支持 fmt 风格格式化。
package main
import "log"
func main() {
// 支持 fmt 风格格式化。
log.Printf("任务 %d 完成", 1)
}log.SetPrefix
log.SetPrefix 设置标准 Logger 的前缀。
package main
import "log"
func main() {
// 设置标准 Logger 的前缀。
log.SetPrefix("[app] ")
log.Print("ready")
}log.SetFlags
log.SetFlags 设置标准日志记录器使用的行首信息标志。
package main
import "log"
func main() {
// SetFlags 和 Ldate、。
log.SetFlags(log.Ldate | log.Ltime)
log.Print("ready")
}log.New
log.New 用输出目标、前缀和标志创建独立日志记录器。
package main
import (
"log"
"os"
)
func main() {
logger := log.New(os.Stdout, "[worker] ", log.LstdFlags)
logger.Print("ready")
}sort:数据排序与查找
常用 API:sort.Ints、sort.Strings、sort.Slice、sort.SearchInts、 sort.Search。
sort.Ints
sort.Ints 将整数切片按升序原地排序。
package main
import (
"fmt"
"sort"
)
func main() {
values := []int{5, 1, 3}
// 原地升序排列 []int。
sort.Ints(values)
// [1 3 5]
fmt.Println(values)
}sort.Strings
sort.Strings 按字典序原地排序。
package main
import (
"fmt"
"sort"
)
func main() {
values := []string{"Go", "C", "Rust"}
// 按字典序原地排序。
sort.Strings(values)
// [C Go Rust]
fmt.Println(values)
}sort.Slice
sort.Slice 这里按字符串长度排序。
package main
import (
"fmt"
"sort"
)
func main() {
values := []string{"Go", "Java", "C"}
// 这里按字符串长度排序。
sort.Slice(values, func(i, j int) bool { return len(values[i]) < len(values[j]) })
// [C Go Java]
fmt.Println(values)
}sort.SearchInts
sort.SearchInts 输入必须已升序排列。
package main
import (
"fmt"
"sort"
)
func main() {
values := []int{1, 3, 5, 7}
// 输入必须已升序排列。
// 2
fmt.Println(sort.SearchInts(values, 5))
}sort.Search
sort.Search 查找首个满足谓词的位置。
package main
import (
"fmt"
"sort"
)
func main() {
// 查找首个满足谓词的位置。
index := sort.Search(100, func(i int) bool { return i*i >= 200 })
// 15
fmt.Println(index)
}Go 1.21 及以上版本中,普通切片通常可优先使用泛型 slices 包。
regexp:正则表达式匹配
常用 API:regexp.Compile、regexp.MustCompile、Regexp.MatchString、 Regexp.FindStringSubmatch、Regexp.ReplaceAllString。
regexp.Compile
regexp.Compile 正则无效时返回错误。
package main
import (
"fmt"
"regexp"
)
func main() {
// 正则无效时返回错误。
re, err := regexp.Compile(`\d+`)
if err != nil {
panic(err)
}
// \d+
fmt.Println(re.String())
}regexp.MustCompile
regexp.MustCompile 编译正则表达式,模式无效时直接触发 panic。
package main
import (
"fmt"
"regexp"
)
func main() {
// 正则无效时会 panic。
re := regexp.MustCompile(`^[a-z]+$`)
// ^[a-z]+$
fmt.Println(re.String())
}Regexp.MatchString
Regexp.MatchString 判断输入字符串是否包含正则表达式匹配。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`^\w+@[\w.]+$`)
// MatchString 是 regexp.Regexp 的方法。
// true
fmt.Println(re.MatchString("dev@example.com"))
}Regexp.FindStringSubmatch
Regexp.FindStringSubmatch 返回完整匹配及各捕获组。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(\w+)@([\w.]+)`)
// FindStringSubmatch 是 regexp.Regexp 的方法,返回完整匹配及各捕获组。
// [dev@example.com dev example.com]
fmt.Println(re.FindStringSubmatch("dev@example.com"))
}Regexp.ReplaceAllString
Regexp.ReplaceAllString 用替换模板处理全部匹配。
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(\w+)@([\w.]+)`)
// ReplaceAllString 是 regexp.Regexp 的方法,用替换模板处理全部匹配。
// ***@example.com
fmt.Println(re.ReplaceAllString("dev@example.com", "***@$2"))
}Go 正则采用 RE2 语法,不支持反向引用和环视。
image:图像创建与编码
常用 API:image.Rect、image.NewRGBA、Image.Bounds、png.Encode。
image.Rect
image.Rect 根据两个角点坐标创建矩形范围。
package main
import (
"fmt"
"image"
)
func main() {
// 构造半开区间矩形。
// (0,0)-(100,50)
fmt.Println(image.Rect(0, 0, 100, 50))
}image.NewRGBA
image.NewRGBA 按给定矩形范围创建 RGBA 图像。
package main
import (
"fmt"
"image"
"image/color"
)
func main() {
// 。
img := image.NewRGBA(image.Rect(0, 0, 2, 2))
img.Set(0, 0, color.RGBA{R: 255, A: 255})
// {255 0 0 255}
fmt.Println(img.RGBAAt(0, 0))
}Image.Bounds
Image.Bounds 返回图像覆盖范围的最小外接矩形。
package main
import (
"fmt"
"image"
)
func main() {
img := image.NewGray(image.Rect(0, 0, 20, 10))
// Bounds 是 image.Image 接口定义的方法。
// (0,0)-(20,10)
fmt.Println(img.Bounds())
}png.Encode
png.Encode 将图像编码为 PNG。
package main
import (
"image"
"image/png"
"os"
)
func main() {
img := image.NewRGBA(image.Rect(0, 0, 2, 2))
file, err := os.Create("result.png")
if err != nil {
panic(err)
}
defer file.Close()
// 将图像编码为 PNG。
if err := png.Encode(file, img); err != nil {
panic(err)
}
}time:时间日期与计时
常用 API:time.Now、Time.Format、time.Parse、Time.Add、time.Since、 time.NewTimer、time.NewTicker、time.Sleep。
time.Now
time.Now 返回当前本地时间。
package main
import (
"fmt"
"time"
)
func main() {
// 返回当前本地时间。
// 输出示例:2026-07-12 14:30:00 +0800 CST(实际值取决于当前时间与时区)
fmt.Println(time.Now())
}Time.Format
Time.Format 按布局字符串格式化时间并返回文本结果。
package main
import (
"fmt"
"time"
)
func main() {
// Format 是 time.Time 的方法;布局使用 Go 的参考时间。
// 2026-07-12 12:00:00
fmt.Println(time.Date(2026, 7, 12, 12, 0, 0, 0, time.UTC).Format("2006-01-02 15:04:05"))
}time.Parse
time.Parse 按指定布局解析字符串。
package main
import (
"fmt"
"time"
)
func main() {
// 按指定布局解析字符串。
value, err := time.Parse("2006-01-02", "2026-07-12")
if err != nil {
panic(err)
}
// 2026-07-12 00:00:00 +0000 UTC
fmt.Println(value)
}Time.Add
Time.Add 把指定时长加到时间上并返回新时间。
package main
import (
"fmt"
"time"
)
func main() {
start := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
// Add 是 time.Time 的方法;Hour 是 time 包常量。
// 2026-01-02 00:00:00 +0000 UTC
fmt.Println(start.Add(24 * time.Hour))
}time.Since
time.Since 返回从指定时间到当前时刻经过的时长。
package main
import (
"fmt"
"time"
)
func main() {
start := time.Now()
// 等价于 time.Now().Sub(start)。
// true
fmt.Println(time.Since(start) >= 0)
}time.NewTimer
time.NewTimer 只触发一次。
package main
import (
"fmt"
"time"
)
func main() {
// 只触发一次。
timer := time.NewTimer(10 * time.Millisecond)
<-timer.C
// 到期
fmt.Println("到期")
}time.NewTicker
time.NewTicker 会按间隔持续触发。
package main
import (
"fmt"
"time"
)
func main() {
// 会按间隔持续触发。
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
// false
fmt.Println((<-ticker.C).IsZero())
}time.Sleep
time.Sleep 暂停当前 goroutine,直到指定时长结束。
package main
import (
"fmt"
"time"
)
func main() {
// 使当前 goroutine 暂停。
time.Sleep(10 * time.Millisecond)
// 继续执行
fmt.Println("继续执行")
}unicode:Unicode 字符处理
常用 API:unicode.IsLetter、unicode.IsDigit、unicode.IsSpace、 unicode.ToUpper、unicode.ToLower。
unicode.IsLetter
unicode.IsLetter 按 Unicode 属性判断 rune。
package main
import (
"fmt"
"unicode"
)
func main() {
// 按 Unicode 属性判断 rune。
// true
fmt.Println(unicode.IsLetter('界'))
}unicode.IsDigit
unicode.IsDigit 判断输入字符是否属于 Unicode 十进制数字。
package main
import (
"fmt"
"unicode"
)
func main() {
// 可识别非 ASCII 数字。
// true
fmt.Println(unicode.IsDigit('9'))
}unicode.IsSpace
unicode.IsSpace 判断 Unicode 空白字符。
package main
import (
"fmt"
"unicode"
)
func main() {
// 判断 Unicode 空白字符。
// true
fmt.Println(unicode.IsSpace('\n'))
}unicode.ToUpper
unicode.ToUpper 转换单个 rune。
package main
import (
"fmt"
"unicode"
)
func main() {
// 转换单个 rune。
// G
fmt.Println(string(unicode.ToUpper('g')))
}unicode.ToLower
unicode.ToLower 转换单个 rune。
package main
import (
"fmt"
"unicode"
)
func main() {
// 转换单个 rune。
// g
fmt.Println(string(unicode.ToLower('G')))
}unsafe:底层内存操作
常用 API:unsafe.Sizeof、unsafe.Alignof、unsafe.Offsetof、 unsafe.Pointer。
unsafe.Sizeof
unsafe.Sizeof 返回值占用的字节数。
package main
import (
"fmt"
"unsafe"
)
func main() {
var value uint64
// 返回值占用的字节数。
// 8
fmt.Println(unsafe.Sizeof(value))
}unsafe.Alignof
unsafe.Alignof 返回所需内存对齐。
package main
import (
"fmt"
"unsafe"
)
func main() {
var value int64
// 返回所需内存对齐。
// 8
fmt.Println(unsafe.Alignof(value))
}unsafe.Offsetof
unsafe.Offsetof 返回字段相对结构体起始地址的偏移。
package main
import (
"fmt"
"unsafe"
)
func main() {
value := struct {
A byte
B int64
}{}
// 返回字段相对结构体起始地址的偏移。
// 8
fmt.Println(unsafe.Offsetof(value.B))
}unsafe.Pointer
unsafe.Pointer 在指针类型间进行底层转换,不提供内存安全保证。
package main
import (
"fmt"
"unsafe"
)
func main() {
var value uint32 = 0x12345678
// 结果依赖机器字节序。
first := *(*byte)(unsafe.Pointer(&value))
// 输出示例:78(实际值取决于机器字节序)
fmt.Printf("%x\n", first)
}unsafe 会绕过类型和内存安全保障,普通业务代码不应使用它简化类型转换。
syscall:操作系统底层调用
常用 API:syscall.Getpid、syscall.Getenv、syscall.Stat。
syscall.Getpid
syscall.Getpid 返回当前进程 ID。
package main
import (
"fmt"
"syscall"
)
func main() {
// 返回当前进程 ID。
// 输出示例:12345(实际值取决于当前进程)
fmt.Println(syscall.Getpid())
}syscall.Getenv
syscall.Getenv 读取环境变量,并返回值和是否存在的标志。
package main
import (
"fmt"
"syscall"
)
func main() {
// 新代码通常应使用 os.LookupEnv。
value, found := syscall.Getenv("PATH")
// 输出示例:true 256(实际值取决于 PATH 环境变量)
fmt.Println(found, len(value))
}syscall.Stat
syscall.Stat 读取 Unix 路径的文件元数据并写入结构体。
下面的 API 仅适用于 Unix;Windows 上应使用 os.Stat 或 golang.org/x/sys/windows。syscall 已冻结,新代码应优先选择 os、net 或 golang.org/x/sys。
//go:build unix
package main
import (
"fmt"
"syscall"
)
func main() {
var info syscall.Stat_t
// 此示例仅在 Unix 编译运行。
if err := syscall.Stat(".", &info); err != nil {
panic(err)
}
// 输出示例:4096(实际值取决于当前目录及文件系统)
fmt.Println(info.Size)
}testing:测试基准与模糊测试
常用 API:t.Run、t.Helper、t.Fatal、b.Run、b.Loop、f.Fuzz。 测试示例必须保存为 _test.go 并通过 go test 运行,因此按 Go 约定使用测试包, 不包含 func main。
t.Run
t.Run 用于创建子测试。
package demo_test
import "testing"
func TestRun(t *testing.T) {
// Run 是 testing.T 的方法,用于创建子测试。
t.Run("addition", func(t *testing.T) {
if 2+3 != 5 {
t.Fatal("加法结果错误")
}
})
}t.Helper
t.Helper 使失败位置指向调用者。
package demo_test
import "testing"
func requireEqual(t *testing.T, got, want int) {
// Helper 是 testing.T 的方法,使失败位置指向调用者。
t.Helper()
if got != want {
t.Fatalf("得到 %d,期望 %d", got, want)
}
}
func TestEqual(t *testing.T) {
requireEqual(t, 2+3, 5)
}t.Fatal
t.Fatal 记录失败信息并立即终止当前测试。
package demo_test
import "testing"
func TestValue(t *testing.T) {
// Fatal 是 testing.T 的方法,记录失败并终止当前测试。
if len("Go") != 2 {
t.Fatal("长度错误")
}
}b.Run
b.Run 用于创建子基准测试。
package demo_test
import "testing"
func BenchmarkLength(b *testing.B) {
// Run 是 testing.B 的方法,用于创建子基准测试。
b.Run("short", func(b *testing.B) {
for b.Loop() {
_ = len("Go")
}
})
}b.Loop
b.Loop 按测试框架控制的次数迭代基准测试主体。
package demo_test
import "testing"
func BenchmarkAddition(b *testing.B) {
// Loop 是 testing.B 的方法,由测试框架控制迭代次数。
for b.Loop() {
_ = 2 + 3
}
}f.Fuzz
f.Fuzz 注册模糊测试目标函数及其种子输入。
package demo_test
import (
"strings"
"testing"
)
func FuzzUpper(f *testing.F) {
f.Add("Go")
// Fuzz 是 testing.F 的方法。
f.Fuzz(func(t *testing.T, input string) {
_ = strings.ToUpper(input)
})
}b.Loop 需要支持该 API 的较新 Go 版本。执行命令为 go test ./...、 go test -bench=. ./... 和 go test -fuzz=FuzzUpper。
sync:并发同步与对象复用
常用 API:Mutex.Lock、RWMutex.RLock、WaitGroup.Go、Once.Do、 sync.Map.LoadOrStore、sync.Pool.Get。
Mutex.Lock
Mutex.Lock 获取互斥锁;锁已占用时阻塞当前 goroutine。
package main
import (
"fmt"
"sync"
)
func main() {
var mutex sync.Mutex
total := 0
// Lock 和 Unlock 是 sync.Mutex 的方法。
mutex.Lock()
total++
mutex.Unlock()
// 1
fmt.Println(total)
}RWMutex.RLock
RWMutex.RLock 和 RUnlock 是 sync.RWMutex 的只读锁方法。
package main
import (
"fmt"
"sync"
)
func main() {
var mutex sync.RWMutex
value := 42
// RLock 和 RUnlock 是 sync.RWMutex 的只读锁方法。
mutex.RLock()
// 42
fmt.Println(value)
mutex.RUnlock()
}WaitGroup.Go
WaitGroup.Go 启动函数并自动跟踪其 goroutine 的完成状态。
package main
import (
"fmt"
"sync"
)
func main() {
var group sync.WaitGroup
// Go 是 sync.WaitGroup 的方法,在新 goroutine 中运行函数并自动计数。
// 完成
group.Go(func() { fmt.Println("完成") })
group.Wait()
}WaitGroup.Go 需要 Go 1.25 或更高版本;旧版本使用 Add、Done 和 Wait。
Once.Do
Once.Do 同一个 Once 只执行一次函数。
package main
import (
"fmt"
"sync"
)
func main() {
var once sync.Once
// Do 是 sync.Once 的方法,同一个 Once 只执行一次函数。
// 初始化
once.Do(func() { fmt.Println("初始化") })
}sync.Map.LoadOrStore
sync.Map.LoadOrStore 读取键的已有值,或在不存在时存入新值。
package main
import (
"fmt"
"sync"
)
func main() {
var values sync.Map
// LoadOrStore 是 sync.Map 的方法。
actual, loaded := values.LoadOrStore("language", "Go")
// Go false
fmt.Println(actual, loaded)
}sync.Pool.Get
sync.Pool.Get 池中无值时调用 New。
package main
import (
"fmt"
"sync"
)
func main() {
pool := sync.Pool{New: func() any { return make([]byte, 0, 64) }}
// Get 是 sync.Pool 的方法,池中无值时调用 New。
buffer := pool.Get().([]byte)
// 64
fmt.Println(cap(buffer))
}context:传递取消与截止时间
常用 API:context.Background、context.WithCancel、context.WithTimeout、 context.WithDeadline、context.WithValue、Context.Done。
context.Background
context.Background 返回不可取消且不含值的根上下文。
package main
import (
"context"
"fmt"
)
func main() {
// 通常作为上下文树的根。
// <nil>
fmt.Println(context.Background().Err())
}context.WithCancel
context.WithCancel 返回派生上下文和取消函数。
package main
import (
"context"
"fmt"
)
func main() {
// 返回派生上下文和取消函数。
ctx, cancel := context.WithCancel(context.Background())
cancel()
// context canceled
fmt.Println(ctx.Err())
}context.WithTimeout
context.WithTimeout 创建在指定时长后自动取消的派生上下文。
package main
import (
"context"
"fmt"
"time"
)
func main() {
// 。
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
<-ctx.Done()
// context deadline exceeded
fmt.Println(ctx.Err())
}context.WithDeadline
context.WithDeadline 在指定时间取消上下文。
package main
import (
"context"
"fmt"
"time"
)
func main() {
deadline := time.Now().Add(time.Second)
// 在指定时间取消上下文。
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()
value, ok := ctx.Deadline()
// true true
fmt.Println(value.Equal(deadline), ok)
}context.WithValue
context.WithValue 仅应用于请求范围元数据。
package main
import (
"context"
"fmt"
)
type requestIDKey struct{}
func main() {
// 仅应用于请求范围元数据。
ctx := context.WithValue(context.Background(), requestIDKey{}, "req-1")
// req-1
fmt.Println(ctx.Value(requestIDKey{}))
}Context.Done
Context.Done 返回取消信号通道。
package main
import (
"context"
"fmt"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
cancel()
// Done 是 context.Context 接口的方法,返回取消信号通道。
<-ctx.Done()
// 已取消
fmt.Println("已取消")
}Context 通常作为函数的第一个参数传递,不应长期保存在结构体中。
strconv:字符串与基础类型转换
常用 API:strconv.Atoi、strconv.Itoa、strconv.ParseBool、 strconv.ParseInt、strconv.ParseFloat、strconv.FormatInt、 strconv.Quote、strconv.Unquote。
strconv.Atoi
strconv.Atoi 将十进制字符串转换为 int。
package main
import (
"fmt"
"strconv"
)
func main() {
// 将十进制字符串转换为 int。
value, err := strconv.Atoi("42")
if err != nil {
panic(err)
}
// 42
fmt.Println(value)
}strconv.Itoa
strconv.Itoa 将 int 转换为十进制字符串。
package main
import (
"fmt"
"strconv"
)
func main() {
// 将 int 转换为十进制字符串。
// 42
fmt.Println(strconv.Itoa(42))
}strconv.ParseBool
strconv.ParseBool 解析受支持的布尔文本。
package main
import (
"fmt"
"strconv"
)
func main() {
// 解析受支持的布尔文本。
value, err := strconv.ParseBool("true")
if err != nil {
panic(err)
}
// true
fmt.Println(value)
}strconv.ParseInt
strconv.ParseInt 按进制和位宽解析字符串并返回有符号整数。
package main
import (
"fmt"
"strconv"
)
func main() {
// base=0 自动识别 0x 等前缀。
value, err := strconv.ParseInt("0xff", 0, 64)
if err != nil {
panic(err)
}
// 255
fmt.Println(value)
}strconv.ParseFloat
strconv.ParseFloat bitSize=64 返回 float64 精度。
package main
import (
"fmt"
"strconv"
)
func main() {
// bitSize=64 返回 float64 精度。
value, err := strconv.ParseFloat("3.14", 64)
if err != nil {
panic(err)
}
// 3.14
fmt.Println(value)
}strconv.FormatInt
strconv.FormatInt 这里转换为十六进制。
package main
import (
"fmt"
"strconv"
)
func main() {
// 这里转换为十六进制。
// ff
fmt.Println(strconv.FormatInt(255, 16))
}strconv.Quote
strconv.Quote 返回合法的 Go 双引号字符串字面量。
package main
import (
"fmt"
"strconv"
)
func main() {
// 返回合法的 Go 双引号字符串字面量。
// "hello\nGo"
fmt.Println(strconv.Quote("hello\nGo"))
}strconv.Unquote
strconv.Unquote 解析 Go 字符串字面量。
package main
import (
"fmt"
"strconv"
)
func main() {
// 解析 Go 字符串字面量。
value, err := strconv.Unquote(`"hello\nGo"`)
if err != nil {
panic(err)
}
// hello
// Go
fmt.Println(value)
}strings:字符串查询与处理
常用 API:strings.Contains、strings.Index、strings.Split、strings.Join、 strings.ReplaceAll、strings.TrimSpace、strings.ToUpper、 strings.Builder。
strings.Contains
strings.Contains 判断是否包含子串。
package main
import (
"fmt"
"strings"
)
func main() {
// 判断是否包含子串。
// true
fmt.Println(strings.Contains("Hello Go", "Go"))
}strings.Index
strings.Index 返回子串首字节位置,未找到返回 -1。
package main
import (
"fmt"
"strings"
)
func main() {
// 返回子串首字节位置,未找到返回 -1。
// 2
fmt.Println(strings.Index("Gopher", "ph"))
}strings.Split
strings.Split 按分隔符拆分字符串。
package main
import (
"fmt"
"strings"
)
func main() {
// 按分隔符拆分字符串。
// [Go Rust C]
fmt.Println(strings.Split("Go,Rust,C", ","))
}strings.Join
strings.Join 用分隔符连接字符串切片。
package main
import (
"fmt"
"strings"
)
func main() {
// 用分隔符连接字符串切片。
// Go | Rust
fmt.Println(strings.Join([]string{"Go", "Rust"}, " | "))
}strings.ReplaceAll
strings.ReplaceAll 替换全部匹配子串。
package main
import (
"fmt"
"strings"
)
func main() {
// 替换全部匹配子串。
// Go Go
fmt.Println(strings.ReplaceAll("go go", "go", "Go"))
}strings.TrimSpace
strings.TrimSpace 移除两端 Unicode 空白。
package main
import (
"fmt"
"strings"
)
func main() {
// 移除两端 Unicode 空白。
// "Go"
fmt.Printf("%q\n", strings.TrimSpace(" \tGo\n"))
}strings.ToUpper
strings.ToUpper 按 Unicode 规则转换字符串。
package main
import (
"fmt"
"strings"
)
func main() {
// 按 Unicode 规则转换字符串。
// GO
fmt.Println(strings.ToUpper("Go"))
}strings.Builder
strings.Builder 通过连续写入高效拼接字符串,并返回最终内容。
package main
import (
"fmt"
"strings"
)
func main() {
var builder strings.Builder
// Builder、WriteString 与 String 都由 strings 包提供。
builder.WriteString("Hello")
builder.WriteString(" Go")
// Hello Go
fmt.Println(builder.String())
}bytes:字节切片与缓冲区
常用 API:bytes.Contains、bytes.Equal、bytes.Split、bytes.ToUpper、 bytes.Buffer、bytes.NewReader。
bytes.Contains
bytes.Contains 判断字节切片是否包含子切片。
package main
import (
"bytes"
"fmt"
)
func main() {
// 判断字节切片是否包含子切片。
// true
fmt.Println(bytes.Contains([]byte("hello go"), []byte("go")))
}bytes.Equal
bytes.Equal 比较两个字节切片内容。
package main
import (
"bytes"
"fmt"
)
func main() {
// 比较两个字节切片内容。
// true
fmt.Println(bytes.Equal([]byte{1, 2}, []byte{1, 2}))
}bytes.Split
bytes.Split 按字节分隔符拆分。
package main
import (
"bytes"
"fmt"
)
func main() {
// 按字节分隔符拆分。
// ["a" "b"]
fmt.Printf("%q\n", bytes.Split([]byte("a,b"), []byte(",")))
}bytes.ToUpper
bytes.ToUpper 返回大写形式的新切片。
package main
import (
"bytes"
"fmt"
)
func main() {
// 返回大写形式的新切片。
// GO
fmt.Println(string(bytes.ToUpper([]byte("Go"))))
}bytes.Buffer
bytes.Buffer 在内存缓冲区中读写字节,并可返回累积内容。
package main
import (
"bytes"
"fmt"
)
func main() {
var buffer bytes.Buffer
// 。
buffer.WriteString("Hello Go")
// Hello Go
fmt.Println(buffer.String())
}bytes.NewReader
bytes.NewReader 创建只读且可 Seek 的 Reader。
package main
import (
"bytes"
"fmt"
)
func main() {
// 创建只读且可 Seek 的 Reader。
reader := bytes.NewReader([]byte("Go"))
// 2
fmt.Println(reader.Len())
}maps:泛型映射操作
常用 API:maps.Clone、maps.Copy、maps.Equal、maps.DeleteFunc、 maps.Keys。
maps.Clone
maps.Clone 对 Map 做浅复制。
package main
import (
"fmt"
"maps"
)
func main() {
// 对 Map 做浅复制。
cloned := maps.Clone(map[string]int{"a": 1})
// map[a:1]
fmt.Println(cloned)
}maps.Copy
maps.Copy 将源 Map 的条目写入目标 Map。
package main
import (
"fmt"
"maps"
)
func main() {
dst := map[string]int{"a": 1}
// 将源 Map 的条目写入目标 Map。
maps.Copy(dst, map[string]int{"b": 2})
// 输出示例:map[a:1 b:2](实际键顺序不保证)
fmt.Println(dst)
}maps.Equal
maps.Equal 比较键值均可比较的两个 Map。
package main
import (
"fmt"
"maps"
)
func main() {
// 比较键值均可比较的两个 Map。
// true
fmt.Println(maps.Equal(map[string]int{"a": 1}, map[string]int{"a": 1}))
}maps.DeleteFunc
maps.DeleteFunc 删除谓词返回 true 的条目。
package main
import (
"fmt"
"maps"
)
func main() {
values := map[string]int{"a": 1, "b": 2}
// 删除谓词返回 true 的条目。
maps.DeleteFunc(values, func(_ string, value int) bool { return value < 2 })
// map[b:2]
fmt.Println(values)
}maps.Keys
maps.Keys 返回遍历映射全部键的迭代器。
package main
import (
"fmt"
"maps"
"slices"
)
func main() {
// 并返回迭代器。
keys := slices.Collect(maps.Keys(map[string]int{"a": 1, "b": 2}))
// 输出示例:[a b](实际键顺序不保证)
fmt.Println(keys)
}maps.Keys 返回迭代器的形式需要 Go 1.23 或更高版本。
slices:泛型切片操作
常用 API:slices.Sort、slices.Contains、slices.Index、slices.Equal、 slices.Insert、slices.Delete、slices.Compact、slices.Clone。
slices.Sort
slices.Sort 原地升序排序有序类型切片。
package main
import (
"fmt"
"slices"
)
func main() {
values := []int{3, 1, 2}
// 原地升序排序有序类型切片。
slices.Sort(values)
// [1 2 3]
fmt.Println(values)
}slices.Contains
slices.Contains 判断切片是否包含值。
package main
import (
"fmt"
"slices"
)
func main() {
// 判断切片是否包含值。
// true
fmt.Println(slices.Contains([]string{"Go", "Rust"}, "Go"))
}slices.Index
slices.Index 返回首个匹配位置。
package main
import (
"fmt"
"slices"
)
func main() {
// 返回首个匹配位置。
// 1
fmt.Println(slices.Index([]int{10, 20, 30}, 20))
}slices.Equal
slices.Equal 按顺序比较切片元素。
package main
import (
"fmt"
"slices"
)
func main() {
// 按顺序比较切片元素。
// true
fmt.Println(slices.Equal([]int{1, 2}, []int{1, 2}))
}slices.Insert
slices.Insert 在指定位置插入元素。
package main
import (
"fmt"
"slices"
)
func main() {
// 在指定位置插入元素。
// [1 2 3]
fmt.Println(slices.Insert([]int{1, 3}, 1, 2))
}slices.Delete
slices.Delete 删除半开区间 [i:j)。
package main
import (
"fmt"
"slices"
)
func main() {
// 删除半开区间 [i:j)。
// [1 3]
fmt.Println(slices.Delete([]int{1, 2, 3}, 1, 2))
}slices.Compact
slices.Compact 删除相邻重复元素。
package main
import (
"fmt"
"slices"
)
func main() {
// 删除相邻重复元素。
// [1 2 1]
fmt.Println(slices.Compact([]int{1, 1, 2, 2, 1}))
}slices.Clone
slices.Clone 对切片做浅复制。
package main
import (
"fmt"
"slices"
)
func main() {
// 对切片做浅复制。
// [1 2 3]
fmt.Println(slices.Clone([]int{1, 2, 3}))
}io:流式输入输出
常用 API:io.Copy、io.ReadAll、io.LimitReader、io.MultiReader、 io.TeeReader、io.Pipe。
io.Copy
io.Copy 从源 Reader 持续复制数据到目标 Writer。
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
var dst bytes.Buffer
// 。
count, err := io.Copy(&dst, strings.NewReader("hello"))
if err != nil {
panic(err)
}
// 5 hello
fmt.Println(count, dst.String())
}io.ReadAll
io.ReadAll 会读到 EOF。
package main
import (
"fmt"
"io"
"strings"
)
func main() {
// 会读到 EOF。
data, err := io.ReadAll(strings.NewReader("hello"))
if err != nil {
panic(err)
}
// hello
fmt.Println(string(data))
}io.LimitReader
io.LimitReader 只暴露前 n 字节。
package main
import (
"fmt"
"io"
"strings"
)
func main() {
// 只暴露前 n 字节。
reader := io.LimitReader(strings.NewReader("abcdef"), 3)
data, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
// abc
fmt.Println(string(data))
}io.MultiReader
io.MultiReader 顺序读取多个 Reader。
package main
import (
"fmt"
"io"
"strings"
)
func main() {
// 顺序读取多个 Reader。
reader := io.MultiReader(strings.NewReader("Hello "), strings.NewReader("Go"))
data, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
// Hello Go
fmt.Println(string(data))
}io.TeeReader
io.TeeReader 读取时同步写入另一个 Writer。
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
var copy bytes.Buffer
// 读取时同步写入另一个 Writer。
reader := io.TeeReader(strings.NewReader("Go"), ©)
data, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
// Go Go
fmt.Println(string(data), copy.String())
}io.Pipe
io.Pipe 创建同步内存管道。
package main
import (
"fmt"
"io"
)
func main() {
// 创建同步内存管道。
reader, writer := io.Pipe()
go func() {
defer writer.Close()
_, _ = writer.Write([]byte("Go"))
}()
data, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
// Go
fmt.Println(string(data))
}io/fs:文件系统抽象
常用 API:fs.ReadFile、fs.ReadDir、fs.WalkDir、fs.Glob、fs.ValidPath。
fs.ReadFile
fs.ReadFile 从给定文件系统读取指定文件的全部内容。
package main
import (
"fmt"
"io/fs"
"testing/fstest"
)
func main() {
files := fstest.MapFS{"hello.txt": {Data: []byte("Go")}}
// 。
data, err := fs.ReadFile(files, "hello.txt")
if err != nil {
panic(err)
}
// Go
fmt.Println(string(data))
}fs.ReadDir
fs.ReadDir 返回按文件名排序的目录项。
package main
import (
"fmt"
"io/fs"
"testing/fstest"
)
func main() {
files := fstest.MapFS{"docs/a.txt": {Data: []byte("A")}}
// 返回按文件名排序的目录项。
entries, err := fs.ReadDir(files, "docs")
if err != nil {
panic(err)
}
// a.txt
fmt.Println(entries[0].Name())
}fs.WalkDir
fs.WalkDir 按词法顺序遍历文件树。
package main
import (
"fmt"
"io/fs"
"testing/fstest"
)
func main() {
files := fstest.MapFS{"a.txt": {Data: []byte("A")}}
// 按词法顺序遍历文件树。
err := fs.WalkDir(files, ".", func(path string, _ fs.DirEntry, err error) error {
//
// .
// a.txt
fmt.Println(path)
return err
})
if err != nil {
panic(err)
}
}fs.Glob
fs.Glob 按 path.Match 语法匹配路径。
package main
import (
"fmt"
"io/fs"
"testing/fstest"
)
func main() {
files := fstest.MapFS{"a.go": {}, "b.txt": {}}
// 按 path.Match 语法匹配路径。
matches, err := fs.Glob(files, "*.go")
if err != nil {
panic(err)
}
// [a.go]
fmt.Println(matches)
}fs.ValidPath
fs.ValidPath 检查是否为合法的 FS 路径。
package main
import (
"fmt"
"io/fs"
)
func main() {
// 检查是否为合法的 FS 路径。
// true
fmt.Println(fs.ValidPath("docs/readme.md"))
}os:文件与操作系统交互
常用 API:os.Create、os.Open、os.ReadFile、os.WriteFile、os.Stat、 os.MkdirAll、os.Remove、os.Getenv、os.LookupEnv。
os.Create
os.Create 创建或截断文件。
package main
import (
"fmt"
"os"
)
func main() {
// 创建或截断文件。
file, err := os.Create("demo.txt")
if err != nil {
panic(err)
}
defer file.Close()
// demo.txt
fmt.Println(file.Name())
}os.Open
os.Open 以只读方式打开当前目录。
package main
import (
"fmt"
"os"
)
func main() {
// 以只读方式打开当前目录。
dir, err := os.Open(".")
if err != nil {
panic(err)
}
defer dir.Close()
// .
fmt.Println(dir.Name())
}os.ReadFile
os.ReadFile 一次性读取整个文件。
package main
import (
"fmt"
"os"
)
func main() {
if err := os.WriteFile("demo.txt", []byte("Go"), 0o600); err != nil {
panic(err)
}
defer os.Remove("demo.txt")
// 一次性读取整个文件。
data, err := os.ReadFile("demo.txt")
if err != nil {
panic(err)
}
// Go
fmt.Println(string(data))
}os.WriteFile
os.WriteFile 一次性写入文件。
package main
import (
"fmt"
"os"
)
func main() {
// 一次性写入文件。
if err := os.WriteFile("demo.txt", []byte("Hello Go"), 0o600); err != nil {
panic(err)
}
defer os.Remove("demo.txt")
// 写入完成
fmt.Println("写入完成")
}os.Stat
os.Stat 读取文件或目录元数据。
package main
import (
"fmt"
"os"
)
func main() {
// 读取文件或目录元数据。
info, err := os.Stat(".")
if err != nil {
panic(err)
}
// true
fmt.Println(info.IsDir())
}os.MkdirAll
os.MkdirAll 递归创建目录。
package main
import (
"fmt"
"os"
)
func main() {
// 递归创建目录。
if err := os.MkdirAll("tmp/a/b", 0o755); err != nil {
panic(err)
}
defer os.RemoveAll("tmp")
// 目录已创建
fmt.Println("目录已创建")
}os.Remove
os.Remove 删除文件或空目录。
package main
import (
"fmt"
"os"
)
func main() {
if err := os.WriteFile("demo.txt", nil, 0o600); err != nil {
panic(err)
}
// 删除文件或空目录。
if err := os.Remove("demo.txt"); err != nil {
panic(err)
}
// 已删除
fmt.Println("已删除")
}os.Getenv
os.Getenv 变量不存在时返回空字符串。
package main
import (
"fmt"
"os"
)
func main() {
// 变量不存在时返回空字符串。
// 输出示例:true(实际值取决于 PATH 环境变量)
fmt.Println(len(os.Getenv("PATH")) > 0)
}os.LookupEnv
os.LookupEnv 可区分不存在与值为空。
package main
import (
"fmt"
"os"
)
func main() {
// 可区分不存在与值为空。
value, found := os.LookupEnv("PATH")
// 输出示例:true 256(实际值取决于 PATH 环境变量)
fmt.Println(found, len(value))
}os/signal:处理进程信号
常用 API:signal.Notify、signal.Stop、signal.Ignore、 signal.NotifyContext。
signal.Notify
signal.Notify 把指定操作系统信号转发到给定通道。
package main
import (
"fmt"
"os"
"os/signal"
)
func main() {
signals := make(chan os.Signal, 1)
// 。
signal.Notify(signals, os.Interrupt)
defer signal.Stop(signals)
// 按 Ctrl+C 退出
fmt.Println("按 Ctrl+C 退出")
// 输出示例:interrupt(实际值取决于收到的操作系统信号)
fmt.Println(<-signals)
}signal.Stop
signal.Stop 停止向通道转发信号。
package main
import (
"fmt"
"os"
"os/signal"
)
func main() {
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt)
// 停止向通道转发信号。
signal.Stop(signals)
// 已停止通知
fmt.Println("已停止通知")
}signal.Ignore
signal.Ignore 此处忽略中断信号。
package main
import (
"fmt"
"os"
"os/signal"
)
func main() {
// 此处忽略中断信号。
signal.Ignore(os.Interrupt)
// 当前进程忽略 Ctrl+C
fmt.Println("当前进程忽略 Ctrl+C")
}signal.NotifyContext
signal.NotifyContext 运行后按 Ctrl+C。
package main
import (
"context"
"fmt"
"os"
"os/signal"
)
func main() {
// 运行后按 Ctrl+C。
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
// 等待中断
fmt.Println("等待中断")
<-ctx.Done()
}不同操作系统支持的信号并不完全相同。
os/exec:执行外部命令
常用 API:exec.Command、exec.CommandContext、Cmd.Output、 Cmd.CombinedOutput、Cmd.Run、Cmd.Start。
exec.Command
exec.Command 不通过 Shell 解释参数。
package main
import (
"fmt"
"os/exec"
)
func main() {
// 不通过 Shell 解释参数。
cmd := exec.Command("go", "version")
// [go version]
fmt.Println(cmd.Args)
}exec.CommandContext
exec.CommandContext 创建绑定上下文的命令,上下文结束时终止进程。
package main
import (
"context"
"fmt"
"os/exec"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// 超时会终止子进程。
cmd := exec.CommandContext(ctx, "go", "version")
// [go version]
fmt.Println(cmd.Args)
}Cmd.Output
Cmd.Output 仅返回标准输出。
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("go", "version")
// Output 是 exec.Cmd 的方法,仅返回标准输出。
output, err := cmd.Output()
if err != nil {
panic(err)
}
// 输出示例:go version go1.25.0 windows/amd64(实际值取决于 Go 版本与运行平台)
fmt.Print(string(output))
}Cmd.CombinedOutput
Cmd.CombinedOutput 返回合并后的标准输出与标准错误。
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("go", "version")
// CombinedOutput 是 os/exec.Cmd 的方法,返回合并后的标准输出与标准错误。
output, err := cmd.CombinedOutput()
if err != nil {
panic(err)
}
// 输出示例:go version go1.25.0 windows/amd64(实际值取决于 Go 版本与运行平台)
fmt.Print(string(output))
}Cmd.Run
Cmd.Run 等待命令执行结束。
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("go", "version")
// Run 是 exec.Cmd 的方法,等待命令执行结束。
if err := cmd.Run(); err != nil {
panic(err)
}
// 执行成功
fmt.Println("执行成功")
}Cmd.Start
Cmd.Start 用于启动命令但不等待;随后必须调用 Wait。
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("go", "version")
// Start 是 os/exec.Cmd 的方法,用于启动命令但不等待;随后必须调用 Wait。
if err := cmd.Start(); err != nil {
panic(err)
}
if err := cmd.Wait(); err != nil {
panic(err)
}
// 执行成功
fmt.Println("执行成功")
}以上示例要求 go 命令位于 PATH 中。
os/user:查询系统用户账户
常用 API:user.Current、user.Lookup、user.LookupId、user.LookupGroup、 User.GroupIds。
user.Current
user.Current 查询当前用户。
package main
import (
"fmt"
"os/user"
)
func main() {
// 查询当前用户。
current, err := user.Current()
if err != nil {
panic(err)
}
// 输出示例:alice(实际值取决于当前系统用户)
fmt.Println(current.Username)
}user.Lookup
user.Lookup 按用户名查询。
package main
import (
"fmt"
"os/user"
)
func main() {
current, err := user.Current()
if err != nil {
panic(err)
}
// 按用户名查询。
found, err := user.Lookup(current.Username)
if err != nil {
panic(err)
}
// 输出示例:1000(实际值取决于当前系统用户)
fmt.Println(found.Uid)
}user.LookupId
user.LookupId 按用户 ID 查询。
package main
import (
"fmt"
"os/user"
)
func main() {
current, err := user.Current()
if err != nil {
panic(err)
}
// 按用户 ID 查询。
found, err := user.LookupId(current.Uid)
if err != nil {
panic(err)
}
// 输出示例:alice(实际值取决于当前系统用户)
fmt.Println(found.Username)
}user.LookupGroup
user.LookupGroup 按组名查询。
package main
import (
"fmt"
"os/user"
)
func main() {
current, err := user.Current()
if err != nil {
panic(err)
}
group, err := user.LookupGroupId(current.Gid)
if err != nil {
panic(err)
}
// 按组名查询。
found, err := user.LookupGroup(group.Name)
if err != nil {
panic(err)
}
// 输出示例:1000(实际值取决于当前系统用户组)
fmt.Println(found.Gid)
}User.GroupIds
User.GroupIds 返回该用户所属全部组的标识符列表。
package main
import (
"fmt"
"os/user"
)
func main() {
current, err := user.Current()
if err != nil {
panic(err)
}
// GroupIds 是 os/user.User 的方法。
groups, err := current.GroupIds()
if err != nil {
panic(err)
}
// 输出示例:[1000 27](实际值及顺序取决于当前系统用户组)
fmt.Println(groups)
}部分交叉编译、静态链接或受限容器环境可能无法查询完整账户数据库。
bufio:缓冲输入输出与扫描
常用 API:bufio.NewReader、Reader.ReadString、bufio.NewWriter、 Writer.Flush、bufio.NewScanner、Scanner.Split、Scanner.Buffer。
bufio.NewReader
bufio.NewReader 为底层 Reader 创建带缓冲的读取器。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
// 。
reader := bufio.NewReader(strings.NewReader("Go"))
// 0
fmt.Println(reader.Buffered())
}Reader.ReadString
Reader.ReadString 读取到分隔符。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
reader := bufio.NewReader(strings.NewReader("first\nsecond"))
// ReadString 是 bufio.Reader 的方法,读取到分隔符。
line, err := reader.ReadString('\n')
if err != nil {
panic(err)
}
// first
fmt.Print(line)
}bufio.NewWriter
bufio.NewWriter 创建带缓冲的 Writer。
package main
import (
"bufio"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
// 创建带缓冲的 Writer。
writer := bufio.NewWriter(&dst)
_, _ = writer.WriteString("Go")
_ = writer.Flush()
// Go
fmt.Println(dst.String())
}Writer.Flush
Writer.Flush 把缓冲数据写入底层 Writer。
package main
import (
"bufio"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
writer := bufio.NewWriter(&dst)
_, _ = writer.WriteString("Go")
// Flush 是 bufio.Writer 的方法,把缓冲数据写入底层 Writer。
if err := writer.Flush(); err != nil {
panic(err)
}
// Go
fmt.Println(dst.String())
}bufio.NewScanner
bufio.NewScanner 默认按行扫描。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
// 默认按行扫描。
scanner := bufio.NewScanner(strings.NewReader("first\nsecond"))
// first
// second
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
panic(err)
}
}Scanner.Split
Scanner.Split 设置扫描器划分输入 token 时使用的拆分函数。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
scanner := bufio.NewScanner(strings.NewReader("Go Rust"))
// Split 是 bufio.Scanner 的方法。
scanner.Split(bufio.ScanWords)
// Go
// Rust
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}Scanner.Buffer
Scanner.Buffer 用于调整最大 token 大小。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
scanner := bufio.NewScanner(strings.NewReader(strings.Repeat("x", 100000)))
// Buffer 是 bufio.Scanner 的方法,用于调整最大 token 大小。
scanner.Buffer(make([]byte, 1024), 200000)
// true 100000
fmt.Println(scanner.Scan(), len(scanner.Text()))
}path:处理斜杠分隔路径
常用 API:path.Join、path.Base、path.Dir、path.Ext、path.Clean、 path.Match。
path.Join
path.Join 连接并清理斜杠分隔的路径片段。
package main
import (
"fmt"
"path"
)
func main() {
// 始终使用正斜杠。
fmt.Println(path.Join("/api", "users", "../posts"))
}path.Base
path.Base 返回路径最后一个元素。
package main
import (
"fmt"
"path"
)
func main() {
// 返回路径最后一个元素。
fmt.Println(path.Base("/a/b/file.txt"))
}path.Dir
path.Dir 返回除最后元素外的路径。
package main
import (
"fmt"
"path"
)
func main() {
// 返回除最后元素外的路径。
fmt.Println(path.Dir("/a/b/file.txt"))
}path.Ext
path.Ext 返回最后元素的扩展名。
package main
import (
"fmt"
"path"
)
func main() {
// 返回最后元素的扩展名。
fmt.Println(path.Ext("archive.tar.gz"))
}path.Clean
path.Clean 按词法规则清理路径。
package main
import (
"fmt"
"path"
)
func main() {
// 按词法规则清理路径。
fmt.Println(path.Clean("/a//b/../c"))
}path.Match
path.Match 按 Shell 风格模式匹配。
package main
import (
"fmt"
"path"
)
func main() {
// 按 Shell 风格模式匹配。
matched, err := path.Match("*.go", "main.go")
if err != nil {
panic(err)
}
fmt.Println(matched)
}path 适用于 URL 和逻辑路径;操作本机文件路径应使用 path/filepath。
path/filepath:处理本机文件路径
常用 API:filepath.Join、filepath.Abs、filepath.Base、filepath.Ext、 filepath.Glob、filepath.WalkDir、filepath.Rel。
filepath.Join
filepath.Join 用当前系统分隔符连接并清理路径片段。
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 使用当前系统分隔符。
fmt.Println(filepath.Join("logs", "2026", "app.log"))
}filepath.Abs
filepath.Abs 返回绝对路径。
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 返回绝对路径。
value, err := filepath.Abs(".")
if err != nil {
panic(err)
}
fmt.Println(value)
}filepath.Base
filepath.Base 按当前系统规则返回路径最后一个元素。
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 遵循当前系统路径规则。
fmt.Println(filepath.Base(filepath.Join("a", "file.txt")))
}filepath.Ext
filepath.Ext 返回扩展名。
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 返回扩展名。
fmt.Println(filepath.Ext("archive.tar.gz"))
}filepath.Glob
filepath.Glob 匹配本机文件路径。
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 匹配本机文件路径。
matches, err := filepath.Glob("*.go")
if err != nil {
panic(err)
}
fmt.Println(matches)
}filepath.WalkDir
filepath.WalkDir 遍历指定根目录,并对每个条目调用回调函数。
package main
import (
"fmt"
"io/fs"
"path/filepath"
)
func main() {
// 此处仅访问根目录后跳过子目录。
err := filepath.WalkDir(".", func(path string, entry fs.DirEntry, err error) error {
fmt.Println(path)
if err != nil {
return err
}
if path == "." {
return fs.SkipDir
}
return nil
})
if err != nil {
panic(err)
}
}filepath.Rel
filepath.Rel 计算词法相对路径。
package main
import (
"fmt"
"path/filepath"
)
func main() {
// 计算词法相对路径。
value, err := filepath.Rel(filepath.Join("a", "b"), filepath.Join("a", "c"))
if err != nil {
panic(err)
}
fmt.Println(value)
}math:基础数学计算
常用 API:math.Abs、math.Max、math.Min、math.Pow、math.Sqrt、 math.Round、math.Sin、math.Log。
math.Abs
math.Abs 返回 float64 的绝对值。
package main
import (
"fmt"
"math"
)
func main() {
// 返回 float64 的绝对值。
fmt.Println(math.Abs(-3.5))
}math.Max
math.Max 返回较大的 float64。
package main
import (
"fmt"
"math"
)
func main() {
// 返回较大的 float64。
fmt.Println(math.Max(10, 20))
}math.Min
math.Min 返回较小的 float64。
package main
import (
"fmt"
"math"
)
func main() {
// 返回较小的 float64。
fmt.Println(math.Min(10, 20))
}math.Pow
math.Pow 计算底数的指定次幂并返回浮点结果。
package main
import (
"fmt"
"math"
)
func main() {
// Pow 与 Pi。
fmt.Println(math.Pi * math.Pow(3, 2))
}math.Sqrt
math.Sqrt 计算平方根。
package main
import (
"fmt"
"math"
)
func main() {
// 计算平方根。
fmt.Println(math.Sqrt(16))
}math.Round
math.Round 将浮点数舍入到最接近的整数值。
package main
import (
"fmt"
"math"
)
func main() {
// 四舍五入到最近整数。
fmt.Println(math.Round(3.6))
}math.Sin
math.Sin 计算以弧度表示的角度正弦值。
package main
import (
"fmt"
"math"
)
func main() {
// Sin 和 Pi,参数单位为弧度。
fmt.Println(math.Sin(math.Pi / 2))
}math.Log
math.Log 与 E 均计算自然对数。
package main
import (
"fmt"
"math"
)
func main() {
// Log 与 E,计算自然对数。
fmt.Println(math.Log(math.E))
}math/bits:整数位运算
常用 API:bits.OnesCount、bits.Len、bits.LeadingZeros、 bits.TrailingZeros、bits.RotateLeft8、bits.Reverse8。
bits.OnesCount
bits.OnesCount 统计 uint 中置位的位数。
package main
import (
"fmt"
"math/bits"
)
func main() {
// 统计 uint 中置位的位数。
fmt.Println(bits.OnesCount(0b10110100))
}bits.Len
bits.Len 返回表示值所需的最少位数。
package main
import (
"fmt"
"math/bits"
)
func main() {
// 返回表示值所需的最少位数。
fmt.Println(bits.Len(255))
}bits.LeadingZeros
bits.LeadingZeros 返回整数二进制表示前端连续零位的数量。
package main
import (
"fmt"
"math/bits"
)
func main() {
// 结果取决于 uint 字宽。
fmt.Println(bits.LeadingZeros(1))
}bits.TrailingZeros
bits.TrailingZeros 统计尾部零位。
package main
import (
"fmt"
"math/bits"
)
func main() {
// 统计尾部零位。
fmt.Println(bits.TrailingZeros(0b1000))
}bits.RotateLeft8
bits.RotateLeft8 将 8 位整数循环左移指定的位数。
package main
import (
"fmt"
"math/bits"
)
func main() {
// 循环左移 8 位整数。
fmt.Printf("%08b\n", bits.RotateLeft8(0b10000001, 1))
}bits.Reverse8
bits.Reverse8 反转 8 个二进制位。
package main
import (
"fmt"
"math/bits"
)
func main() {
// 反转 8 个二进制位。
fmt.Printf("%08b\n", bits.Reverse8(0b00001101))
}math/cmplx:复数数学计算
常用 API:cmplx.Abs、cmplx.Phase、cmplx.Conj、cmplx.Sqrt、 cmplx.Polar、cmplx.Rect。
cmplx.Abs
cmplx.Abs 返回复数的模。
package main
import (
"fmt"
"math/cmplx"
)
func main() {
// 返回复数的模。
fmt.Println(cmplx.Abs(complex(3, 4)))
}cmplx.Phase
cmplx.Phase 返回复数辐角。
package main
import (
"fmt"
"math/cmplx"
)
func main() {
// 返回复数辐角。
fmt.Println(cmplx.Phase(complex(0, 1)))
}cmplx.Conj
cmplx.Conj 返回共轭复数。
package main
import (
"fmt"
"math/cmplx"
)
func main() {
// 返回共轭复数。
fmt.Println(cmplx.Conj(complex(3, 4)))
}cmplx.Sqrt
cmplx.Sqrt 计算复数平方根。
package main
import (
"fmt"
"math/cmplx"
)
func main() {
// 计算复数平方根。
fmt.Println(cmplx.Sqrt(complex(-1, 0)))
}cmplx.Polar
cmplx.Polar 返回模和辐角。
package main
import (
"fmt"
"math/cmplx"
)
func main() {
// 返回模和辐角。
radius, theta := cmplx.Polar(complex(3, 4))
fmt.Println(radius, theta)
}cmplx.Rect
cmplx.Rect 将极坐标转换为复数。
package main
import (
"fmt"
"math/cmplx"
)
func main() {
// 将极坐标转换为复数。
fmt.Println(cmplx.Rect(2, 0))
}math/rand:生成伪随机数据
常用 API:rand.New、Rand.Intn、Rand.Float64、Rand.Shuffle、 Rand.Perm。
rand.New
rand.New 用指定随机源创建独立的伪随机数生成器。
package main
import (
"fmt"
"math/rand"
)
func main() {
// New 与 NewSource。
random := rand.New(rand.NewSource(42))
fmt.Println(random)
}Rand.Intn
Rand.Intn 返回 [0,n) 的整数。
package main
import (
"fmt"
"math/rand"
)
func main() {
random := rand.New(rand.NewSource(42))
// Intn 是 math/rand.Rand 的方法,返回 [0,n) 的整数。
fmt.Println(random.Intn(100))
}Rand.Float64
Rand.Float64 返回 [0,1) 的数。
package main
import (
"fmt"
"math/rand"
)
func main() {
random := rand.New(rand.NewSource(42))
// Float64 是 math/rand.Rand 的方法,返回 [0,1) 的数。
fmt.Println(random.Float64())
}Rand.Shuffle
Rand.Shuffle 原地打乱元素。
package main
import (
"fmt"
"math/rand"
)
func main() {
random := rand.New(rand.NewSource(42))
values := []string{"a", "b", "c"}
// Shuffle 是 math/rand.Rand 的方法,原地打乱元素。
random.Shuffle(len(values), func(i, j int) { values[i], values[j] = values[j], values[i] })
fmt.Println(values)
}Rand.Perm
Rand.Perm 返回 [0,n) 的随机排列。
package main
import (
"fmt"
"math/rand"
)
func main() {
random := rand.New(rand.NewSource(42))
// Perm 是 math/rand.Rand 的方法,返回 [0,n) 的随机排列。
fmt.Println(random.Perm(5))
}math/rand 不适合密码、令牌或密钥;安全场景应使用 crypto/rand。
math/big:任意精度数值计算
常用 API:big.NewInt、Int.SetString、Int.Add、Int.Mul、 Rat.SetFrac、Rat.FloatString、big.NewFloat。
big.NewInt
big.NewInt 创建任意精度整数。
package main
import (
"fmt"
"math/big"
)
func main() {
// 创建任意精度整数。
fmt.Println(big.NewInt(123456789))
}Int.SetString
Int.SetString 第二个返回值表示解析成功。
package main
import (
"fmt"
"math/big"
)
func main() {
// SetString 是 math/big.Int 的方法,第二个返回值表示解析成功。
value, ok := new(big.Int).SetString("12345678901234567890", 10)
fmt.Println(value, ok)
}Int.Add
Int.Add 结果写入接收者。
package main
import (
"fmt"
"math/big"
)
func main() {
// Add 是 math/big.Int 的方法,结果写入接收者。
result := new(big.Int).Add(big.NewInt(10), big.NewInt(20))
fmt.Println(result)
}Int.Mul
Int.Mul 结果写入接收者。
package main
import (
"fmt"
"math/big"
)
func main() {
// Mul 是 math/big.Int 的方法,结果写入接收者。
result := new(big.Int).Mul(big.NewInt(12), big.NewInt(34))
fmt.Println(result)
}Rat.SetFrac
Rat.SetFrac 创建精确分数。
package main
import (
"fmt"
"math/big"
)
func main() {
// SetFrac 是 math/big.Rat 的方法,创建精确分数。
value := new(big.Rat).SetFrac(big.NewInt(1), big.NewInt(3))
fmt.Println(value)
}Rat.FloatString
Rat.FloatString 按指定小数位舍入。
package main
import (
"fmt"
"math/big"
)
func main() {
value := big.NewRat(1, 3)
// FloatString 是 math/big.Rat 的方法,按指定小数位舍入。
fmt.Println(value.FloatString(5))
}big.NewFloat
big.NewFloat 创建任意精度浮点数。
package main
import (
"fmt"
"math/big"
)
func main() {
// 创建任意精度浮点数。
value := big.NewFloat(3.1415926)
fmt.Println(value.Text('f', 4))
}多数 math/big 运算把结果写入接收者,需避免意外覆盖仍要使用的值。
container/heap:维护堆数据结构
常用 API:heap.Init、heap.Push、heap.Pop、heap.Fix、heap.Remove。 每个示例都重复最小堆定义,以保证代码块可独立编译。
heap.Init
heap.Init 原地调整集合元素,使其满足堆的顺序约束。
package main
import (
"container/heap"
"fmt"
)
type intHeap []int
func (h intHeap) Len() int { return len(h) }
func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h intHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *intHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *intHeap) Pop() any {
old := *h
value := old[len(old)-1]
*h = old[:len(old)-1]
return value
}
func main() {
values := &intHeap{5, 1, 3}
// 建立堆不变量。
heap.Init(values)
fmt.Println((*values)[0])
}heap.Push
heap.Push 向堆中加入元素,并重新维护堆的顺序约束。
package main
import (
"container/heap"
"fmt"
)
type intHeap []int
func (h intHeap) Len() int { return len(h) }
func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h intHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *intHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *intHeap) Pop() any {
old := *h
value := old[len(old)-1]
*h = old[:len(old)-1]
return value
}
func main() {
values := &intHeap{2, 5}
heap.Init(values)
// 。
heap.Push(values, 1)
fmt.Println((*values)[0])
}heap.Pop
heap.Pop 移除最小元素。
package main
import (
"container/heap"
"fmt"
)
type intHeap []int
func (h intHeap) Len() int { return len(h) }
func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h intHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *intHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *intHeap) Pop() any {
old := *h
value := old[len(old)-1]
*h = old[:len(old)-1]
return value
}
func main() {
values := &intHeap{3, 1, 2}
heap.Init(values)
// 移除最小元素。
fmt.Println(heap.Pop(values).(int))
}heap.Fix
heap.Fix 元素改变后恢复堆不变量。
package main
import (
"container/heap"
"fmt"
)
type intHeap []int
func (h intHeap) Len() int { return len(h) }
func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h intHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *intHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *intHeap) Pop() any {
old := *h
value := old[len(old)-1]
*h = old[:len(old)-1]
return value
}
func main() {
values := &intHeap{1, 5, 3}
heap.Init(values)
(*values)[1] = 0
// 元素改变后恢复堆不变量。
heap.Fix(values, 1)
fmt.Println((*values)[0])
}heap.Remove
heap.Remove 删除指定索引的元素。
package main
import (
"container/heap"
"fmt"
)
type intHeap []int
func (h intHeap) Len() int { return len(h) }
func (h intHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h intHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *intHeap) Push(x any) { *h = append(*h, x.(int)) }
func (h *intHeap) Pop() any {
old := *h
value := old[len(old)-1]
*h = old[:len(old)-1]
return value
}
func main() {
values := &intHeap{1, 3, 2}
heap.Init(values)
// 删除指定索引的元素。
fmt.Println(heap.Remove(values, 1))
}container/list:操作双向链表
常用 API:list.New、List.PushFront、List.PushBack、List.InsertAfter、 List.Remove、List.Front。
list.New
list.New 创建双向链表。
package main
import (
"container/list"
"fmt"
)
func main() {
// 创建双向链表。
values := list.New()
fmt.Println(values.Len())
}List.PushFront
List.PushFront 把新元素插入双向链表头部并返回该元素。
package main
import (
"container/list"
"fmt"
)
func main() {
values := list.New()
// PushFront 是 container/list.List 的方法。
values.PushFront("first")
fmt.Println(values.Front().Value)
}List.PushBack
List.PushBack 把新元素插入双向链表尾部并返回该元素。
package main
import (
"container/list"
"fmt"
)
func main() {
values := list.New()
// PushBack 是 container/list.List 的方法。
values.PushBack("last")
fmt.Println(values.Back().Value)
}List.InsertAfter
List.InsertAfter 在指定链表元素之后插入新值并返回新元素。
package main
import (
"container/list"
"fmt"
)
func main() {
values := list.New()
first := values.PushBack("a")
// InsertAfter 是 container/list.List 的方法。
inserted := values.InsertAfter("b", first)
fmt.Println(inserted.Value)
}List.Remove
List.Remove 从链表移除指定元素,并返回其保存的值。
package main
import (
"container/list"
"fmt"
)
func main() {
values := list.New()
element := values.PushBack("a")
// Remove 是 container/list.List 的方法。
fmt.Println(values.Remove(element), values.Len())
}List.Front
List.Front 返回链表首元素;链表为空时返回 nil。
package main
import (
"container/list"
"fmt"
)
func main() {
values := list.New()
values.PushBack("a")
values.PushBack("b")
// Front 和 Element.Next 均由 container/list 包提供。
for element := values.Front(); element != nil; element = element.Next() {
fmt.Println(element.Value)
}
}container/ring:操作循环链表
常用 API:ring.New、Ring.Next、Ring.Move、Ring.Do、Ring.Link、 Ring.Unlink。
ring.New
ring.New 创建固定长度循环链表。
package main
import (
"container/ring"
"fmt"
)
func main() {
// 创建固定长度循环链表。
values := ring.New(3)
fmt.Println(values.Len())
}Ring.Next
Ring.Next 返回循环链表中的下一个元素。
package main
import (
"container/ring"
"fmt"
)
func main() {
values := ring.New(2)
values.Value = "A"
values.Next().Value = "B"
// Next 是 container/ring.Ring 的方法。
fmt.Println(values.Next().Value)
}Ring.Move
Ring.Move 按步数移动。
package main
import (
"container/ring"
"fmt"
)
func main() {
values := ring.New(2)
values.Value = "A"
values.Next().Value = "B"
// Move 是 container/ring.Ring 的方法,按步数移动。
fmt.Println(values.Move(1).Value)
}Ring.Do
Ring.Do 对每个元素调用函数。
package main
import (
"container/ring"
"fmt"
)
func main() {
values := ring.New(2)
values.Value = "A"
values.Next().Value = "B"
// Do 是 container/ring.Ring 的方法,对每个元素调用函数。
values.Do(func(value any) { fmt.Println(value) })
}Ring.Link
Ring.Link 连接两个环。
package main
import (
"container/ring"
"fmt"
)
func main() {
left := ring.New(1)
right := ring.New(2)
// Link 是 container/ring.Ring 的方法,连接两个环。
left.Link(right)
fmt.Println(left.Len())
}Ring.Unlink
Ring.Unlink 移除后续 n 个元素。
package main
import (
"container/ring"
"fmt"
)
func main() {
values := ring.New(3)
// Unlink 是 container/ring.Ring 的方法,移除后续 n 个元素。
removed := values.Unlink(1)
fmt.Println(values.Len(), removed.Len())
}archive/zip:读写 ZIP 归档
常用 API:zip.NewWriter、Writer.Create、Writer.Close、zip.OpenReader、 File.Open。
zip.NewWriter
zip.NewWriter 基于目标 Writer 创建 ZIP 归档写入器。
package main
import (
"archive/zip"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
// 。
writer := zip.NewWriter(&dst)
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}Writer.Create
Writer.Create 在 ZIP 归档中创建指定名称的文件条目。
package main
import (
"archive/zip"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
writer := zip.NewWriter(&dst)
// Create 是 archive/zip.Writer 的方法。
entry, err := writer.Create("hello.txt")
if err != nil {
panic(err)
}
_, _ = entry.Write([]byte("Hello ZIP"))
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}Writer.Close
Writer.Close 必须调用以写完目录信息。
package main
import (
"archive/zip"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
writer := zip.NewWriter(&dst)
// Close 是 archive/zip.Writer 的方法,必须调用以写完目录信息。
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println("已关闭")
}zip.OpenReader
zip.OpenReader 打开指定 ZIP 文件并返回归档读取器。
package main
import (
"archive/zip"
"fmt"
)
func main() {
// 要求当前目录已有 demo.zip。
reader, err := zip.OpenReader("demo.zip")
if err != nil {
panic(err)
}
defer reader.Close()
fmt.Println(len(reader.File))
}File.Open
File.Open 打开 ZIP 文件条目并返回其内容读取流。
package main
import (
"archive/zip"
"fmt"
"io"
)
func main() {
reader, err := zip.OpenReader("demo.zip")
if err != nil {
panic(err)
}
defer reader.Close()
if len(reader.File) == 0 {
return
}
// Open 是 archive/zip.File 的方法,要求 demo.zip 至少有一个条目。
file, err := reader.File[0].Open()
if err != nil {
panic(err)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}后两个读取示例依赖当前目录中的 demo.zip;这是归档读取 API 必需的外部输入。
archive/tar:读写 TAR 归档
常用 API:tar.NewWriter、Writer.WriteHeader、Writer.Write、 tar.NewReader、Reader.Next。
tar.NewWriter
tar.NewWriter 基于目标 Writer 创建 TAR 归档写入器。
package main
import (
"archive/tar"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
// 。
writer := tar.NewWriter(&dst)
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}Writer.WriteHeader
Writer.WriteHeader 向 TAR 归档写入下一个文件的头部元数据。
package main
import (
"archive/tar"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
writer := tar.NewWriter(&dst)
// WriteHeader 是 archive/tar.Writer 的方法。
err := writer.WriteHeader(&tar.Header{Name: "hello.txt", Mode: 0o600, Size: 0})
if err != nil {
panic(err)
}
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}Writer.Write
Writer.Write 把文件内容写入当前 TAR 归档条目。
package main
import (
"archive/tar"
"bytes"
"fmt"
)
func main() {
var dst bytes.Buffer
writer := tar.NewWriter(&dst)
data := []byte("Hello TAR")
if err := writer.WriteHeader(&tar.Header{Name: "hello.txt", Mode: 0o600, Size: int64(len(data))}); err != nil {
panic(err)
}
// Write 是 archive/tar.Writer 的方法。
if _, err := writer.Write(data); err != nil {
panic(err)
}
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}tar.NewReader
tar.NewReader 从顺序数据流读取 TAR。
package main
import (
"archive/tar"
"bytes"
"fmt"
)
func main() {
// 从顺序数据流读取 TAR。
reader := tar.NewReader(bytes.NewReader(nil))
fmt.Println(reader != nil)
}Reader.Next
Reader.Next 空归档返回 io.EOF。
package main
import (
"archive/tar"
"bytes"
"errors"
"fmt"
"io"
)
func main() {
reader := tar.NewReader(bytes.NewReader(nil))
// Next 是 archive/tar.Reader 的方法,空归档返回 io.EOF。
_, err := reader.Next()
fmt.Println(errors.Is(err, io.EOF))
}TAR 只负责归档;.tar.gz 还需配合 compress/gzip。
compress:数据压缩与解压
常用 API:gzip.NewWriter、gzip.NewReader、zlib.NewWriter、 flate.NewWriter、bzip2.NewReader。compress 本身是目录,实际应导入具体子包。
gzip.NewWriter
gzip.NewWriter 创建向目标流写入 GZIP 压缩数据的写入器。
package main
import (
"bytes"
"compress/gzip"
"fmt"
)
func main() {
var dst bytes.Buffer
// 。
writer := gzip.NewWriter(&dst)
_, _ = writer.Write([]byte("Hello compression"))
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}gzip.NewReader
gzip.NewReader 读取 GZIP 数据头并返回解压读取器。
package main
import (
"bytes"
"compress/gzip"
"fmt"
"io"
)
func main() {
var compressed bytes.Buffer
writer := gzip.NewWriter(&compressed)
_, _ = writer.Write([]byte("Go"))
_ = writer.Close()
// 。
reader, err := gzip.NewReader(&compressed)
if err != nil {
panic(err)
}
defer reader.Close()
data, err := io.ReadAll(reader)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}zlib.NewWriter
zlib.NewWriter 创建向目标流写入 zlib 压缩数据的写入器。
package main
import (
"bytes"
"compress/zlib"
"fmt"
)
func main() {
var dst bytes.Buffer
// 。
writer := zlib.NewWriter(&dst)
_, _ = writer.Write([]byte("Go"))
if err := writer.Close(); err != nil {
panic(err)
}
fmt.Println(dst.Len())
}flate.NewWriter
flate.NewWriter 按指定压缩级别创建 DEFLATE 写入器。
package main
import (
"bytes"
"compress/flate"
"fmt"
)
func main() {
var dst bytes.Buffer
// 。
writer, err := flate.NewWriter(&dst, flate.BestSpeed)
if err != nil {
panic(err)
}
_, _ = writer.Write([]byte("Go"))
_ = writer.Close()
fmt.Println(dst.Len())
}bzip2.NewReader
bzip2.NewReader 标准库只提供 bzip2 解压。
package main
import (
"bytes"
"compress/bzip2"
"fmt"
)
func main() {
// 标准库只提供 bzip2 解压。
reader := bzip2.NewReader(bytes.NewReader(nil))
fmt.Println(reader != nil)
}最后一个示例只演示构造 Reader;实际读取需要合法的 bzip2 数据。
database/sql:访问关系型数据库
常用 API:sql.Open、DB.PingContext、DB.ExecContext、 DB.QueryContext、DB.QueryRowContext、Rows.Scan、DB.BeginTx、 sql.Named。
database/sql 不包含驱动。下列连接与查询示例可以编译,但必须把驱动名、DSN、 SQL 占位符和表结构替换为项目实际配置后才能成功运行。
sql.Open
sql.Open 按驱动名和数据源创建数据库句柄,但不会立即连接。
package main
import (
"database/sql"
"fmt"
)
func main() {
// unknown 未注册,因此示例会打印预期错误。
db, err := sql.Open("unknown", "")
fmt.Println(db, err)
}DB.PingContext
DB.PingContext 在上下文约束下验证数据库连接是否可用。
package main
import (
"context"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("unknown", "")
if err != nil {
// 未注册驱动时会到达这里。
fmt.Println(err)
return
}
defer db.Close()
// PingContext 是 database/sql.DB 的方法,用于验证数据库连接是否可用。
fmt.Println(db.PingContext(context.Background()))
}DB.ExecContext
DB.ExecContext 用于执行不返回结果行的 SQL。
package main
import (
"context"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("unknown", "")
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
// ExecContext 是 database/sql.DB 的方法,用于执行不返回结果行的 SQL。
_, err = db.ExecContext(context.Background(), "DELETE FROM users WHERE id = ?", 1)
fmt.Println(err)
}DB.QueryContext
DB.QueryContext 用于执行返回多行结果的 SQL。
package main
import (
"context"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("unknown", "")
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
// QueryContext 是 database/sql.DB 的方法,用于执行返回多行结果的 SQL。
_, err = db.QueryContext(context.Background(), "SELECT id FROM users")
fmt.Println(err)
}DB.QueryRowContext
DB.QueryRowContext 用于查询单行,错误在 Scan 时报告。
package main
import (
"context"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("unknown", "")
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
var name string
// QueryRowContext 是 database/sql.DB 的方法,用于查询单行,错误在 Scan 时报告。
err = db.QueryRowContext(context.Background(), "SELECT name FROM users WHERE id = ?", 1).Scan(&name)
fmt.Println(name, err)
}Rows.Scan
Rows.Scan 用于把当前行的列复制到目标变量。
package main
import (
"context"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("unknown", "")
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
rows, err := db.QueryContext(context.Background(), "SELECT id FROM users")
if err != nil {
fmt.Println(err)
return
}
defer rows.Close()
var id int
// Scan 是 database/sql.Rows 的方法,用于把当前行的列复制到目标变量。
if rows.Next() {
err = rows.Scan(&id)
}
fmt.Println(id, err)
}DB.BeginTx
DB.BeginTx 用于按上下文与选项启动事务。
package main
import (
"context"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("unknown", "")
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
// BeginTx 是 database/sql.DB 的方法,用于按上下文与选项启动事务。
_, err = db.BeginTx(context.Background(), nil)
fmt.Println(err)
}sql.Named
sql.Named 可独立创建命名参数。
package main
import (
"database/sql"
"fmt"
)
func main() {
// 可独立创建命名参数。
argument := sql.Named("user_id", 42)
fmt.Println(argument.Name, argument.Value)
}应始终把参数单独传入 SQL API,不要拼接不可信输入。占位符语法由驱动决定。
encoding:数据编码与序列化
常用 API:json.Marshal、json.Unmarshal、json.NewEncoder、 xml.Marshal、base64.StdEncoding.EncodeToString、binary.Write、 hex.EncodeToString。
json.Marshal
json.Marshal 将 Go 值编码为 JSON 字节数据。
package main
import (
"encoding/json"
"fmt"
)
func main() {
value := struct {
Name string `json:"name"`
}{Name: "Go"}
// 。
data, err := json.Marshal(value)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}json.Unmarshal
json.Unmarshal 解析 JSON 字节并写入目标 Go 值。
package main
import (
"encoding/json"
"fmt"
)
func main() {
var value struct {
Name string `json:"name"`
}
// 。
if err := json.Unmarshal([]byte(`{"name":"Go"}`), &value); err != nil {
panic(err)
}
fmt.Println(value.Name)
}json.NewEncoder
json.NewEncoder 创建将 Go 值逐次编码到输出流的 JSON 编码器。
package main
import (
"encoding/json"
"os"
)
func main() {
encoder := json.NewEncoder(os.Stdout)
if err := encoder.Encode(map[string]string{"language": "Go"}); err != nil {
panic(err)
}
}xml.Marshal
xml.Marshal 将 Go 值编码为 XML 字节数据。
package main
import (
"encoding/xml"
"fmt"
)
func main() {
value := struct {
Name string `xml:"name"`
}{Name: "Go"}
// 。
data, err := xml.Marshal(value)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}base64.StdEncoding.EncodeToString
base64.StdEncoding.EncodeToString 按标准 Base64 编码字节并返回字符串。
package main
import (
"encoding/base64"
"fmt"
)
func main() {
// 。
fmt.Println(base64.StdEncoding.EncodeToString([]byte("hello")))
}binary.Write
binary.Write 按指定字节序把固定大小数据写入输出流。
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
func main() {
var dst bytes.Buffer
// 。
if err := binary.Write(&dst, binary.LittleEndian, uint32(42)); err != nil {
panic(err)
}
fmt.Println(dst.Bytes())
}hex.EncodeToString
hex.EncodeToString 把字节编码为小写十六进制字符串。
package main
import (
"encoding/hex"
"fmt"
)
func main() {
// 。
fmt.Println(hex.EncodeToString([]byte("Go")))
}自定义类型可实现 encoding.TextMarshaler、encoding.TextUnmarshaler 等接口。
crypto:密码学与安全通信
常用 API:rand.Read、sha256.Sum256、hmac.New、hmac.Equal、 aes.NewCipher、cipher.NewGCM、tls.Dial。
rand.Read
rand.Read 用密码学安全随机数据填满给定字节切片。
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
)
func main() {
token := make([]byte, 32)
// 。
if _, err := rand.Read(token); err != nil {
panic(err)
}
fmt.Println(hex.EncodeToString(token))
}sha256.Sum256
sha256.Sum256 计算输入字节的 SHA-256 摘要并返回固定数组。
package main
import (
"crypto/sha256"
"fmt"
)
func main() {
// 。
sum := sha256.Sum256([]byte("hello"))
fmt.Printf("%x\n", sum)
}hmac.New
hmac.New 使用哈希构造函数和密钥创建 HMAC 计算器。
package main
import (
"crypto/hmac"
"crypto/sha256"
"fmt"
)
func main() {
// 。
mac := hmac.New(sha256.New, []byte("secret"))
_, _ = mac.Write([]byte("message"))
fmt.Printf("%x\n", mac.Sum(nil))
}hmac.Equal
hmac.Equal 以恒定时间比较 MAC。
package main
import (
"crypto/hmac"
"fmt"
)
func main() {
left := []byte{1, 2, 3}
right := []byte{1, 2, 3}
// 以恒定时间比较 MAC。
fmt.Println(hmac.Equal(left, right))
}aes.NewCipher
aes.NewCipher 用 16、24 或 32 字节密钥创建 AES 分组密码。
package main
import (
"crypto/aes"
"fmt"
)
func main() {
key := []byte("0123456789abcdef")
// 密钥须为 16、24 或 32 字节。
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
fmt.Println(block.BlockSize())
}cipher.NewGCM
cipher.NewGCM 基于分组密码创建提供认证加密的 GCM 实例。
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
)
func main() {
block, err := aes.NewCipher([]byte("0123456789abcdef"))
if err != nil {
panic(err)
}
// 。
aead, err := cipher.NewGCM(block)
if err != nil {
panic(err)
}
fmt.Println(aead.NonceSize())
}tls.Dial
tls.Dial 需要网络和可验证的远端证书。
package main
import (
"crypto/tls"
"fmt"
)
func main() {
// 需要网络和可验证的远端证书。
conn, err := tls.Dial("tcp", "example.com:443", nil)
if err != nil {
panic(err)
}
defer conn.Close()
fmt.Println(conn.ConnectionState().Version)
}密码不能直接保存 SHA-256 摘要,应使用 bcrypt、scrypt 或 Argon2 等专用 密码哈希方案。不要自行设计密码协议。
go/ast:遍历与分析语法树
常用 API:ast.Inspect、ast.Walk、ast.Print、ast.IsExported。
ast.Inspect
ast.Inspect 深度优先遍历语法树,并对每个节点调用回调函数。
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
func main() {
file, err := parser.ParseFile(token.NewFileSet(), "demo.go", "package demo; func Add() {}", 0)
if err != nil {
panic(err)
}
// parser 与 token。
ast.Inspect(file, func(node ast.Node) bool {
if fn, ok := node.(*ast.FuncDecl); ok {
fmt.Println(fn.Name.Name)
}
return true
})
}ast.Walk
ast.Walk 使用给定访问器深度优先遍历语法树。
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
)
type visitor struct{}
func (visitor) Visit(node ast.Node) ast.Visitor {
if fn, ok := node.(*ast.FuncDecl); ok {
fmt.Println(fn.Name.Name)
}
return visitor{}
}
func main() {
file, err := parser.ParseFile(token.NewFileSet(), "demo.go", "package demo; func Add() {}", 0)
if err != nil {
panic(err)
}
// 需要实现 ast.Visitor。
ast.Walk(visitor{}, file)
}ast.Print
ast.Print 把 AST 结构写到标准输出。
package main
import (
"go/ast"
"go/parser"
"go/token"
)
func main() {
fileset := token.NewFileSet()
expr, err := parser.ParseExpr("a + b")
if err != nil {
panic(err)
}
// 把 AST 结构写到标准输出。
if err := ast.Print(fileset, expr); err != nil {
panic(err)
}
}ast.IsExported
ast.IsExported 判断标识符是否以大写 Unicode 字母开头。
package main
import (
"fmt"
"go/ast"
)
func main() {
// 判断标识符是否以大写 Unicode 字母开头。
fmt.Println(ast.IsExported("Println"))
}go/parser:解析 Go 源代码
常用 API:parser.ParseFile、parser.ParseDir、parser.ParseExpr、 parser.ParseExprFrom。
parser.ParseFile
parser.ParseFile 解析指定 Go 源文件并返回对应的语法树。
package main
import (
"fmt"
"go/parser"
"go/token"
)
func main() {
// 。
file, err := parser.ParseFile(token.NewFileSet(), "demo.go", "package demo; var Answer = 42", parser.ParseComments)
if err != nil {
panic(err)
}
fmt.Println(file.Name.Name)
}parser.ParseDir
parser.ParseDir 解析当前目录中的 Go 文件。
package main
import (
"fmt"
"go/parser"
"go/token"
)
func main() {
// 解析当前目录中的 Go 文件。
packages, err := parser.ParseDir(token.NewFileSet(), ".", nil, 0)
if err != nil {
panic(err)
}
fmt.Println(len(packages))
}ParseDir 的输出取决于当前目录中的 .go 文件。
parser.ParseExpr
parser.ParseExpr 把表达式解析为 ast.Expr。
package main
import (
"fmt"
"go/parser"
)
func main() {
// 把表达式解析为 ast.Expr。
expr, err := parser.ParseExpr("a + b*2")
if err != nil {
panic(err)
}
fmt.Printf("%T\n", expr)
}parser.ParseExprFrom
parser.ParseExprFrom 按文件位置解析表达式并返回语法树节点。
package main
import (
"fmt"
"go/parser"
"go/token"
)
func main() {
// 可指定文件名和 FileSet。
expr, err := parser.ParseExprFrom(token.NewFileSet(), "expr.go", "1 + 2", 0)
if err != nil {
panic(err)
}
fmt.Printf("%T\n", expr)
}go/importer:导入已编译 Go 包
常用 API:importer.Default、Importer.Import、importer.ForCompiler。
importer.Default
importer.Default 返回当前环境的默认导入器。
package main
import (
"fmt"
"go/importer"
)
func main() {
// 返回当前环境的默认导入器。
fmt.Printf("%T\n", importer.Default())
}Importer.Import
Importer.Import 按导入路径加载并返回已编译包的类型信息。
package main
import (
"fmt"
"go/importer"
)
func main() {
// Import 是 go/types.Importer 接口的方法,依赖本机 Go 工具链导出数据。
pkg, err := importer.Default().Import("fmt")
if err != nil {
panic(err)
}
fmt.Println(pkg.Name(), pkg.Path())
}importer.ForCompiler
importer.ForCompiler 为指定编译器导出格式创建包导入器。
package main
import (
"fmt"
"go/importer"
"go/token"
)
func main() {
// "gc" 使用 Go 编译器导出格式。
value := importer.ForCompiler(token.NewFileSet(), "gc", nil)
fmt.Printf("%T\n", value)
}默认导入器适合简单工具;需精确遵循模块、构建标签时通常使用 golang.org/x/tools/go/packages。Import 依赖本机工具链与可用的包导出数据。
go/format:格式化 Go 源代码
常用 API:format.Source、format.Node。
format.Source
format.Source 按 gofmt 规则格式化源码。
package main
import (
"fmt"
"go/format"
)
func main() {
source := []byte("package main\nfunc main(){println(\"hello\")}\n")
// 按 gofmt 规则格式化源码。
formatted, err := format.Source(source)
if err != nil {
panic(err)
}
fmt.Print(string(formatted))
}format.Node
format.Node 按 gofmt 规则格式化语法树并写入目标流。
package main
import (
"bytes"
"fmt"
"go/format"
"go/parser"
"go/token"
)
func main() {
fileset := token.NewFileSet()
file, err := parser.ParseFile(fileset, "demo.go", "package demo;var Answer=42", 0)
if err != nil {
panic(err)
}
var output bytes.Buffer
// AST 由 go/parser 解析。
if err := format.Node(&output, fileset, file); err != nil {
panic(err)
}
fmt.Println(output.String())
}arena:区域内存分配(实验包)
常用 API:arena.NewArena、arena.New、arena.MakeSlice、arena.Clone、 Arena.Free。
实验性警告: 原清单中的
areana是拼写错误,正确包名为arena。arena默认关闭,不属于稳定标准库 API;其行为和接口可能随 Go 版本改变或被移除。 只有使用支持 arena 实验的 Go 工具链,并设置GOEXPERIMENT=arenas时才能导入。
PowerShell 中可先设置实验环境变量,再运行任一示例:
$env:GOEXPERIMENT = "arenas"
go run .arena.NewArena
arena.NewArena 用于创建一块可批量释放的分配区域。
//go:build goexperiment.arenas
package main
import (
"arena"
"fmt"
)
func main() {
// NewArena 用于创建一块可批量释放的分配区域。
memory := arena.NewArena()
defer memory.Free()
fmt.Println(memory != nil)
}arena.New
arena.New 在指定 Arena 中分配值。
//go:build goexperiment.arenas
package main
import (
"arena"
"fmt"
)
func main() {
memory := arena.NewArena()
defer memory.Free()
// New 在指定 Arena 中分配值。
number := arena.New[int](memory)
*number = 42
fmt.Println(*number)
}arena.MakeSlice
arena.MakeSlice 用于在指定 Arena 中分配切片。
//go:build goexperiment.arenas
package main
import (
"arena"
"fmt"
)
func main() {
memory := arena.NewArena()
defer memory.Free()
// MakeSlice 在指定 Arena 中分配切片。
values := arena.MakeSlice[string](memory, 2, 10)
values[0], values[1] = "Go", "arena"
fmt.Println(values)
}arena.Clone
arena.Clone 把值复制回普通 Go 堆。
//go:build goexperiment.arenas
package main
import (
"arena"
"fmt"
)
func main() {
memory := arena.NewArena()
defer memory.Free()
values := arena.MakeSlice[string](memory, 1, 1)
values[0] = "Go"
// Clone 把值复制回普通 Go 堆。
cloned := arena.Clone(values)
fmt.Println(cloned)
}Arena.Free
Arena.Free 释放整块区域;之后不可访问区域内值。
//go:build goexperiment.arenas
package main
import (
"arena"
"fmt"
)
func main() {
memory := arena.NewArena()
// Free 是 arena.Arena 的方法,释放整块区域;之后不可访问区域内值。
memory.Free()
fmt.Println("Arena 已释放")
}常规程序应依赖垃圾回收器。遇到性能问题时,先使用 runtime/pprof 与基准测试 定位分配热点,再决定是否尝试实验能力。
runtime:查询与控制 Go 运行时
常用 API:runtime.Version、runtime.NumCPU、runtime.NumGoroutine、 runtime.GOMAXPROCS、runtime.GC、runtime.ReadMemStats、 runtime.Stack、runtime.Caller。
runtime.Version
runtime.Version 返回当前 Go 运行时的版本字符串。
package main
import (
"fmt"
"runtime"
)
func main() {
// Version、GOOS 和 GOARCH。
fmt.Println(runtime.Version(), runtime.GOOS, runtime.GOARCH)
}runtime.NumCPU
runtime.NumCPU 返回启动时可用的逻辑 CPU 数。
package main
import (
"fmt"
"runtime"
)
func main() {
// 返回启动时可用的逻辑 CPU 数。
fmt.Println(runtime.NumCPU())
}runtime.NumGoroutine
runtime.NumGoroutine 返回当前进程中存在的 goroutine 数量。
package main
import (
"fmt"
"runtime"
)
func main() {
// 。
fmt.Println(runtime.NumGoroutine())
}runtime.GOMAXPROCS
runtime.GOMAXPROCS 参数 0 只查询而不修改。
package main
import (
"fmt"
"runtime"
)
func main() {
// 参数 0 只查询而不修改。
fmt.Println(runtime.GOMAXPROCS(0))
}runtime.GC
runtime.GC 强制执行一次垃圾回收。
package main
import (
"fmt"
"runtime"
)
func main() {
// 强制执行一次垃圾回收。
runtime.GC()
fmt.Println("GC 完成")
}runtime.ReadMemStats
runtime.ReadMemStats 把当前内存分配与垃圾回收统计写入结构体。
package main
import (
"fmt"
"runtime"
)
func main() {
var stats runtime.MemStats
// ReadMemStats 与 MemStats。
runtime.ReadMemStats(&stats)
fmt.Println(stats.Alloc)
}runtime.Stack
runtime.Stack 第二个参数为 true 时包含所有 goroutine。
package main
import (
"fmt"
"runtime"
)
func main() {
buffer := make([]byte, 64<<10)
// 第二个参数为 true 时包含所有 goroutine。
length := runtime.Stack(buffer, true)
fmt.Println(string(buffer[:length]))
}runtime.Caller
runtime.Caller skip=0 表示当前调用位置。
package main
import (
"fmt"
"runtime"
)
func main() {
// skip=0 表示当前调用位置。
_, file, line, ok := runtime.Caller(0)
fmt.Println(file, line, ok)
}多数应用不需要直接调整运行时;应先通过基准测试和性能分析确认瓶颈。