Почему существует два способа объявления переменных в Go, какова разница и какие использовать?

В соответствии с ссылкой Go есть два способа объявления переменной

Variable_declarations (в формате var count = 0 или var count int)
и
Short_variable_declarations (в формате count := 0)

Мне было очень сложно определить, какой из них использовать.

Различия, которые я знаю (до сих пор), таковы:

  • Я могу использовать только формат count := 0, когда в рамках функции.
  • count := 0 может быть обновлен в краткой декларации с несколькими переменными.

Но они ведут себя одинаково, насколько я знаю. И в ссылке также говорит:

Это (путь count:=0) сокращенное для объявления регулярной переменной с выражениями инициализатора, но без типов

Мое недоумение:

  • Если кто-то является просто сокращенным способом другого, почему они ведут себя по-другому?
  • В чем озабоченность автора Go делает два способа объявления переменной (почему они не объединены в один путь)? Просто чтобы смутить нас?
  • Есть ли какой-либо другой аспект, который я должен держать в своих глазах при использовании, если я попаду в яму?

Ответы

Ответ 1

Переменные объявления дают понять, что переменные объявлены. Требуется ключевое слово var, оно короткое и выражает то, что делается (на уровне файла все, кроме комментариев, должно начинаться с ключевого слова, например package, import, const, type, var, func). Как и любой другой блок, объявления переменных могут быть сгруппированы следующим образом:

var (
    count int
    sum float64
)

Вы не можете сделать это с помощью коротких объявлений переменных. Также вы можете использовать объявления Variable без указания начального значения, и в этом случае каждая переменная будет иметь нулевое значение своего типа. Объявление Short variable не позволяет этого, вы должны указать начальное значение.

Один из принципов руководства Go заключается в том, чтобы сделать синтаксис чистым. Требуется много операторов или удобно, что они позволяют объявлять локальные переменные, которые будут доступны только в теле оператора, например for, if, switch и т.д. Чтобы сделать синтаксис более чистым и коротким, объявление короткой переменной оправдано в этих случаях, и недвусмысленно, что они делают.

for idx, value := range array {
    // Do something with index and value
}

if num := runtime.NumCPU(); num > 1 {
    fmt.Println("Multicore CPU, cores:", num)
}

Другое отличие: Редекларация

Цитата из спецификации языка:

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

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

var name = "myfile.txt"

fi, err := os.Stat(name) // fi and err both first declared
if err != nil {
    log.Fatal(err)
}
fmt.Println(name, fi.Size(), "bytes")

data, err := ioutil.ReadFile(name) // data is new but err already exists
                                   // so just a new value is assigned to err
if err != nil {
    log.Fatal(err)
}

// Do something with data