简体   繁体   中英

Go's gofmt and diff/VCS issues?

I've got a question about Go's gofmt tool, which formats automatically the output of programs according to the official Go specs (for example you cannot argue about where brackets should go in Go, because that's apparently fixed by the specs).

On the following page:

http://golang.org/doc/effective_go.html

under the "Formatting" paragraph, it is written that:

As an example, there's no need to spend time lining up the comments on the fields of a structure. Gofmt will do that for you. Given the declaration

type T struct {
    name string // name of the object
    value int // its value
}

gofmt will line up the columns:

type T struct {
    name    string // name of the object
    value   int    // its value
}

However I don't understand how this could possibly play nice with diff and VCSes.

For example, if I had a new line:

confuzzabler int // doo doo be doo

and run a diff , I should get this:

2d1
<     confuzzabler int // doo doo be doo
7d5
< 

And life would be all good: the diff shows the only line that got changed.

However if I re-run the gofmt I got this:

type T struct {
    confuzzabler int    // doo doo be doo
    name         string // name of the object
    value        int    // its value
}

And now I re-run diff and I get this:

2,4c2,3
<     confuzzabler int    // doo doo be doo
<     name         string // name of the object
<     value        int    // its value
---
>     name    string // name of the object
>     value   int    // its value
7d5
< 

Which is a highly confusing and misleading diff output because only one line changed.

How do you deal with this as a Go developer?

$ diff --help|grep -i white
  -b  --ignore-space-change  Ignore changes in the amount of white space.
  -w  --ignore-all-space  Ignore all white space.

As to issues with VCS, if you were formatting the code yourself following some established convention (let's assume here this convention is what gofmt follows) you'd have manually reformatted the whitespace in that code block exactly the way gofmt did, and this change would have been counted by any VCS as a change. So I don't see any problem with semantics in this case, really. If you instead care about diffing tools provided by VCSes you should probably look whether they do support ignoring whitespace changes as the GNU diff mentioned above does. FWIW git diff does support this with the same -b command line option.

Your Go-based project standards should dictate something like:

Before any Go code is committed to the VCS, it is formatted with gofmt . This is the only acceptable format.

Then there is no argument; if the code passes through gofmt unchanged, all is well. If it changes when passed through gofmt , then use the output from gofmt . What you do while editing is up to you (subject to the other coding standards), but this is a requirement for any code checked into your VCS.

If this really bothers you, do two checkins.

The first check in adds confuzzabler . A reasonable comment is "Adding new variable to T". Your diff will be isolated to the code you have actually changed.

Then, perform gofmt.

The second commit is just formatting changes and a reasonable commit msg would be "gofmt". The diff here will be only code that gofmt has changed.

Comparing the diff output, it's obvious what happened. It's neither confusing nor misleading.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM