Как понимать _ в func (a, _ int, z float32) bool [duplicate]

W3C исключил такой селектор из-за огромного влияния производительности на браузер.

10
задан icza 3 December 2016 в 19:38
поделиться

1 ответ

Беззначительные параметры совершенно верны. Объявление параметра параметра из спецификации:

ParameterDecl  = [ IdentifierList ] [ "..." ] Type .

Как вы можете видеть, IdentifierList (имя или имена идентификатора) находится в квадратных скобках, что означает, что это необязательно . Требуется только Type.

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

Обычно вы называете переменные и параметры, чтобы вы могли ссылаться на них.

Когда вы не называйте что-то, потому что вы не хотите ссылаться на него.

Итак, вопрос должен быть следующим: Почему я не хочу ссылаться на параметр?

Например, поскольку параметр "есть" (он передан), но он вам не нужен, вы не хотите его использовать. Почему он должен быть там, если мне это не нужно?

Потому что кто-то или что-то диктует для определенных параметров. Например, вы хотите реализовать интерфейс или хотите передать значение функции, подпись которого определяется ожидаемым типом функции.

Давайте посмотрим пример. У нас есть следующий интерфейс MyWriter:

type MyWriter interface {
    Write(p []byte) error
}

Упрощенный io.Writer , который возвращает только ошибку, но не сообщает количество записанных байтов. Если вы хотите предоставить реализацию, которая просто отбрасывает данные (аналогично ioutil.Discard ), то реализация не использует (не нужно использовать) свой аргумент:

type DiscardWriter struct{}

func (DiscardWriter) Write([]byte) error { return nil }

И это все: мы не используем приемник, мы не используем этот аргумент. Оба могут быть безымянными. И реализация делает именно то, что ему нужно.

Выполняя это (используя неназванные параметры), также документы , что значение не используется / не упоминается.

Другое причиной может быть обеспечение совместимости вперед . Если вы отпустите библиотеку, вы не сможете изменить или расширить список параметров без нарушения обратной совместимости (и в Go нет перегрузки функций: если вы хотите 2 варианта с разными параметрами, их имена также должны быть разными). Таким образом, вы можете заранее объявить экспортированную функцию или метод с дополнительными параметрами, но поскольку вы еще не используете их, вы можете оставить их неназванными. Пример этого подробно описан в этом ответе: Почему Go разрешает компиляцию неиспользуемых функциональных параметров?

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

Простой веб-сервер, который отвечает текстом "Hello" для всех запросов:

http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
    io.WriteString(w, "Hello")
})
panic(http.ListenAndServe(":8080", nil))

Функция обработчика, отправляющая обратно текст "Hello", использует автоответчик w, но не структуру запроса, поэтому в качестве имени используется пустой идентификатор.

Другой связанный с этим вопрос:

Почему мы должны объявлять имя переменной при добавлении метода в структуру в Golang?

Также несколько связано, но в отношении использования / naming возвращаемые значения:

Вернуть карту, как «ok» в Golang, при нормальных функциях

И в отношении получения имени метода / функции:

Имена параметров метода метода в Golang

13
ответ дан icza 19 August 2018 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: