Var vs: = in Go

В примере веб-сервера Go: http://golang.org/doc/effective_go.html#web_server

Следующая строка кода работает

var addr = flag.String("addr", ":1718", "http service address")

но изменив его на

addr := flag.String("addr", ":1718", "http service address")

- ошибка компиляции. Зачем? Имеет ли это какое-либо отношение к лицу, что тип возврата функции *string вместо string? Какая разница?

UPDATE: Спасибо, что указали, что := не разрешено на верхнем уровне. Любая идея, почему эта несогласованность находится в спецификации? Я не вижу причин, чтобы поведение отличалось внутри блока.

Ответ 1

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

От spec:

В отличие от обычных объявлений переменных краткое объявление переменной может обновлять переменные, если они были изначально объявлены ранее в том же блоке с одним и тем же типом, и по крайней мере одна из непустых переменных является новой. Как следствие, переопределение может появляться только в короткой декларации с несколькими переменными. В Redeclaration не вводится новая переменная; он просто назначает новое значение оригиналу.

field1, offset := nextField(str, 0)
field2, offset := nextField(str, offset)  // redeclares offset
a, a := 1, 2                              // illegal: double declaration of a or no new variable if a was declared elsewhere

Итак, я бы сказал, что оператор := не является чистым объявлением, но более похож на объявление и назначение. Не допускается повторная декларация в верхнем слое, поэтому ни краткие декларации.

Другой причиной этого может быть простота синтаксиса. В Go все формы верхнего уровня начинаются с type, var или func. Короткие объявления там разрушат всю симпатичность.

Ответ 2

В Go, назначения переменных верхнего уровня должны иметь префикс с ключевым словом var. Опускание ключевого слова var разрешено только внутри блоков.

package main

var toplevel = "Hello world"         // var keyword is required

func F() {
        withinBlock := "Hello world" // var keyword is not required
}

Ответ 3

Спецификация языка программирования Go

Объявления коротких переменных

Объявление короткой переменной использует синтаксис:

ShortVarDecl = IdentifierList ":=" ExpressionList .

Короткие объявления переменных могут отображаться только внутри функций.

В вашем примере изменение оператора объявления переменной вне тела функции

var addr = flag.String("addr", ":1718", "http service address")

в короткий оператор объявления переменной за пределами тела функции

addr := flag.String("addr", ":1718", "http service address")

не удается с ошибкой компилятора "выражение без декларации вне тела функции".