Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Go runtime 包详解

概述

runtime 包包含与 Go 运行时系统交互的操作,例如控制 goroutine 的函数。它还包括 reflect 包使用的低级类型信息。

重要说明

  • 此包提供对 Go 运行时系统的低级访问
  • 包含垃圾回收、goroutine 调度、性能分析等功能
  • 大多数应用程序不需要直接使用此包
  • 许多函数应该在性能分析或调试场景中使用

包导入

import "runtime"

环境变量

runtime 包的行为可以通过以下环境变量控制:

GOGC

设置初始垃圾回收目标百分比。默认值为 100。设置为 off 禁用垃圾回收器。

GOMEMLIMIT

设置运行时的软内存限制(字节为单位)。

GODEBUG

控制运行时内的调试变量,常用选项:

  • cgocheck - cgo 指针检查
  • gccheckmark - 验证 GC 并发标记
  • gctrace - 输出 GC 信息
  • panicnil - 允许 panic(nil)

GOMAXPROCS

限制同时执行用户级 Go 代码的操作系统线程数。

GOTRACEBACK

控制 Go 程序失败时生成的输出量。

常量

Compiler

const Compiler = "gc"

说明:构建运行中二进制文件的编译器工具链名称。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Compiler:", runtime.Compiler)
}

运行结果

Compiler: gc

GOARCH

const GOARCH = "amd64"

说明:运行程序的目标架构(386、amd64、arm、s390x 等)。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Architecture:", runtime.GOARCH)
}

运行结果

Architecture: amd64

GOOS

const GOOS = "windows"

说明:运行程序的目标操作系统(darwin、freebsd、linux 等)。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Printf("OS: %s, Arch: %s\n", runtime.GOOS, runtime.GOARCH)
}

运行结果

OS: windows, Arch: amd64

变量

MemProfileRate

var MemProfileRate int = 512 * 1024

说明:控制内存分析中记录的内存分配比例。分析器旨在平均每 MemProfileRate 字节分配采样一次。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Default MemProfileRate:", runtime.MemProfileRate)
    
    // 记录所有分配
    runtime.MemProfileRate = 1
    
    // 关闭分析
    // runtime.MemProfileRate = 0
}

运行结果

Default MemProfileRate: 524288

函数详解(按 a-z 排序)

AddCleanup

func AddCleanup[T, S any](ptr *T, cleanup func(S), arg S) Cleanup

说明:将清理函数附加到 ptr。当 ptr 不再可达时,运行时将在单独的 goroutine 中调用 cleanup(arg)。

使用示例

package main

import (
    "fmt"
    "runtime"
    "time"
)

type Resource struct {
    id int
}

func main() {
    r := &Resource{id: 1}
    
    cleanup := runtime.AddCleanup(r, func(id int) {
        fmt.Printf("Cleaning up resource %d\n", id)
    }, r.id)
    
    fmt.Println("Resource created, cleanup registered")
    
    // 让 r 不可达
    r = nil
    
    // 强制 GC
    runtime.GC()
    time.Sleep(100 * time.Millisecond)
    
    // 停止清理
    cleanup.Stop()
    fmt.Println("Cleanup stopped")
}

运行结果

Resource created, cleanup registered
Cleaning up resource 1
Cleanup stopped

BlockProfile

func BlockProfile(p []BlockProfileRecord) (n int, ok bool)

说明:返回当前阻塞 profile 中的记录数。

使用示例

package main

import (
    "fmt"
    "runtime"
    "sync"
    "time"
)

func main() {
    runtime.SetBlockProfileRate(1)
    
    var mu sync.Mutex
    var wg sync.WaitGroup
    
    // 制造一些阻塞
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            mu.Lock()
            defer mu.Unlock()
            time.Sleep(10 * time.Millisecond)
        }()
    }
    
    wg.Wait()
    
    // 获取阻塞 profile
    records := make([]runtime.BlockProfileRecord, 10)
    n, ok := runtime.BlockProfile(records)
    
    fmt.Printf("Records: %d, OK: %v\n", n, ok)
}

运行结果

Records: 1, OK: true

Breakpoint

func Breakpoint()

说明:执行断点陷阱。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Before breakpoint")
    
    // 在调试器中会触发断点
    runtime.Breakpoint()
    
    fmt.Println("After breakpoint")
}

