Go变量不会在if语句中被覆盖

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

I guess the issue here is that duration is declared again as local var within if statement. Is there a syntactically good way to resolve this?

Indeed, you declare the duration variable again in the if block. My way to do this is to declare err before the if block (usually at the beginning of the function, as an error variable is pretty much always needed...).

var err error
duration := 1 * time.Hour
if true {
    duration, err = time.ParseDuration("5s")
    if err != nil {
        log.Fatal(err)
    }
}

The question is whether you want duration to be overwritten when time.ParseDuration returns an error or not. If not, then I would write

duration := 1 * time.Hour
if true {
    d, err := time.ParseDuration("5s")
    if err != nil {
        log.Fatal(err)
    } else {
        duration = d
    }
}

If you don't care about the old value in the case of an error, @julienc's answer is just as good.

Go is a block-structured programming language. Generally, variables are declared with minimal scope.

The variable duration is declared and used in the outer (func) scope and is also set in the inner (if) scope. The err variable is declared and used in the inner (if) scope. For example,

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)
}

Output:

5s

Using a short variable declaration won't work. A short variable declaration can only redeclare variables that are originally declared earlier in the same block.

func main() {
    duration := 1 * time.Hour
    if true {
        duration, err := time.ParseDuration("5s")
        if err != nil {
            log.Fatal(err)
        }
    }
    fmt.Println(duration)
}

Error:

duration declared and not used

The variable duration is declared and used in the outer (func) scope. It is also declared (not redeclared) and set, but not used, in the inner (if) scope.

References:

Block (programming)

Block scope (computer science)

The Go Programming Language Specification

The Go Programming Language Specification: Blocks

The Go Programming Language Specification: Declarations and scope

The Go Programming Language Specification: Short variable declarations