#go
#Вперед
Вопрос:
duration := 1 * time.Hour
if true {
duration, err := time.ParseDuration("5s")
_ = duration // if I don't have this, it gives me a duration declared not used error
if err != nil {
log.Fatal(err)
}
}
fmt.Println(duration) // prints 1 hour
Я думаю, проблема здесь в том, что duration снова объявляется как local var в инструкции if. Есть ли синтаксически хороший способ решить эту проблему?
Комментарии:
Ответ №1:
Действительно, вы снова объявляете duration
переменную в if
блоке. Мой способ сделать это — объявить err
перед if
блоком (обычно в начале функции, поскольку error
переменная практически всегда необходима …).
var err error
duration := 1 * time.Hour
if true {
duration, err = time.ParseDuration("5s")
if err != nil {
log.Fatal(err)
}
}
Комментарии:
1. Да, я пробовал это, это сработало. Но оператор if не должен быть замыканием, подобным вызову функции, я чувствую, что это должна быть ошибка, которую golang должен исправить сам?
2. Это не ошибка, такое поведение соответствует спецификациям. Об этом уже сообщалось как о проблеме Golang, но она была отклонена по этой причине: code.google.com/p/go/issues/detail?id=5990
3. Болен! Я думаю, они просто хотят быть очень строгими к этому языку. Это действительно полезно 🙂
Ответ №2:
Вопрос в том, хотите ли вы, чтобы она duration
перезаписывалась, когда time.ParseDuration
возвращает ошибку, или нет. Если нет, то я бы написал
duration := 1 * time.Hour
if true {
d, err := time.ParseDuration("5s")
if err != nil {
log.Fatal(err)
} else {
duration = d
}
}
Если вас не волнует старое значение в случае ошибки, ответ @ julienc так же хорош.
Комментарии:
1. То есть каждый раз, когда мне нужно объявлять новый var? Я чувствую, что это должно быть довольно распространенным логическим вариантом использования в любом коде…
Ответ №3:
Go — это блочно-структурированный язык программирования. Как правило, переменные объявляются с минимальной областью видимости.
Переменная duration
объявляется и используется во внешней ( func
) области видимости, а также устанавливается во внутренней ( if
) области видимости. err
Переменная объявляется и используется во внутренней ( if
) области видимости. Например,
package main
import (
"fmt"
"log"
"time"
)
func main() {
duration := 1 * time.Hour
if true {
var err error
duration, err = time.ParseDuration("5s")
if err != nil {
log.Fatal(err)
}
}
fmt.Println(duration)
}
Вывод:
5s
Использование короткого объявления переменной не сработает. Краткое объявление переменной может повторно объявлять только переменные, которые первоначально были объявлены ранее в том же блоке.
func main() {
duration := 1 * time.Hour
if true {
duration, err := time.ParseDuration("5s")
if err != nil {
log.Fatal(err)
}
}
fmt.Println(duration)
}
Ошибка:
duration declared and not used
Переменная duration
объявляется и используется во внешней ( func
) области видимости. Она также объявлена (не объявлена повторно) и установлена, но не используется, во внутренней ( if
) области видимости.
Ссылки:
Область действия блока (информатика)
Спецификация языка программирования Go
Спецификация языка программирования Go: блокирует
Спецификация языка программирования Go: объявления и область видимости
Спецификация языка программирования Go: короткие объявления переменных