Caller

func Caller(skip int) (pc uintptr, file string, line int, ok bool)

说明:报告调用 goroutine 堆栈上函数调用的文件和行号信息。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func inner() {
    pc, file, line, ok := runtime.Caller(0)
    if ok {
        fmt.Printf("PC: %v, File: %s, Line: %d\n", pc, file, line)
    }
}

func outer() {
    inner()
}

func main() {
    outer()
}

运行结果

PC: 1032065, File: main.go, Line: 10

Callers

func Callers(skip int, pc []uintptr) int

说明:用调用 goroutine 堆栈上的返回程序计数器填充 pc 切片。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func level3() int {
    pc := make([]uintptr, 10)
    n := runtime.Callers(0, pc)
    return n
}

func level2() int {
    return level3()
}

func level1() int {
    return level2()
}

func main() {
    n := level1()
    fmt.Printf("Captured %d callers\n", n)
}

运行结果

Captured 5 callers

CallersFrames

func CallersFrames(callers []uintptr) *Frames

说明:获取 Callers 返回的 PC 值的函数/文件/行信息。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func deep() {
    pc := make([]uintptr, 10)
    n := runtime.Callers(1, pc)
    
    frames := runtime.CallersFrames(pc[:n])
    for {
        frame, more := frames.Next()
        fmt.Printf("%s\n\t%s:%d\n", frame.Function, frame.File, frame.Line)
        if !more {
            break
        }
    }
}

func main() {
    deep()
}

运行结果

main.deep
    C:/main.go:8
main.main
    C:/main.go:21

CPUProfile

func CPUProfile() []byte

说明:已弃用。使用 runtime/pprof 包代替。

FuncForPC

func FuncForPC(pc uintptr) *Func

说明:返回描述包含给定程序计数器地址的函数的 *Func。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func myFunction() {
    pc, _, _, _ := runtime.Caller(0)
    fn := runtime.FuncForPC(pc)
    
    if fn != nil {
        fmt.Println("Function name:", fn.Name())
        file, line := fn.FileLine(pc)
        fmt.Printf("File: %s, Line: %d\n", file, line)
    }
}

func main() {
    myFunction()
}

运行结果

Function name: main.myFunction
File: main.go, Line: 9

GC

func GC()

说明:运行垃圾回收并阻塞调用者直到垃圾回收完成。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Starting GC...")
    runtime.GC()
    fmt.Println("GC completed")
}

运行结果

Starting GC...
GC completed

GOMAXPROCS

func GOMAXPROCS(n int) int

说明:设置可同时执行的最大 CPU 数并返回之前的设置。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Current GOMAXPROCS:", runtime.GOMAXPROCS(0))
    
    old := runtime.GOMAXPROCS(4)
    fmt.Println("Old GOMAXPROCS:", old)
    fmt.Println("New GOMAXPROCS:", runtime.GOMAXPROCS(0))
}

运行结果

Current GOMAXPROCS: 8
Old GOMAXPROCS: 8
New GOMAXPROCS: 4

GOROOT

func GOROOT() string

说明:已弃用。返回 Go 树的根目录。

Goexit

func Goexit()

说明:终止调用它的 goroutine。

使用示例

package main

import (
    "fmt"
    "runtime"
    "time"
)

func worker(id int) {
    defer fmt.Println("Worker", id, "cleaning up")
    
    fmt.Println("Worker", id, "starting")
    
    if id == 1 {
        fmt.Println("Worker", id, "exiting early")
        runtime.Goexit()
    }
    
    fmt.Println("Worker", id, "finished")
}

func main() {
    go worker(1)
    go worker(2)
    
    time.Sleep(100 * time.Millisecond)
}

运行结果

Worker 1 starting
Worker 1 exiting early
Worker 2 starting
Worker 2 finished
Worker 1 cleaning up
Worker 2 cleaning up

GoroutineProfile

func GoroutineProfile(p []StackRecord) (n int, ok bool)

说明:返回活动 goroutine 堆栈 profile 中的记录数。

使用示例

package main

import (
    "fmt"
    "runtime"
    "time"
)

func worker() {
    time.Sleep(time.Second)
}

