-1

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.

Vishwa Ratna
  • 5,567
  • 5
  • 33
  • 55
Michael C
  • 339
  • 4
  • 19
  • 2
    Before you were assigning the variable but never reading its value. Adding the `fmt.Println` made meant you actually "used" the variable's value. Also see [this answer](https://stackoverflow.com/a/21744129/4676641) and [this answer](https://stackoverflow.com/a/6178100/4676641). – cam Jun 12 '21 at 01:27
  • 2
    *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* -> Because your insideValley is used only inside If condition, what will happen if the code never traverse the if condition?? insideValley will never be used.... – Vishwa Ratna Jun 12 '21 at 01:28
  • 1
    The answer below is wrong. It has nothing to do with branching (unlike return statement check). It is just about reading the value of that variable. – leaf bebop Jun 12 '21 at 03:49

1 Answers1

6

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.

Kaedys
  • 9,600
  • 1
  • 33
  • 40