[英]Go: Arrays of arrays, arrays of slices, slices of arrays and slices of slices
[英]Aliasing of slices
如何检查两个切片是否由同一阵列备份?
例如:
a := []int{1, 2, 3}
b := a[0:1]
c := a[2:3]
alias(b, c) == true
alias
应如何显示?
通常,您无法确定2个切片之间是否共享了支持数组,因为使用完整切片表达式 ,一个数组可能会控制所得切片的容量,因此即使检查容量也不会有重叠。
例如,如果您有一个包含10个元素的支持数组,则可能会创建一个仅包含前2个元素的切片,其容量可能是2。并且可能会创建另一个仅保留其后2个元素及其容量的切片。再次是2。
请参阅以下示例:
a := [10]int{}
x := a[0:2:2]
y := a[8:10:10]
fmt.Println("len(x) = ", len(x), ", cap(x) = ", cap(x))
fmt.Println("len(y) = ", len(y), ", cap(y) = ", cap(y))
上面的代码将打印出x
和y
长度和容量均为2。它们显然具有相同的后备数组,但是您将没有任何办法来说明这一点。
编辑:我误解了这个问题,下面介绍如何判断2个切片的(元素)是否重叠。
没有语言支持,但是由于切片具有某个后备数组的连续部分,因此我们可以检查其元素的地址范围是否重叠。
不幸的是,指针不能以不能在其上应用<
和>
运算符的方式排序(Go中有指针,但是没有指针算术)。 并且检查第一个切片的元素的所有地址是否与第二个切片的任何地址匹配,这是不可行的。
但是我们可以使用反射包,更具体地说是Value.Pointer()
方法(或者也可以使用包unsafe
,但reflect
是“更安全”的)来获取指针值(地址)作为uintptr
一种类型。 uintptr
值是整数,它们是有序的,因此我们可以对其进行比较。
因此,我们可以做的是获取切片的第一个和最后一个元素的地址,并通过比较它们来确定它们是否重叠。
这是一个简单的实现:
func overlap(a, b []int) bool {
if len(a) == 0 || len(b) == 0 {
return false
}
amin := reflect.ValueOf(&a[0]).Pointer()
amax := reflect.ValueOf(&a[len(a)-1]).Pointer()
bmin := reflect.ValueOf(&b[0]).Pointer()
bmax := reflect.ValueOf(&b[len(b)-1]).Pointer()
return !(amax < bmin || amin > bmax)
}
测试它:
a := []int{0, 1, 2, 3}
b := a[0:2]
c := a[2:4]
d := a[0:3]
fmt.Println(overlap(a, b)) // true
fmt.Println(overlap(b, c)) // false
fmt.Println(overlap(c, d)) // true
在Go Playground上尝试一下。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.