func main() {
    for i := 0; i < 3; i++ {
        go worker()
    }
    
    time.Sleep(10 * time.Millisecond)
    
    records := make([]runtime.StackRecord, 10)
    n, ok := runtime.GoroutineProfile(records)
    
    fmt.Printf("Goroutines: %d, OK: %v\n", n, ok)
}

运行结果

Goroutines: 4, OK: true

Gosched

func Gosched()

说明:让出处理器,允许其他 goroutine 运行。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    go func() {
        fmt.Println("Goroutine 1")
    }()
    
    runtime.Gosched()
    fmt.Println("Main goroutine yielded and resumed")
}

运行结果

Goroutine 1
Main goroutine yielded and resumed

KeepAlive

func KeepAlive(x interface{})

说明:标记其参数当前可达,确保对象在调用 KeepAlive 之前不会被释放。

使用示例

package main

import (
    "fmt"
    "runtime"
)

type File struct {
    d int
}

func main() {
    p := &File{d: 42}
    
    runtime.SetFinalizer(p, func(p *File) {
        fmt.Println("Finalizer called")
    })
    
    // 使用 p
    fmt.Println("Using file:", p.d)
    
    // 确保 p 在这一点之前不会被回收
    runtime.KeepAlive(p)
    
    fmt.Println("After KeepAlive")
}

运行结果

Using file: 42
After KeepAlive
Finalizer called

LockOSThread

func LockOSThread()

说明:将调用 goroutine 绑定到其当前操作系统线程。

使用示例

package main

import (
    "fmt"
    "runtime"
    "time"
)

func init() {
    runtime.LockOSThread()
    fmt.Println("Locked to OS thread in init")
}

func main() {
    go func() {
        runtime.LockOSThread()
        fmt.Println("Goroutine locked to OS thread")
        time.Sleep(10 * time.Millisecond)
        runtime.UnlockOSThread()
    }()
    
    time.Sleep(50 * time.Millisecond)
}

运行结果

Locked to OS thread in init
Goroutine locked to OS thread

MemProfile

func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)

说明:返回每个分配站点的内存分配和释放的 profile。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    // 分配一些内存
    data := make([][]byte, 100)
    for i := range data {
        data[i] = make([]byte, 1024)
    }
    
    // 获取内存 profile
    records := make([]runtime.MemProfileRecord, 10)
    n, ok := runtime.MemProfile(records, true)
    
    fmt.Printf("Records: %d, OK: %v\n", n, ok)
    
    for i := 0; i < n && i < 3; i++ {
        fmt.Printf("Alloc: %d bytes, Free: %d bytes\n", 
            records[i].AllocBytes, records[i].FreeBytes)
    }
}

运行结果

Records: 1, OK: true
Alloc: 102400 bytes, Free: 0 bytes

MutexProfile

func MutexProfile(p []BlockProfileRecord) (n int, ok bool)

说明:返回当前 mutex profile 中的记录数。

NumCPU

func NumCPU() int

说明:返回当前进程可用的逻辑 CPU 数。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Logical CPUs:", runtime.NumCPU())
}

运行结果

Logical CPUs: 8

NumCgoCall

func NumCgoCall() int64

说明:返回当前进程进行的 cgo 调用次数。

NumGoroutine

func NumGoroutine() int

说明:返回当前存在的 goroutine 数量。

使用示例

package main

import (
    "fmt"
    "runtime"
    "time"
)

func worker() {
    time.Sleep(time.Second)
}

func main() {
    fmt.Println("Initial goroutines:", runtime.NumGoroutine())
    
    for i := 0; i < 5; i++ {
        go worker()
    }
    
    time.Sleep(10 * time.Millisecond)
    fmt.Println("After spawning:", runtime.NumGoroutine())
}

运行结果

Initial goroutines: 1
After spawning: 6

ReadMemStats

func ReadMemStats(m *MemStats)

说明:用内存分配器统计信息填充 m。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    
    fmt.Printf("Alloc = %v KB", m.Alloc/1024)
    fmt.Printf("\tTotalAlloc = %v KB", m.TotalAlloc/1024)
    fmt.Printf("\tSys = %v KB", m.Sys/1024)
    fmt.Printf("\tNumGC = %v\n", m.NumGC)
}

运行结果

Alloc = 113 KB    TotalAlloc = 113 KB    Sys = 7165 KB    NumGC = 1

ReadTrace

func ReadTrace() []byte

