声明的变量,不在条件语句中使用

时间:2016-07-03 23:51:50

标签: go scope

我在条件语句之外声明了一些变量(offsetIlimitI)。在条件语句中,我试图为它们分配值,然后在条件语句之后将这些值用于查询。

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 {...}

我不打算在limitI语句的范围内重新声明else变量,但我需要使用:=运算符来声明新的err变量。

我唯一能想到的是分别声明另一个err变量,所以我可以使用常规赋值语句:

} else {

    var err error    // New

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

我希望能够在不必声明其他错误变量的情况下执行此操作。

2 个答案:

答案 0 :(得分:1)

额外的limitI很尴尬,但这是解决这种情况的常用方法。 The spec on scoping说(强调我的):

  

在函数内声明的常量或变量标识符的范围从ConstSpec或VarSpec(短变量声明的ShortVarDecl)的末尾开始,并在最里面的包含块的末尾结束。 / p>

因此,在您的情况下,该短变量声明声明了一个不同的 err作用于"最里面的包含块。"因为它只是"生活"直到下一个结束括号,它才被使用。

在您的具体情况下,选项可能是在if / else之外声明=,因为它在两个内部范围中都使用了,因此您可以使用:=而不是{ {1}}这些函数返回error个。然后没有"内部limitI"声明,你没有未使用的变量问题。

"遮蔽"像这样的情况也会产生意外的行为而不是错误。 go vet -shadow tries to detect "[v]ariables that may have been unintentionally shadowed"和不同但相关的gordonklaus/ineffasign概括了"未使用的变量"检查以检测无用的分配,即使它们不是声明。

答案 1 :(得分:0)

  

我唯一想出的就是分别声明另一个err变量

正在对未来的Go 2(2019年或2020年)进行研究。
参见“ Error Handling — Problem Overview”(Russ Cox,2018年8月27日)

可能提出的新语法可以避免重新声明err:

示例:

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
}

请注意,go vet -shadow不再可用since Go 1.12(2019年2月):

  

-shadow不再提供实验性go vet选项。
  现在可以使用

检查变量阴影
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)