在 Go 中,切片是对底层数组的引用,它们的头存储有关切片长度和容量的信息,以及指向基础数据。虽然切片的内容可以修改,但其标头通常保持不变。
考虑以下代码片段:
var buffer [256] byte func SubtractOneFromLength(slice []byte) []byte { slice = slice[0 : len(slice)-1] return slice } func main() { slice := buffer[10:20] fmt.Println("Before: len(slice) =", len(slice)) newSlice := SubtractOneFromLength(slice) fmt.Println("After: len(slice) =", len(slice)) fmt.Println("After: len(newSlice) =", len(newSlice)) newSlice2 := SubtractOneFromLength(newSlice) fmt.Println("After: len(newSlice2) =", len(newSlice2)) }
当调用函数 SubtractOneFromLength 时,它会修改切片,但不是切片头。要检查切片头,您可以使用reflect.SliceHeader类型。
type SliceHeader struct { Data uintptr Len int Cap int }
以下不安全操作演示了如何将切片指针转换为*reflect.SliceHeader:
sh := (*reflect.SliceHeader)(unsafe.Pointer(&newSlice2))
然后您可以使用格式字符串 % v:
fmt.Printf("%+v", sh)
Go Playground 生成以下输出:
&{Data:1792106 Len:8 Cap:246}
此输出提供底层数据 (Data) 的内存地址、切片的长度 (Len) 及其容量 (Cap)。
不带unsafe:
不使用unsafe访问切片头信息也是如此可能:
以上是如何安全和不安全地检查Go Slice的头部?的详细内容。更多信息请关注PHP中文网其他相关文章!