说明:返回下一块二进制跟踪数据。

SetBlockProfileRate

func SetBlockProfileRate(rate int)

说明:控制 goroutine 阻塞事件的报告比例。

SetCPUProfileRate

func SetCPUProfileRate(hz int)

说明:设置 CPU 分析率为每秒 hz 个样本。

SetCgoTraceback

func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer)

说明:记录三个 C 函数,用于从 C 代码收集回溯信息。

SetDefaultGOMAXPROCS

func SetDefaultGOMAXPROCS()

说明:将 GOMAXPROCS 更新为运行时默认值。

SetFinalizer

func SetFinalizer(obj interface{}, finalizer interface{})

说明:设置与 obj 关联的 finalizer 函数。

使用示例

package main

import (
    "fmt"
    "runtime"
    "time"
)

type Resource struct {
    name string
}

func main() {
    r := &Resource{name: "test"}
    
    runtime.SetFinalizer(r, func(r *Resource) {
        fmt.Println("Finalizing:", r.name)
    })
    
    fmt.Println("Resource created")
    
    // 让 r 不可达
    r = nil
    
    // 强制 GC
    runtime.GC()
    time.Sleep(100 * time.Millisecond)
}

运行结果

Resource created
Finalizing: test

SetMutexProfileFraction

func SetMutexProfileFraction(rate int) int

说明:控制 mutex 竞争事件的报告比例。

SetMutexProfileFraction

func SetMutexProfileFraction(rate int) int

说明:控制 mutex 竞争事件的报告比例。

Stack

func Stack(buf []byte, all bool) int

说明:将调用 goroutine 的堆栈跟踪格式化为 buf。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func deep() {
    buf := make([]byte, 1024)
    n := runtime.Stack(buf, false)
    fmt.Printf("Stack trace (%d bytes):\n%s", n, buf[:n])
}

func main() {
    deep()
}

运行结果

Stack trace (xxx bytes):
goroutine 1 [running]:
main.deep(...)
    main.go:9
main.main()
    main.go:14 +0x1

StartTrace

func StartTrace() error

说明:启用当前进程的跟踪。

StopTrace

func StopTrace()

说明:停止跟踪。

ThreadCreateProfile

func ThreadCreateProfile(p []StackRecord) (n int, ok bool)

说明:返回线程创建 profile 中的记录数。

UnlockOSThread

func UnlockOSThread()

说明:撤销早期的 LockOSThread 调用。

Version

func Version() string

说明:返回 Go 树的版本字符串。

使用示例

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Go version:", runtime.Version())
}

运行结果

Go version: go1.21.0

类型详解

BlockProfileRecord

type BlockProfileRecord struct {
    Count  int64
    Cycles int64
    StackRecord
}

说明:描述在特定调用序列产生的阻塞事件。

Cleanup

type Cleanup struct{}

说明:清理调用的句柄。

方法

  • func (c Cleanup) Stop() - 取消清理调用

Error

type Error interface {
    error
    RuntimeError()
}

说明:标识运行时错误使用的 panic。

Frame

type Frame struct {
    Function string
    File     string
    Line     int
    Entry    uintptr
}

说明:Frames 为每个调用帧返回的信息。

Frames

type Frames struct{}

说明:用于获取 Callers 返回的 PC 值的函数/文件/行信息。

方法

  • func (ci *Frames) Next() (frame Frame, more bool) - 返回下一个调用帧

Func

type Func struct{}

说明:表示运行中二进制文件中的 Go 函数。

方法

  • func FuncForPC(pc uintptr) *Func - 获取函数
  • func (f *Func) Entry() uintptr - 返回入口地址
  • func (f *Func) FileLine(pc uintptr) (file string, line int) - 返回文件行号
  • func (f *Func) Name() string - 返回函数名

MemProfileRecord

type MemProfileRecord struct {
    AllocBytes, FreeBytes     int64
    AllocObjects, FreeObjects int64
    Stack0                    [32]uintptr
}

说明:描述由特定调用序列分配的存活对象。

方法

  • func (r *MemProfileRecord) InUseBytes() int64 - 返回使用中的字节数
  • func (r *MemProfileRecord) InUseObjects() int64 - 返回使用中的对象数
  • func (r *MemProfileRecord) Stack() []uintptr - 返回堆栈跟踪

