Variable declared and not used in conditional statement

Deadly 提交于 2021-02-07 08:43:52

问题


I declare some variables (offsetI and limitI) outside of a conditional statement. Inside the conditional statement I am trying to assign them values, then use those values for a query after the conditional statement.

var (
    number, size, offset, limit string
    offsetI, limitI             uint64
)

// Get the string values for number, size, offset, and limit
// ...

if size != "" {

    // Parse the number value
    numberI, err := strconv.ParseUint(number, 10, 64)
    if err != nil {...}

    // Parse the size value
    limitI, err = strconv.ParseUint(size, 10, 64)
    if err != nil {...}

    // Calculate the offset
    offsetI = numberI * limitI

} else {

    // Parse the limit value
    limitI, err := strconv.ParseUint(limit, 10, 64)         // limitI declared and not used
    if err != nil {...}

    // Parse the offset value
    offsetI, err = strconv.ParseUint(offset, 10, 64)
    if err != nil {...}
}

// Make the query using offsetI and limitI
result, err := s.GetAllPaginated(offsetI, limitI)
if err != nil {...}

I am not intending to re-declare the limitI variable in the scope of the else statement, but I need to use the := operator for declaring a new err variable.

The only thing I could come up with was to separately declare another err variable, so I could use a regular assignment statement:

} else {

    var err error    // New

    // Regular assignment statement now
    limitI, err = strconv.ParseUint(limit, 10, 64)
    if err != nil {...}

I would like to be able to do this without having to declare an additional error variable.


回答1:


The extra var error is awkward, but it's a common way to address this situation. The spec on scoping says (emphasis mine):

The scope of a constant or variable identifier declared inside a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl for short variable declarations) and ends at the end of the innermost containing block.

So in your case, that short variable declaration is declaring a different limitI scoped to the "innermost containing block." Since it only "lives" until the next closing brace, it isn't used.

In your specific case, an option might be to declare err outside the if/else, since it's used in both inner scopes, so you can use use = instead of := with those functions returning errors. Then there's no "inner limitI" declared and you have no unused variable issue.

"Shadowing" situations like this can also produce unexpected behavior rather than an error. go vet -shadow tries to detect "[v]ariables that may have been unintentionally shadowed" and, different but related, gordonklaus/ineffasign generalizes the "unused variable" check to detect useless assignments even if they weren't declarations.




回答2:


The only thing I could come up with was to separately declare another err variable

This is being studied in the context of a future Go 2 (2019? 2020).
See "Error Handling — Problem Overview" (Russ Cox - August 27, 2018)

A possible proposed new syntax would avoid having to redeclare err:

Example:

func CopyFile(src, dst string) error {
    handle err {
        return fmt.Errorf("copy %s %s: %v", src, dst, err)
    }

    r := check os.Open(src)
    defer r.Close()

    w := check os.Create(dst)
    handle err {
        w.Close()
        os.Remove(dst) // (only if a check fails)
    }

    check io.Copy(w, r)
    check w.Close()
    return nil
}

Note that go vet -shadow is no longer available since Go 1.12 (February 2019):

The experimental -shadow option is no longer available with go vet.
Checking for variable shadowing may now be done using

go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)


来源:https://stackoverflow.com/questions/38175345/variable-declared-and-not-used-in-conditional-statement

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!