Ответ
Сравнение интерфейсов в Go — это важная концепция, которая проверяет как динамический тип, так и динамическое значение, хранящиеся в интерфейсе.
Правила сравнения
Два интерфейсных значения равны, если выполняется одно из условий:
- Оба интерфейса равны
nil. - Их динамические типы идентичны, и их динамические значения равны в соответствии с правилами сравнения для этого типа.
Интерфейсы не равны, если:
- Один из них
nil, а другой нет. - Их динамические типы различаются.
- Их типы одинаковы, но значения не равны.
Пример сравнения
var a, b interface{}
a = 100
b = 100
fmt.Println(a == b) // true (типы int, значения 100 == 100)
b = int64(100)
fmt.Println(a == b) // false (типы разные: int != int64)
var c interface{} = "hello"
var d interface{} = "hello"
fmt.Println(c == d) // true (типы string, значения равны)
⚠️ Паника при сравнении несравниваемых типов
Попытка сравнить два интерфейса, которые содержат значения несравниваемых типов, вызовет панику во время выполнения.
К несравниваемым типам относятся:
- Слайсы (
slice) - Карты (
map) - Функции (
func)
var c interface{} = []int{1, 2}
var d interface{} = []int{1, 2}
// fmt.Println(c == d) // паника: runtime error: comparing uncomparable type []int
Классическая ловушка: nil интерфейс vs интерфейс с nil значением
Интерфейс не равен nil, если в нем хранится значение, даже если само это значение является nil-указателем. Это происходит потому, что у такого интерфейса есть динамический тип.
type MyError struct{}
func (e *MyError) Error() string { return "error" }
func getError() error {
var err *MyError = nil // Создаем nil-указатель на структуру
return err // Возвращаем его как интерфейс error
}
func main() {
err := getError()
// err не равен nil, т.к. он содержит тип (*MyError) и значение (nil)
if err != nil {
fmt.Printf("Ошибка! Тип: %T, Значение: %vn", err, err)
}
}
// Вывод:
// Ошибка! Тип: *main.MyError, Значение: <nil> Ответ 18+ 🔞
А, интерфейсы в Go, ёпта! Ну это ж классика, блядь, вечный источник головной боли и паники в три часа ночи. Слушай, тут всё просто, как два пальца об асфальт, но с подвохом, как всегда.
Вот представь: интерфейс — это такая коробка, блядь. Внутри может лежать что угодно: число, строка, твоя старая фотка. И сравнивать эти коробки — это не просто так, на глазок.
Правила, сука, железные: Коробки считаются одинаковыми, если:
- Обе пустые, нихуя в них нет, обе
nil. Всё, вопросов нет. - Внутри лежат одинаковые хуйни (один и тот же тип) и эти самые хуйни равны между собой по своим внутренним законам.
А вот если:
- Одна коробка пустая, а в другой что-то лежит — нихуя не равны.
- Типы внутри разные — нихуя не равны.
- Типы одинаковые, а значения разные — нихуя не равны.
var a, b interface{}
a = 100
b = 100
fmt.Println(a == b) // true (оба int, оба 100, всё ок)
b = int64(100)
fmt.Println(a == b) // false (внутри разная хуйня: int vs int64, ёпта!)
var c interface{} = "hello"
var d interface{} = "hello"
fmt.Println(c == d) // true (оба string, оба "hello")
А теперь главный пиздец, блядь!
Если ты сунешь в эту коробку несравниваемую хуйню, а потом попробуешь коробки сравнить — тебе пизда, паника на ровном месте! Кто несравниваемый? Да всякие извращенцы: слайсы, мапы, функции!
var c interface{} = []int{1, 2}
var d interface{} = []int{1, 2}
// fmt.Println(c == d) // ПИЗДЕЦ! Паника! Слайсы сравнивать низяяя!
И ловушка года, блядь, классика жанра!
nil интерфейс и интерфейс с nil значением — это, сука, две большие разницы! Представь, у тебя есть коробка, в которой лежит бумажка с надписью "ничего". Коробка-то не пустая! В ней же бумажка лежит, ёбана!
type MyError struct{}
func (e *MyError) Error() string { return "error" }
func getError() error {
var err *MyError = nil // Указатель на структуру, который нихуя не указывает (nil)
return err // Возвращаем его как интерфейс error
}
func main() {
err := getError()
// Сюрприз, сука! err тут НЕ nil!
// Потому что коробка (интерфейс error) НЕ ПУСТАЯ.
// В ней лежит информация: "тут внутри тип *MyError, а значение у него — nil".
if err != nil {
fmt.Printf("Ошибка! Тип: %T, Значение: %vn", err, err) // Вот же ж блядь!
}
}
// Вывод:
// Ошибка! Тип: *main.MyError, Значение: <nil>
Вот так вот, ебать мои старые костыли. Кажется, что всё просто, а потом бац — и ты уже дебажишь эту хуйню до утра. Главное запомни: коробка с бумажкой "ничего" — это не пустая коробка!