MemStats

type MemStats struct {
    Alloc      uint64
    TotalAlloc uint64
    Sys        uint64
    NumGC      uint32
    // ... 更多字段
}

说明:记录内存分配器的统计信息。

PanicNilError

type PanicNilError struct{}

说明:当代码调用 panic(nil) 时发生。

方法

  • func (*PanicNilError) Error() string
  • func (*PanicNilError) RuntimeError()

Pinner

type Pinner struct{}

说明:一组 Go 对象,每个对象都固定在内存中的固定位置。

方法

  • func (p *Pinner) Pin(pointer interface{}) - 固定对象
  • func (p *Pinner) Unpin() - 解除所有固定对象

StackRecord

type StackRecord struct {
    Stack0 [32]uintptr
}

说明:描述单个执行堆栈。

方法

  • func (r *StackRecord) Stack() []uintptr - 返回堆栈跟踪

TypeAssertionError

type TypeAssertionError struct {
    // 未导出字段
}

说明:解释失败的类型断言。

方法

  • func (e *TypeAssertionError) Error() string
  • func (*TypeAssertionError) RuntimeError()

典型示例

示例 1:获取调用堆栈

package main

import (
    "fmt"
    "runtime"
)

func printStack() {
    pc := make([]uintptr, 10)
    n := runtime.Callers(1, pc)
    
    frames := runtime.CallersFrames(pc[:n])
    for i := 0; ; i++ {
        frame, more := frames.Next()
        fmt.Printf("#%-2d %s\n\t%s:%d\n", i, frame.Function, frame.File, frame.Line)
        if !more {
            break
        }
    }
}

func level1() {
    level2()
}

func level2() {
    level3()
}

func level3() {
    printStack()
}

func main() {
    level1()
}

运行结果

#0  main.printStack
    main.go:11
#1  main.level3
    main.go:22
#2  main.level2
    main.go:18
#3  main.level1
    main.go:14
#4  main.main
    main.go:26

示例 2:内存统计监控

package main

import (
    "fmt"
    "runtime"
    "time"
)

func printMemStats(label string) {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    
    fmt.Printf("%s:\n", label)
    fmt.Printf("  Alloc = %v KB\n", m.Alloc/1024)
    fmt.Printf("  TotalAlloc = %v KB\n", m.TotalAlloc/1024)
    fmt.Printf("  Sys = %v KB\n", m.Sys/1024)
    fmt.Printf("  NumGC = %v\n", m.NumGC)
    fmt.Printf("  NumGoroutine = %v\n\n", runtime.NumGoroutine())
}

func main() {
    printMemStats("Initial")
    
    // 分配内存
    data := make([][]byte, 100)
    for i := range data {
        data[i] = make([]byte, 10*1024)
    }
    
    printMemStats("After allocation")
    
    // 释放内存
    data = nil
    runtime.GC()
    
    printMemStats("After GC")
    
    time.Sleep(time.Second)
}

运行结果

Initial:
  Alloc = 113 KB
  TotalAlloc = 113 KB
  Sys = 7165 KB
  NumGC = 1
  NumGoroutine = 1

After allocation:
  Alloc = 1138 KB
  TotalAlloc = 1251 KB
  Sys = 7165 KB
  NumGC = 1
  NumGoroutine = 1

After GC:
  Alloc = 113 KB
  TotalAlloc = 1251 KB
  Sys = 7165 KB
  NumGC = 2
  NumGoroutine = 1

示例 3:Goroutine 分析

package main

import (
    "fmt"
    "runtime"
    "time"
)

func worker(id int, done chan bool) {
    <-done
}

func main() {
    done := make(chan bool)
    
    // 启动多个 goroutine
    for i := 0; i < 5; i++ {
        go worker(i, done)
    }
    
    time.Sleep(10 * time.Millisecond)
    
    // 获取 goroutine profile
    records := make([]runtime.StackRecord, 10)
    n, ok := runtime.GoroutineProfile(records)
    
    fmt.Printf("Total goroutines: %d\n", n)
    
    for i := 0; i < n; i++ {
        frames := runtime.CallersFrames(records[i].Stack())
        for {
            frame, more := frames.Next()
            if frame.Function != "" {
                fmt.Printf("  Goroutine %d: %s\n", i, frame.Function)
            }
            if !more {
                break
            }
        }
    }
    
    // 清理
    close(done)
}

