Note that in languages that don't mandate the open brace be on the same line as the code that opens the new scope, this can happen during a merge:
// original code
if (foo)
{
printf("foo is true!")
}
// after the merge
if (foo)
someFunction()
{
printf("foo is true!")
}
Now this code will always print "foo is true!". Because Go requires the open brace to be on the same line as the if, this type of bug is impossible in Go.Gofmt will never change the behavior of your code, so you don't have to "worry" about what it will do. It only makes cosmetic changes to code, never functional.
As willvarfar points out, I feel Rob Pike is being disingenous when he talks about this. Golang uses less significant whitespace than Python, but it exists, the difference is in degree. If he prefers to minimize the impact of whitespace in Go code, that's fine. But why does he have to talk about it as an error or misjudgment?
If significant whitespace is such a bad idea, why do exist keywords that require whitespace around them in Go (package, func, type, etc.? Why can't I use whitespace in names in Go? This didn't happen in good old FORTRAN ;)
func (){
a := 1
return a
}
while ugly, this still compiles just fine. It would compile just as fine if you randomly flipped some of the spaces into tabs.Whitespace is not significant in Go.
The difference between significant whitespace and requiring "some" whitespace is that if you did something like that in Python, you could end up with a program with different logic depending on which spaces were flipped to tabs. This is why mixing spaces and tabs in Python is verboten.
In go, you can mix spaces and tabs all you want, wherever you want in your code and it will never ever change the logic of your code, period. (obvious exceptions for changes inside string literals)
So, it's not really a matter of degrees, and Python's method is completely broken if you ever mix tabs and spaces, which as Rob Pike points out, are completely indistinguishable in the default views of most editors.
def my_func ( ) :
a = 1
return a
It will run without a problem because only leading space is significant. Then you can mix tabs and spaces, add the space you want, blank lines, etc.The Python coding style guideline (PEP 8) is very specific in that it recommends the use of 4 leading spaces per level. You can use a very simple program with regular expressions to solve any problem you could have in the mix of tabs and spaces in your files.
Now, try this example in FORTRAN.
parameter(x=2)
print*,"The parameter is ",x
Why can't I use commas or parentheses to delimit all the tokens in Go? Why does it insert semicolons without asking? Is such an arbitrary and problematic decision as the significant leading whitespace in Python.Yes, it's just leading spaces that are different in Python, I know. I actually like python, but the space indenting is fragile.
if (a == 1) {
return a }
else { return b }
This won't compile in Go. But whitespace wasn't significant in Go, right? Take out the curly braces, add a couple of colons and this will run without a problem in Python.My point is, there isn't such a big difference between Go and Python. Significant whitespace doesn't mean "whatever Python does differently", it means that whitespace is syntactically meaningful. Any whitespace in any part of your program has the potential for changing the meaning of it. If it does, then it's significant.
It's trivial to make a text editor show tabs and insert spaces even if you press tab. It's trivial to make a program that will switch leading tabs for the number of spaces that you want from a file. I don't say it's trouble-free, but it isn't such a big issue; and automatic semicolon insertion isn't trouble-free either, as you can see. You won't have problems with any of them if you take a little care.
In Python, leading whitespace and newlines are syntactically significant. In Go, newlines are in many cases syntactically significant. In both of them space around many keywords is significant (try to write packagemain in Go, see how it goes), and you can't put whitespace in names.
def my_func():a=1;return a;
Try it, it works!