Используя адрес первого элемента
Самый простой способ - просто получить адрес первого элемента срезов и сравнить их (указатели сопоставимы ). Мы можем получить адрес первого элемента, просто используя адресный оператор , например, &s[0]
. Если срезы пусты, первого элемента не существует, и в этом случае мы проверяем только, являются ли оба элемента пустыми. Мы также должны сравнить длины ломтиков:
func identical(s1, s2 []int) bool {
if len(s1) != len(s2) {
return false
}
return len(s1) == 0 || &s1[0] == &s2[0]
}
Я намеренно пропустил сравнение емкости, так как она играет роль только в том случае, если срезы нарезаны.
Эта identical()
функция только проверяет идентичность срезов. 2 неидентичных среза могут быть одинаковыми (они могут содержать одинаковые элементы), даже если они не идентичны.
Тестирование:
s := []int{1, 2, 3}
fmt.Println(identical(s, s))
s2 := []int{1, 2, 3}
fmt.Println(identical(s, s2))
Вывод (попробуйте на Go Playground ):
true
false
Использование reflect.SliceHeader
Мы можем выбрать получение и использование дескрипторов слайса, которые содержат указатель, длину и емкость. Это смоделировано reflect.SliceHeader
:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
Чтобы получить reflect.SliceHeader
, мы можем использовать пакет unsafe
и тип unsafe.Pointer
, например:
var s []int = ... // s is a slice
// and h will be its descriptor, of type *reflect.SliceHeader
h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
Простая функция сравнения, которая проверяет, являются ли 2 среза идентичными, то есть они указывают на один и тот же резервный массив и имеют одинаковую длину (независимо от их емкости):
func identical(s1, s2 []int) bool {
h1 := (*reflect.SliceHeader)(unsafe.Pointer(&s1))
h2 := (*reflect.SliceHeader)(unsafe.Pointer(&s2))
return h1.Data == h2.Data && h1.Len == h2.Len
}
Тестирование:
s := []int{1, 2, 3}
fmt.Println(identical(s, s))
s2 := []int{1, 2, 3}
fmt.Println(identical(s, s2))
Вывод (попробуйте на Go Playground ):
true
false