运行结果

Total goroutines: 6
  Goroutine 0: runtime.gopark
  Goroutine 1: main.worker
  Goroutine 2: main.worker
  ...

示例 4:CPU 和内存分析

package main

import (
    "fmt"
    "runtime"
    "runtime/pprof"
    "os"
)

func main() {
    // 创建 CPU profile 文件
    cpuFile, _ := os.Create("cpu.prof")
    pprof.StartCPUProfile(cpuFile)
    defer pprof.StopCPUProfile()
    
    // 创建内存 profile 文件
    memFile, _ := os.Create("mem.prof")
    defer memFile.Close()
    
    // 执行一些工作
    data := make([]int, 1000000)
    for i := range data {
        data[i] = i * i
    }
    
    // 写入内存 profile
    runtime.GC()
    pprof.WriteHeapProfile(memFile)
    
    fmt.Println("Profiling completed")
}

示例 5:Finalizer 使用

package main

import (
    "fmt"
    "runtime"
    "time"
)

type Database struct {
    conn string
}

func NewDatabase() *Database {
    db := &Database{conn: "mysql://localhost"}
    fmt.Println("Database connection opened")
    
    runtime.SetFinalizer(db, func(db *Database) {
        fmt.Println("Closing database connection:", db.conn)
    })
    
    return db
}

func process() {
    db := NewDatabase()
    // 使用 db...
    _ = db
    // 忘记关闭连接
}

func main() {
    process()
    
    // 强制 GC 以触发 finalizer
    runtime.GC()
    time.Sleep(100 * time.Millisecond)
}

运行结果

Database connection opened
Closing database connection: mysql://localhost

示例 6:Pinner 固定对象

package main

import (
    "fmt"
    "runtime"
    "unsafe"
)

func main() {
    var p runtime.Pinner
    
    // 分配 Go 对象
    data := make([]byte, 100)
    
    // 固定对象
    p.Pin(data)
    
    // 获取指针(可以安全传递给 C 代码)
    ptr := unsafe.Pointer(&data[0])
    fmt.Printf("Pinned at: %p\n", ptr)
    
    // 使用完后解除固定
    p.Unpin()
    
    fmt.Println("Unpinned")
}

运行结果

Pinned at: 0xc000016060
Unpinned

示例 7:版本和平台信息

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("Go 运行时信息:")
    fmt.Printf("  版本:%s\n", runtime.Version())
    fmt.Printf("  编译器:%s\n", runtime.Compiler)
    fmt.Printf("  操作系统:%s\n", runtime.GOOS)
    fmt.Printf("  架构:%s\n", runtime.GOARCH)
    fmt.Printf("  CPU 数:%d\n", runtime.NumCPU())
    fmt.Printf("  GOMAXPROCS:%d\n", runtime.GOMAXPROCS(0))
}

运行结果

Go 运行时信息:
  版本:go1.21.0
  编译器:gc
  操作系统:windows
  架构:amd64
  CPU 数:8
  GOMAXPROCS:8

示例 8:调试信息收集

package main

import (
    "fmt"
    "runtime"
)

func collectDebugInfo() {
    fmt.Println("=== 调试信息 ===")
    
    // 内存统计
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    fmt.Printf("内存使用:%d KB\n", m.Alloc/1024)
    fmt.Printf("GC 次数:%d\n", m.NumGC)
    
    // Goroutine 数量
    fmt.Printf("Goroutine 数量:%d\n", runtime.NumGoroutine())
    
    // 堆栈跟踪
    buf := make([]byte, 1024)
    n := runtime.Stack(buf, true)
    fmt.Printf("堆栈跟踪大小:%d bytes\n", n)
}

func main() {
    collectDebugInfo()
}

运行结果

=== 调试信息 ===
内存使用:113 KB
GC 次数:1
Goroutine 数量:1
堆栈跟踪大小:xxx bytes

最佳实践

1. 谨慎使用 runtime 包

// ✅ 推荐:使用标准库
import "context"
ctx, cancel := context.WithTimeout(context.Background(), time.Second)

// ❌ 不推荐:过度依赖 runtime
runtime.Gosched()  // 手动调度

2. 正确使用 Finalizer

