声明且未使用-如何在IF语句中更新变量

I am trying to setup a bool variable with a default value and update it based on a condition, in Go Lang. The func foo compiles, But the function bar doesn't compile and gives an error "f declared and not used"

There is a related answer - which doesn't explain the next question

What is the correct pattern for this(bar function) in Go?

Here is the code:

package main

import (
"fmt"
"strconv"
)

func foo(m map[string]string) bool {
    f := false

if _, exists := m["READWRITE"]; exists {
    fmt.Println("Before Updating f : ", f)
    f, _ = strconv.ParseBool(m["READWRITE"])
    //if err != nil {
    //  panic(err)
    //}
}

fmt.Println("After Updating f : ", f)

return f
}

func bar(m map[string]string) bool {
    f := false

    if _, exists := m["READWRITE"]; exists {
         fmt.Println("Before Updating f : ", f)
         f, err := strconv.ParseBool(m["READWRITE"]) // error on this line "f declared and not used"
        if err != nil {
            panic(err)
        }
    }

    fmt.Println("After Updating f : ", f)

    return f
}

func main() {
    m := map[string]string{"READWRITE": "true"}

    fmt.Println(foo(m))
    fmt.Println(bar(m))
}

gives an error "f declared and not used"

f in your sample is a newly-declared variable. Its scope lies within the if block, and is different from the one originally declared at the start of your main().

Here is a sample commented code that may help clarify (also available as a runnable Go Playground snippet):

package main

import (
    "fmt"
)

func main() {
    food := "burger"                 // (1) variable 'food' is declared
    fmt.Println("food is", food)     // OUTPUT: "burger"

    if true {
        food := "fries"              // (2) a new 'food' variable is a declared here. it shadows the one in (1)
        fmt.Println("food is", food) // this accesses the 'food' var from (2). OUTPUT: "fries"
    }

    fmt.Println("food is", food)     // this accesses the variable from (1). OUTPUT: "burger"
}

Hope this helps clarify. Cheers,

From go-lang specification

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new

The if starts a new block and hence this line is declaring a new variable with name f.

On the other hand = operator is an assignment operator and hence the value from the previous scope is modified.

If you want to re-use the same variable, you can declare err explicitly.

 var err error 
 f, err = strconv.ParseBool(m["READWRITE"])
 if err != nil {
    panic(err)
 }

Context on why I am calling this out: For a person moving to Go from quite a few other languages, this would be an oddity.

I am adding this here - just to demonstrate that it might be useful to use a temp variable explicitly. barNotCorrectYet, has f being updated with the "default false" return from strconv.ParseBool (which would have changed the preset value). So, on cases where we want to ignore bad inputs, it will be useful to assign output to a temp variable, check if no errors were returned and then update the preset value barCorrectHandlingOfTempVariable.

func barNotCorrectYet(m map[string]string) bool {
f := true // preset value of variable

if _, exists := m["READWRITE"]; exists {
    var err error

    fmt.Println("Before Updating f : ", f)

    f, err = strconv.ParseBool(m["READWRITE"])
    if err != nil {
        // If error, wrong value got updated on f.. and erased preset value
    }   

}

fmt.Println("[Value could be wrong] After Updating f : ", f)

return f
}

func barCorrectHandlingOfTempVariable(m map[string]string) bool {
f := true // preset value of variable

if _, exists := m["READWRITE"]; exists {

    fmt.Println("Before Updating f : ", f)

    temp, err := strconv.ParseBool(m["READWRITE"])
    if err != nil { // Update only when there are no errors to not affect preset value
        f = temp
    }       
}

fmt.Println("After Updating f : ", f)

return f
}