If I understand correctly, your primary complaint seems to be that you can shadow an imported package with a variable. Eg in the example below, fmt
is a package but then gets shadowed when we create a variable named fmt
and from that point onwards inside of main()
it doesn’t reference the package.
package main
import (
"fmt"
)
func main() {
fmt := fmt.Println
fmt("hi")
}
Playground link: https://play.golang.org/p/QduMG8JnLV8
I understand how this might feel confusing, which is why most developers tend to avoid doing this. As you said, it can lead to confusion.
When this DOES happen, it tends to be very intentional and done because package level functions might be more useful if we had more context of some sort. For instance, https://github.com/matryer/is does this because you really don’t tend to use the package functions and instead want something that wraps the individual testing.T
from each test case.
This isn’t limited to just packages either. For instance, you can shadow regular old variables in Go:
package main
import (
"fmt"
)
func main() {
x := 14
fmt.Println(x)
for i := 0; i < 2; i++ {
x := i * 2
fmt.Println("in for loop:", x)
}
fmt.Println("out of for loop:", x) // unchanged!
// You can even do this with just curly braces and assign to the original x
{
x := x
x *= 3
fmt.Println("in curly:", x)
}
fmt.Println("out of curly:", x) // unchanged!
}
Playground link: https://play.golang.org/p/DDTggNumuiN
At one point you make the argument that Java doesn’t have this “unclearness”, but it actually does in many ways. For instance, all of this shadowing of variables I mentioned is indeed possible in Java and is illustrated here: https://www.dummies.com/programming/java/shadowed-classes-or-variables-in-java/ (this article may suck, as I’m not up-to-date with what Java articles are good).
Again, it is discouraged from being used too much because, as you pointed out, it can cause confusion for future developers, but Java DOES permit it.
The only thing really unique to Go is that you can shadow a package name with a new variable, but I’m not really sure this is such an awful thing. As we saw with the is
package, it can be very helpful in designing some packages where you need additional context and then once you shadow the package name you never use it again anyway. But, as with all things, it could indeed be abused and lead to super confusing code so you should be cautious with how you use it.
As to your last comment about the difference between {}
and ()
- these both do very different things, and it sounds like you just need to learn how each one works in Go. Yes, it is different from some other languages. Yes, that might lead to confusion at first. But what is the point of creating another language identical to Java or some other language? Go tried a different approach and both myself and many others have come to prefer it over time.