为什么这个布尔值在Go中没有被注册?

huangapple go评论141阅读模式
英文:

Why wasn't this boolean value being registered in Go?

问题

我开始学习Go语言,遇到了一个奇怪的错误,并且找到了一个更奇怪的解决方法,这个问题是在HackerRank问题上遇到的:

func countingValleys(steps int32, path string) int32 {
    // 在这里编写你的代码
    var level int32 = 0
    var valleys int32 = 0
    // 下面的声明导致了初始错误
    insideValley := false

    for _, char := range path {
        fmt.Println(insideValley)
        if string(char) == "U" {
            if level == -1 {
            insideValley = false
                valleys += 1
            }
            level += 1
        } else if string(char) == "D"{
           if level == 0 {
            insideValley = true
            }
             level -= 1
        }
    }
    return valleys
}

编译器报错说insideValley被声明但未使用,无论是在HackerRank还是Go Playground上都是如此。我在for循环内部立即添加了fmt.Println调用进行调试,怀疑是作用域错误,然后错误消失了,并且我的代码通过了所有的测试,这让我想知道:

  • 为什么一开始会出现这个错误?我目前对Go语言中变量作用域的理解是,在函数中声明的变量将在函数内的所有代码块中可用。

  • 为什么添加了fmt.Println这个变量的语句后错误就消失了?根据我的理解,如果只能嵌套X个代码块,那么在外部代码块中的变量将会超出作用域,修复这个错误的唯一方法应该涉及指针。

英文:

I've begun learning Go, and I ran into a strange bug, and an even stranger fix for it working on a HackerRack problem:

func countingValleys(steps int32, path string) int32 {
    // Write your code here
    var level int32 = 0
    var valleys int32 = 0
    // The below declaration was throwing the initial error
    insideValley := false

    for _, char := range path {
        fmt.Println(insideValley)
        if string(char) == "U" {
            if level == -1 {
            insideValley = false
                valleys += 1
            }
            level += 1
        } else if string(char) == "D"{
           if level == 0 {
            insideValley = true
            }
             level -= 1
        }
    }
    return valleys
}

The compiler was complaining that insideValley is declared by not used, both on HR and the Go playground. I added the fmt.Println call immediately inside of the for loop to debug, suspecting it to be a scope error, and the error went away AND my code passed all tests for the challenge, leaving me wondering:

  • Why was the error being thrown in the first place? My current understanding of variable scope in Go is that when declared in a function like this, it will be available to all blocks contained within the function.

  • Why did adding the fmt.Println of that var fix the error? I would have assumed with my current understanding that IF you can only nest X amount of blocks before variables in enclosing blocks become out of scope, the only fix for it would involve pointers.

答案1

得分: 6

所以我们在这里有一个实际上正确的答案,问题在于你写入了布尔值,但从未读取它。如果没有Println(),它不会在任何依赖于其值的条件或其他表达式中使用,因此对它的赋值不会影响程序流程。你可以删除所有赋值给insideValley的行,程序的行为与现在完全相同(当然,除了Println(),这就是为什么添加它可以“修复”问题的原因)。

Go语言专门设计了标记这种无用代码的功能,这些代码对程序流程没有任何影响,会被编译器报错(在大多数情况下是这样的,未使用的全局变量和未使用的函数是一些例外情况)。只需添加使用该布尔值的代码(例如基于其值的条件语句),就不会再收到“变量未使用”的错误。

正如Vishwa Ratna的答案中所指出的,在每个逻辑路径中都不需要使用变量。它们只需要在至少一个逻辑路径中被使用(即从中读取)。

英文:

So we have an actually correct answer here, the issue is that you're writing to the boolean but never reading from it. Without the Println(), it's not used in a conditional or any other expression anywhere that depends on its value, so the assignments to it don't affect the program flow. You could remove all of the lines assigning values to insideValley and the program would act no differently than it does right now (excepting the Println(), of course, which is why adding that "fixed" the issue).

Go is specifically designed to flag "junk" code like that, that adds nothing to the program flow, as a compiler error (well, in most cases. Unused globals and unused functions are some exceptions to that). Simply add in whatever is supposed to be using that boolean's value (such as a conditional based on its value), and you'll stop getting the "variable unused" error.

And as noted in the comments of Vishwa Ratna's answer, vars do not have to be used in every logical pathway. They only need to be used (ie. read from) in at least one logical pathway.

huangapple
  • 本文由 发表于 2021年6月12日 09:21:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/67944883.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定