golang切片边界自动检查

作者:matrix 发布时间:2025-09-30 分类:Golang

golang切片边界自动检查

Golang 的切片边界自动检查(automatic slice bounds checking)是编译器在每次访问切片元素(比如 s[i])或进行切片操作(比如 s[a:b])时自动插入检查逻辑的安全机制,用于防止越界访问导致的崩溃。

自动检查机制

比如读取这个切片元素 s[i] ,在编译期间就会自动插入边界检查代码。

看到的代码:

func get(s []int, i int) int {
    return s[i]
}

编译器自动检查后的伪代码(编译器隐式实现):

func get(s []int, i int) int {
    // 自动插入的边界检查
    if i < 0 || i >= len(s) {
        panic("runtime error: index out of range")
    }
    return s[i]
}

编译器一般都会自动添加这种检查逻辑,除非编译器知道这个边界范围是安全的。
如果在循环中频繁访问切片元素的话就会导致不必要的开销。这种算是极致的性能优化了~ 目前还用不到😂

消除越界检查

没有主动消除的办法,只能显示告知编译器让其安全访问

source: https://cs.opensource.google/go/go/+/refs/tags/go1.23.2:src/cmd/compile/internal/bitvec/bv.go;l=161

func (dst BitVec) And(src1, src2 BitVec) {
    if len(src1.B) == 0 {
        return
    }
    _, _ = dst.B[len(src1.B)-1], src2.B[len(src1.B)-1] // hoist bounds checks out of the loop

    for i, x := range src1.B {
        dst.B[i] = x & src2.B[i]
    }
}

第 5 行「hoist bounds checks out of the loop」注释位置的代码 目的就是把越界检查提升到循环外部,显式告知编译器 dst.B 和 src2.B 的长度至少和 src1.B 一样,避免在每次迭代时检查。

如何确定有边界检查

go build -gcflags="-d=ssa/check_bce/debug=1" yourmain.go

run或者 build添加的-gcflags="-d=ssa/check_bce/debug=1" 可以看到是否存在边界检查

# command-line-arguments
./struct_11test.go:23:19: Found IsInBounds

Found IsInBounds 即表示存在自动边界检查