❝"Выпуск 8" До 80-го номера дядюшки еще 72 номера., чем дядя хочет поделиться с вами сегодня, так это базовыми знаниями голанга——Можно ли сравнивать структуру?, Этот основной вопрос является проверкой основ и деталей каждого, и это также вопрос, который предпочитают задавать интервьюеры. Давайте посмотрим на него вместе с вами.
❞
Можно ли сравнивать структуру?Очевидно, что это предложение содержит две ситуации:
- Можно ли сравнивать два экземпляра одной и той же структуры?
- Можно ли сравнивать два экземпляра разных структур?
фокус
Прежде чем разбирать два вопроса выше, давайте разберемся, какие типы данных сопоставимы, а какие несопоставимы в golang:
- Сопоставимые:Integer,Floating-point,String,Boolean,Комплекс (множественное число),Pointer,Channel,Interface,Array
- Не сравнимо:Slice,Map,Function
Проанализируем две описанные выше ситуации по отдельности.
Можно ли сравнивать два экземпляра одной и той же структуры?
Во-первых, давайте создадим структурную структуру для игры с
type S struct {
Name string
Age int
Address *int
}
func main() {
a := S{
Name: "aa",
Age: 1,
Address: new(int),
}
b := S{
Name: "aa",
Age: 1,
Address: new(int),
}
fmt.Println(a == b)
}
Запуск приведенного выше кода обнаруживает, что он напечатает false. Поскольку вывод можно распечатать нормально, значит, его можно сравнить."Два вопроса о смерти"
Что можно сравнить?
Возвращаясь к выделенной выше части, в резюме мы можем знать, что в golangSlice,Map,FunctionЭти три типа данных нельзя сравнивать напрямую. Давайте снова посмотрим на структуру S. Структура не содержит несравнимых переменных-членов, поэтому структуру можно сравнивать напрямую.
Почему он печатает ложь?
Хотя a и b являются двумя экземплярами одной и той же структуры, поскольку значение переменной-указателя Address отличается, a != b, если ab удаляет Address во время инициализации (не инициализирует Address), то a = = b истинно, потому что значение по умолчанию переменной ptr равно нулю, или значение той же переменной-указателя присваивается переменной-члену Address, что также верно.
Что, если в структуру S добавить переменную-член типа Slice?
type S struct {
Name string
Age int
Address *int
Data []int
}
func main() {
a := S{
Name: "aa",
Age: 1,
Address: new(int),
Data: []int{1, 2, 3},
}
b := S{
Name: "aa",
Age: 1,
Address: new(int),
Data: []int{1, 2, 3},
}
fmt.Println(a == b)
}
Что будет напечатано в это время? истинный? ложный? На самом деле запуск приведенного выше кода сообщит о следующей ошибке:
# command-line-arguments
./test.go:37:16: invalid operation: a == b (struct containing []int cannot be compared)
Хотя a, b являются двумя экземплярами одной и той же структуры с одинаковым назначением, поскольку переменные-члены структуры имеют несравнимые элементы (срез), их нельзя сравнивать напрямую с ==, поэтому просто напишите == и сообщите об ошибке
"Суммировать"
Два экземпляра одной и той же структуры можно сравнивать или нет. Если структура не содержит несопоставимых переменных-членов, их можно сравнивать напрямую. В противном случае их нельзя сравнивать напрямую.
Но в обычном практическом процессе, когда нам нужно сравнить экземпляры структур, содержащих типы данных, которые нельзя сравнивать напрямую, нельзя ли сравнивать? На самом деле это не так, golang по-прежнему дружелюбен, мы можем использоватьфункция Reflect.DeepEqualдля сравнения двух переменных. Таким образом, мы можем написать приведенный выше код следующим образом:
type S struct {
Name string
Age int
Address *int
Data []int
}
func main() {
a := S{
Name: "aa",
Age: 1,
Address: new(int),
Data: []int{1, 2, 3},
}
b := S{
Name: "aa",
Age: 1,
Address: new(int),
Data: []int{1, 2, 3},
}
fmt.Println(reflect.DeepEqual(a, b))
}
распечатать:
true
Так как же Reflect.DeepEqual сравнивает переменные?
reflect.DeepEqual
Функция DeepEqual используется для определения того, являются ли два значения глубоко согласованными. Конкретные правила сравнения следующие:
- Ценности разных типов никогда не бывают глубоко равными
- Два массива имеют одинаковую глубину, когда соответствующие глубины элементов двух массивов равны.
- Когда все поля двух одинаковых структур соответствуют одной и той же глубине, глубины двух структур равны
- Когда обе функции равны нулю, две функции имеют одинаковую глубину, в противном случае они не равны (одна и та же функция также не равна)
- Когда глубины истинных значений двух интерфейсов равны, глубины двух интерфейсов равны
- Сравнение карт должно одновременно отвечать следующим требованиям.
- Обе карты равны нулю или ни одна из них не равна нулю, а длины должны быть равны
- Один и тот же объект карты или все ключи должны соответствовать одному и тому же
- Значение, соответствующее карте, также должно иметь одинаковую глубину.
- Указатель, удовлетворяющий одному из следующих условий, равен глубине
- Два указателя удовлетворяют оператору go ==
- Значения, на которые указывают два указателя, глубоко равны
- Нарезая, вам необходимо одновременно выполнить следующие пункты, чтобы они были равными по глубине
- Оба среза равны нулю или ни один из них не равен нулю и имеют одинаковую длину
- Первая позиция, на которую указывают базовые данные двух срезов, должна быть одинаковой или базовые элементы должны иметь одинаковую глубину.
- Примечание. Пустой срез не имеет такой же глубины, как нулевой срез.
- Значения других типов (числа, логические значения, строки, каналы) глубоко равны, если они удовлетворяют оператору go ==. Имейте в виду, что не все значения глубоко равны сами себе, такие как функции и вложенные структуры, массивы и т. д., которые содержат эти значения.
Можно ли сравнивать два экземпляра разных структур?
"в заключении": Сопоставимо или несопоставимо
Сравнение можно провести с помощью приведения:
type T2 struct {
Name string
Age int
Arr [2]bool
ptr *int
}
type T3 struct {
Name string
Age int
Arr [2]bool
ptr *int
}
func main() {
var ss1 T2
var ss2 T3
// Cannot use 'ss2' (type T3) as type T2 in assignment
//ss1 = ss2 // 不同结构体之间是不可以赋值的
ss3 := T2(ss2)
fmt.Println(ss3==ss1) // true
}
Если переменная-член содержит несопоставимые переменные-члены, даже если она может быть приведена, ее нельзя сравнивать
type T2 struct {
Name string
Age int
Arr [2]bool
ptr *int
map1 map[string]string
}
type T3 struct {
Name string
Age int
Arr [2]bool
ptr *int
map1 map[string]string
}
func main() {
var ss1 T2
var ss2 T3
ss3 := T2(ss2)
fmt.Println(ss3==ss1) // 含有不可比较成员变量
}
Ошибка компиляции:
# command-line-arguments
./test.go:28:18: invalid operation: ss3 == ss1 (struct containing map[string]string cannot be compared)
В: Можно ли использовать структуру в качестве ключа карты?
структура должна быть сопоставима, прежде чем ее можно будет использовать в качестве ключа, иначе при компиляции будет сообщено об ошибке
type T1 struct {
Name string
Age int
Arr [2]bool
ptr *int
slice []int
map1 map[string]string
}
type T2 struct {
Name string
Age int
Arr [2]bool
ptr *int
}
func main() {
// n := make(map[T2]string, 0) // 无报错
// fmt.Print(n) // map[]
m := make(map[T1]string, 0)
fmt.Println(m) // invalid map key type T1
}
Это то, чем я хочу поделиться с вами сегодня.Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение дяде на заднем плане, обратите вниманиедядя говорит код, увидимся в следующий раз~
Справочная документация:
- https://studygolang.com/pkgdoc
- https://studygolang.com/articles/12944?fr=sidebar