Ответ 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?
Также несколько связано, но относительно использования/именования возвращаемых значений:
Вернуть карту, как & # 39; ok & # 39; в Голанге о нормальных функциях
А что касается получения имен параметров метода/функции: