Как правило, вы не можете определить, используется ли массив резервных копий для двух срезов, потому что, используя выражение полного среза , можно контролировать емкость результирующего среза, и тогда не будет перекрытия.даже при проверке емкости.
Например, если у вас есть резервный массив с 10 элементами, может быть создан фрагмент, который содержит только первые 2 элемента, и его емкость может быть равна 2. И другой фрагмент можетbe create, который содержит только последние 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 есть указатели, нонет арифметики указателей).И проверить, совпадают ли все адреса элементов первого слайса с любым из второго, это неосуществимо.
Но мы можем получить значение указателя (адрес) как тип uintptr
, используя отражениепакет, более конкретно метод Value.Pointer()
(или мы могли бы также сделать это, используя пакет unsafe
, но reflect
"безопаснее"), а значения 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 .