// ✅ 推荐:使用 defer 清理资源
func process() {
    f, _ := os.Open("file.txt")
    defer f.Close()
    // ...
}

// ❌ 不推荐:依赖 finalizer 清理
func process() {
    f := &File{...}
    runtime.SetFinalizer(f, func(f *File) { f.Close() })
    // finalizer 可能不会运行
}

3. 合理使用 GOMAXPROCS

// ✅ 推荐:让运行时自动选择
// 默认值通常是最优的

// ⚠️ 谨慎:手动设置
runtime.GOMAXPROCS(4)  // 仅在了解影响时设置

4. 性能分析使用 pprof

// ✅ 推荐:使用 pprof 包
import "runtime/pprof"
pprof.StartCPUProfile(file)

// ❌ 不推荐:直接使用底层函数
runtime.SetCPUProfileRate(100)

与其他包配合

runtime/pprof

package main

import (
    "os"
    "runtime/pprof"
)

func main() {
    f, _ := os.Create("cpu.prof")
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()
    
    // 执行代码...
}

runtime/trace

package main

import (
    "os"
    "runtime/trace"
)

func main() {
    f, _ := os.Create("trace.out")
    trace.Start(f)
    defer trace.Stop()
    
    // 执行代码...
}

reflect

package main

import (
    "fmt"
    "reflect"
    "runtime"
)

func main() {
    pc, _, _, _ := runtime.Caller(0)
    fn := runtime.FuncForPC(pc)
    
    t := reflect.TypeOf(fn)
    fmt.Printf("Type: %s\n", t)
}

快速参考

常量

常量类型说明
Compilerstring编译器名称
GOARCHstring目标架构
GOOSstring目标操作系统

变量

变量类型说明
MemProfileRateint内存分析率

函数

函数参数返回值说明
AddCleanupptr, cleanup, argCleanup添加清理函数
BlockProfilep []BlockProfileRecordn, ok阻塞 profile
Callerskip intpc, file, line, ok调用者信息
Callersskip int, pc []uintptrint填充调用者 PC
CallersFramescallers []uintptr*Frames获取帧信息
GC--运行 GC
GOMAXPROCSn intint设置/获取 CPU 数
Goexit--终止 goroutine
GoroutineProfilep []StackRecordn, okGoroutine profile
Gosched--让出处理器
KeepAlivex interface{}-保持对象可达
LockOSThread--锁定 OS 线程
MemProfilep, inuseZeron, ok内存 profile
NumCPU-intCPU 数量
NumGoroutine-intGoroutine 数量
ReadMemStatsm *MemStats-读取内存统计
SetFinalizerobj, finalizer-设置 finalizer
Stackbuf []byte, all boolint堆栈跟踪
Version-stringGo 版本

类型

类型说明
BlockProfileRecord阻塞 profile 记录
Cleanup清理句柄
Error运行时错误接口
Frame调用帧信息
Frames帧迭代器
Func函数表示
MemProfileRecord内存 profile 记录
MemStats内存统计
PanicNilErrorpanic(nil) 错误
Pinner对象固定器
StackRecord堆栈记录
TypeAssertionError类型断言错误

注意事项

1. 低级包

runtime 是低级包,大多数应用程序不需要直接使用。

2. Finalizer 限制

  • Finalizer 不保证运行
  • Finalizer 运行顺序不确定
  • 不应依赖 finalizer 释放关键资源

3. 性能影响

  • 频繁调用 GC 会影响性能
  • 过高的分析率会影响性能
  • LockOSThread 会限制调度器优化

4. 平台差异

  • 某些函数在特定平台行为不同
  • Windows 不支持某些功能

5. 版本兼容

  • runtime API 可能随 Go 版本变化
  • 应避免依赖未文档化的行为

总结

runtime 包提供了与 Go 运行时系统交互的低级接口。

核心要点

  1. 这是低级包,大多数情况使用标准库即可
  2. Finalizer 不保证运行,不应依赖其释放关键资源
  3. 性能分析应使用 pprof 而非直接调用 runtime 函数
  4. GOMAXPROCS 默认值通常是最优的
  5. 谨慎使用 LockOSThread 和 Goexit

主要用途

  • 性能分析和调优
  • 调试和故障排查
  • 特殊场景的 goroutine 控制
  • 内存管理监控