My understanding is that go fmt is supposed to produce code that is readable and consistently formatted. However I'm not finding this to be the case.
I typed in the commented code and go fmt returned the uncommented code. Why did it collapse 0.5*(y3-y0)
, but not 0.5 * (y2 - y0)
? How is that consistent? And, IMO, the return line with nearly every space collapsed out is a readability disaster.
Is the inconsistency a bug? Is there a way to get go fmt to leave some lines (like the return line) alone?
func cubicInterpolate(x, y0, y1, y2, y3 float64) float64 {
// 4-point, 3rd-order Hermite (x-form)
// c0 := y1
// c1 := 0.5 * (y2 - y0)
// c2 := y0 - 2.5 * y1 + 2. * y2 - 0.5 * y3
// c3 := 1.5 * (y1 - y2) + 0.5 * (y3 - y0)
//
// return ((c3 * x + c2) * x + c1) * x + c0
c0 := y1
c1 := 0.5 * (y2 - y0)
c2 := y0 - 2.5*y1 + 2.*y2 - 0.5*y3
c3 := 1.5*(y1-y2) + 0.5*(y3-y0)
return ((c3*x+c2)*x+c1)*x + c0
}
This is documented in the go source code; the aim is to make operator precedence clear. For example in your example y0 - 2.5*y1 + 2.*y2 - 0.5*y3
the multiplications will be performed before the subtractions and the format chosen makes this clear at a glance.
In answer to your question; this is not a bug; indeed quite a bit of effort was put into the formatting. You cannot exclude a line from formatting; this is by design, as mentioned in the FAQ, the aim is to enforce layont rules:
gofmt is a pretty-printer whose purpose is to enforce layout rules; it replaces the usual compendium of do's and don'ts that allows interpretation.
Below is a formatted extract from go/printer/nodes.go that details the formatting rules:
Format the binary expression: decide the cutoff and then format. Let's call depth == 1 Normal mode, and depth > 1 Compact mode. (Algorithm suggestion by Russ Cox.)
The precedences are:
5 * / % << >> & &^ 4 + - | ^ 3 == != < <= > >= 2 && 1 ||
The only decision is whether there will be spaces around levels 4 and 5. There are never spaces at level 6 (unary), and always spaces at levels 3 and below.
To choose the cutoff, look at the whole expression but excluding primary expressions (function calls, parenthesized exprs), and apply these rules:
- If there is a binary operator with a right side unary operand that would clash without a space, the cutoff must be (in order):
/* 6 && 6 &^ 6 ++ 5 -- 5
(Comparison operators always have spaces around them.)
If there is a mix of level 5 and level 4 operators, then the cutoff is 5 (use spaces to distinguish precedence) in Normal mode and 4 (never use spaces) in Compact mode.
If there are no level 4 operators or no level 5 operators, then the cutoff is 6 (always use spaces) in Normal mode and 4 (never use spaces) in Compact mode.