Golang中slice的底层数组实现解析
Golang中slice的底层数组实现解析
tail := make([]byte, 1000, 1000)
block := make([]byte, 1000)
block = append(tail, block...)
在上述代码中,“tail”和“block”将指向不同的底层数组。
tail := make([]byte, 1000, 2000)
block := make([]byte, 1000)
block = append(tail, block...)
在上述代码中,最后一行会将“block”中的1000个字节追加到“tail”中,然后将“block”指向“tail”。因此,在这种情况下,“tail”和“block”将指向相同的底层数组。
如何通过编程方式判断两个切片的底层数组是否指向相同的内存位置?
if &tail[0] == &block[0] {
// 相同位置
}
上述代码可以工作,但这是符合Go语言习惯的代码吗?有没有更好的方法?
更多关于Golang中slice的底层数组实现解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html
为什么你要检查一个切片是否与另一个切片共享相同的底层数组?你会想要处理像这样的情况吗?
a := make([]byte, 1000)
b := a[16:24]
更多关于Golang中slice的底层数组实现解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
通常更好的做法是制定一个策略,明确函数是否“拥有”传递给它的切片,或者如果它需要保留切片,是否需要创建副本。例如,io.Reader 及其相关函数被记录为不保留切片。此外,使用三索引切片(foo[:len(foo):len(foo)])来限制容量,确保追加操作会触发新的内存分配。接收到这种切片的函数无法覆盖 len 之后的字节。
func main() {
fmt.Println("hello world")
}
在Go中判断两个切片是否共享底层数组,可以通过比较它们的底层数组指针来实现。你提到的方法 &tail[0] == &block[0] 是可行的,但需要确保切片非空,否则会引发panic。
更健壮的方式是使用reflect.SliceHeader来获取底层数组指针,但需要注意这涉及unsafe操作。以下是两种实现方式:
方法1:使用切片首元素地址比较(需确保非空)
func shareArray(s1, s2 []byte) bool {
if len(s1) == 0 || len(s2) == 0 {
return false
}
return &s1[0] == &s2[0]
}
方法2:使用reflect.SliceHeader(可处理空切片)
import (
"reflect"
"unsafe"
)
func shareArray(s1, s2 []byte) bool {
h1 := (*reflect.SliceHeader)(unsafe.Pointer(&s1))
h2 := (*reflect.SliceHeader)(unsafe.Pointer(&s2))
return h1.Data == h2.Data
}
方法3:使用unsafe.Pointer直接比较
import "unsafe"
func shareArray(s1, s2 []byte) bool {
return unsafe.Pointer(&s1[:1][0]) == unsafe.Pointer(&s2[:1][0])
}
在实际代码中,第一种方法最为常见,因为它简单直接。但如果你需要处理空切片的情况,第二种方法更安全。需要注意的是,这些方法都涉及底层实现细节,应谨慎使用。
示例验证:
func main() {
// 示例1:不同底层数组
tail := make([]byte, 1000, 1000)
block := make([]byte, 1000)
block = append(tail, block...)
fmt.Println("示例1共享数组:", shareArray(tail, block)) // false
// 示例2:相同底层数组
tail2 := make([]byte, 1000, 2000)
block2 := make([]byte, 1000)
block2 = append(tail2, block2...)
fmt.Println("示例2共享数组:", shareArray(tail2, block2)) // true
}
在Go社区中,&s1[0] == &s2[0] 这种写法被认为是可接受的,只要你能确保切片非空。如果代码中可能遇到空切片,建议添加长度检查或使用更安全的方法。


