Подтвердить что ты не робот

Значение подчеркивания (пустой идентификатор) в Go

Как я читал документы Go, я нашел это:

Вы можете попросить компилятор проверить, что тип T реализует интерфейс I, пытаясь выполнить назначение:

type T struct{}
var _ I = T{} // Verify that T implements I.

Я не понимаю, для чего используется _, и я видел его в других назначениях, но не могу понять, что это значит. Копая глубже, я обнаружил, что он называется "пустой идентификатор", но я не понимаю, как они используются:

_ = x // evaluate x but ignore it

Идиомы поезда все еще немного чужды мне, поэтому я пытаюсь понять, почему я хотел бы сделать что-то вроде этого.

4b9b3361

Ответ 1

_ - специальный идентификатор, который вы можете назначить, но никогда не читать. В первом примере вы дали:

var _ I = T{}

Нет доступа к этой переменной, поэтому она будет оптимизирована из полученной программы. Однако это может привести к ошибке компиляции, если тип T не назначен для интерфейса I. Поэтому в этом случае он используется как статическое утверждение о типе.

Второй случай более распространен. Хотя может показаться странным отказаться от результата вызова функции, это может иметь больший смысл в функциях с несколькими возвратами. Рассмотрим функцию foo, которая возвращает два значения, но вас интересует только первая? Вы можете использовать _ для игнорирования второго:

a, _ = foo()

Вы можете получить тот же эффект, создав еще одну переменную, чтобы удерживать нежелательное возвращаемое значение, но эта функция означает, что вам не нужно беспокоиться о выборе для нее уникального имени.

Ответ 2

Это распространено в языках, допускающих множественные возвращаемые значения. Бывают ситуации, когда вы действительно не заботитесь об одном из возвращаемых значений.

Например, в Go обычно возникает ошибка. Если по какой-то причине вас не волнует эта ошибка, вы можете игнорировать ее:

value, _ := methodThatReturnsValueAndError()

Если, однако, вы назначаете его и не используете его, возникает ошибка компилятора:

value, err := methodThatReturnsValueAndError()
// if you don't use "err" .. its an error

Ответ 3

"В" Информатике "есть только две тяжелые вещи: недействительность кэша и именование вещей". Тим Брей цитирует Фила Карлтона

Это о том, чтобы не называть вещи.

В Go, если вы не хотите использовать a или foo в качестве имени переменной примера, вы можете использовать _. Это! Они могли бы написать var a I = T{}, результат был бы одинаковым (за исключением того, что неиспользуемые переменные являются ошибкой в ​​Go).

Для других целей использования пустого идентификатора прочитайте Эффективный переход.

Ответ 4

Простыми словами _ это игнорируемое значение. Go не разрешает использование неиспользуемых локальных переменных и выдает ошибку компиляции, если вы попытаетесь это сделать. Таким образом, вы обманываете компилятор, говоря "пожалуйста, игнорируйте это значение", поместив _

Например:

// Here range of os.Args returns index, value
for index, arg := range os.Args[1:] {
    fmt.Println(arg)
}

Здесь Go генерирует ошибку компиляции, потому что вы вообще не используете index (unused local variable) в цикле. Теперь вы должны сделать index для _, чтобы компилятор игнорировал его.

for _, arg := range os.Args[1:] {
    fmt.Println(arg)
}

Ответ 5

Компилятор Go в значительной степени запрещает переменные, которые объявлены, но не используются. Вот так,

for i, myvalue := range myvar {
    total += mvalue
}

Данный код покажет ошибку несколько в этом контексте → "объявлено, но не используется".
Следовательно, мы решаем это, используя следующий фрагмент:

for _, myvalue := range x {
    total += myvalue
}


Что касается части импорта, то речь идет об импорте пакета исключительно по побочным эффектам.
Пожалуйста, обратитесь по этой ссылке.