Deprecate goimports in favor of gofmt + the extra functionality in goimports?

2,188 views
Skip to first unread message

Florin Patan

unread,
Feb 13, 2015, 7:08:09 PM2/13/15
to golan...@googlegroups.com
Hi,


I'd like to know if it would be possible to deprecate goimports in favor of including the extra functionality into gofmt.
The reason I'm asking this is because I'm seeing many projects using either one or the other and, in my opinion, it contradicts with the whole idea behind using gofmt to have a single way to format the go code.

Thank you.

cm...@golang.org

unread,
Feb 13, 2015, 7:19:08 PM2/13/15
to golan...@googlegroups.com
Why would a project use only goimports and not gofmt? gofmt is still a single way to format Go code, goimports just helps you find missing imports/eliminate unused imports. There are plenty of other tools that modify Go source code and they should be used when desired. Whatever they generate should still be gofmt regardlessly.

DisposaBoy

unread,
Feb 14, 2015, 1:57:08 AM2/14/15
to golan...@googlegroups.com
The description here http://godoc.org/golang.org/x/tools/cmd/goimports says it's a drop-in replacement for gofmt. I don't use it myself, but I have tested it in the past and it did fmt the code, so there's no reason to run gofmt again that's still the case.

Tarrant Rollins

unread,
Feb 14, 2015, 4:00:03 AM2/14/15
to golan...@googlegroups.com
`goimports` uses the same formatter (go/format) as gofmt does. See
https://github.com/golang/tools/blob/master/imports/imports.go#L94

-T
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Florin Patan

unread,
Feb 14, 2015, 5:54:13 AM2/14/15
to golan...@googlegroups.com
I'm sorry I wasn't so clear.

Take this example http://play.golang.org/p/5SVuqozBDE and run either Format or Format + Imports.
You'll see the differences between the two of them and why I think the extra functionality in goimports should be added to the gofmt.

It basically comes down to grouping the imports into sections of internal packages and external ones.

Thank you.

Rob Pike

unread,
Feb 14, 2015, 10:24:23 AM2/14/15
to Florin Patan, golan...@googlegroups.com
They are not equivalent. They both reformat, but goimports also modifies your program and does so with unreliable heuristics. Gofmt does not modify your program.

Goimports is great, and I use it by default, but sometimes gofmt is the one to use and it needs to persist.

-rob

Daniel Eloff

unread,
Feb 14, 2015, 10:36:25 AM2/14/15
to golan...@googlegroups.com, flori...@gmail.com
On Saturday, February 14, 2015 at 10:24:23 AM UTC-5, Rob 'Commander' Pike wrote:
> Goimports is great, and I use it by default, but sometimes gofmt is the one to use and it needs to persist.

I also use goimports by default, it's a great tool. Have you considered making the goimport functionality accessible via a flag to gofmt?

Cheers,
Dan

Florin Patan

unread,
Feb 14, 2015, 10:47:55 AM2/14/15
to golan...@googlegroups.com, flori...@gmail.com
I've considered suggesting introducing a flag instead of the whole functionality directly but then it's the same problem, some will use the flag, some not, which is what I want to avoid to begin with.

Cheers,
Florin

Florin Patan

unread,
Feb 14, 2015, 11:03:57 AM2/14/15
to golan...@googlegroups.com, flori...@gmail.com
I'm sorry if I'm not grasping the full extent of the issue, but like you've said, you are using it by default and it's included in the official playground as well.
Also, for example, there are editors / IDEs who integrate with either one or the other or both, or others that chose (or have to) to replicate the functionality in order to format the source code properly.
So then the question is: what should be done to in order to port the imports functionality over to gofmt in a way that is acceptable to use by default?


Thank you,
Florin

Ian Lance Taylor

unread,
Feb 14, 2015, 11:16:45 AM2/14/15
to Florin Patan, golang-nuts
On Sat, Feb 14, 2015 at 8:03 AM, Florin Patan <flori...@gmail.com> wrote:
>
> I'm sorry if I'm not grasping the full extent of the issue, but like you've
> said, you are using it by default and it's included in the official
> playground as well.
> Also, for example, there are editors / IDEs who integrate with either one or
> the other or both, or others that chose (or have to) to replicate the
> functionality in order to format the source code properly.
> So then the question is: what should be done to in order to port the imports
> functionality over to gofmt in a way that is acceptable to use by default?

Rob already explained. The gofmt program always act the same way on
all systems and never changes your program behaviour in any way. The
goimports program uses heuristics and will in some cases produce
different results on different systems. Also, because goimports
introduces new imports, it can change your program behaviour.

The only way that the imports functionality will be ported to gofmt
would be if it used no heuristics and always produced exactly the same
results no matter what system it is run on, and if it never changed
your program behaviour in any way. But then, of course, it would be
useless.

There needs to be a tool like gofmt that is 100% reliable and
predictable. Adding goimports functionality to gofmt would break
that.

Ian

Florin Patan

unread,
Feb 14, 2015, 2:37:06 PM2/14/15
to golan...@googlegroups.com, flori...@gmail.com
Thank you for your reply. I've understood the problem better now.

How about porting only the formatting functionality, which works the same for most of the code, it's just the imports that are handled differently?
Then goimports would only have the imports functionality to take care of while gofmt would still preserve its properties.


Thank you.

Tamás Gulácsi

unread,
Feb 14, 2015, 3:29:43 PM2/14/15
to golan...@googlegroups.com
Maybe not clear, but
goimports = (imports fixing hand grouping) + gofmt.

So they use the same formatting, just go imports does some magic and grouping (which I like), then calls the same formatting code as gofmt.

Dan Kortschak

unread,
Feb 14, 2015, 3:48:10 PM2/14/15
to Tamás Gulácsi, golan...@googlegroups.com
It would be nice if they didn't disagree on import list ordering and grouping (that is if either goimports didn't force grouping or gofmt did) - purely because of diff polution. This change to gofmt would not break the invariant that gofmt does not change the behaviour of a program.

Jan Mercl

unread,
Feb 14, 2015, 4:35:57 PM2/14/15
to golan...@googlegroups.com
On Sat Feb 14 2015 at 20:37:13 Florin Patan <flori...@gmail.com> wrote:

> How about porting only the formatting functionality, which works the
> same for most of the code, it's just the imports that are handled 
> differently?
>
> Then goimports would only have the imports functionality to take care of 
> while gofmt would still preserve its properties.

Rob mentioned before that the heuristics of goimports are not reliable. If someone can live with that (me not), good luck with goimports.

I realize that goimports probably work flawlessly in, say ~99% of cases. I'm worried "only" about the remaining 1%.

Additionally, I guestimate that the time I spend editing the import list of a file is less than one percent (or maybe one promile) of the time it takes to write it. And the time to write the file is, once again, only a small fraction of the time it takes to develop it. I mean, in no particular order, debugging, profiling, rewriting the algos, cpu & mem optimization, writing tests and documentation. In those later stages the import list changes less frequently, if at all.

I believe that anyone using goimports can easily find a convenient way how to also invoke gofmt afterwards. Automagically, manually, whatever way - just always let gofmt have the final word before publishing code.

IOW, please leave gofmt alone, thanks.

-j

Florin Patan

unread,
Feb 14, 2015, 4:46:25 PM2/14/15
to golan...@googlegroups.com
Hi,

Yes, Rob and Ian mentioned before why the whole functionality for goimports can't be done for gofmt.
I realized after Ians response what him and Rob where saying about goimports changing the code and I agree / fully understand the problem with reliable determining the insert/remove of packages to be imported.
However I'm interested in having the formatting functionality ported to gofmt so that when I'm running goimports on projects that don't use it, I won't generate unneeded / unintentional changes. That's the problem I currently have with having two major tools formatting my code instead of only one (and yes, I know goimports calls gofmt).
I'm sorry that I wasn't as clear as I should have been from the beginning.


Cheers,
Florin

Ian Lance Taylor

unread,
Feb 14, 2015, 5:21:36 PM2/14/15
to Florin Patan, golang-nuts
On Sat, Feb 14, 2015 at 1:46 PM, Florin Patan <flori...@gmail.com> wrote:
>
> Yes, Rob and Ian mentioned before why the whole functionality for goimports
> can't be done for gofmt.
> I realized after Ians response what him and Rob where saying about goimports
> changing the code and I agree / fully understand the problem with reliable
> determining the insert/remove of packages to be imported.
> However I'm interested in having the formatting functionality ported to
> gofmt so that when I'm running goimports on projects that don't use it, I
> won't generate unneeded / unintentional changes. That's the problem I
> currently have with having two major tools formatting my code instead of
> only one (and yes, I know goimports calls gofmt).
> I'm sorry that I wasn't as clear as I should have been from the beginning.

Right now, gofmt and goimports share the same formatting code. I'm
not clear on what you are proposing. I'm not aware of any formatting
functionality in goimports that is not already in gofmt.

Ian

Dan Kortschak

unread,
Feb 14, 2015, 5:45:34 PM2/14/15
to Ian Lance Taylor, Florin Patan, golang-nuts
On Sat, 2015-02-14 at 14:21 -0800, Ian Lance Taylor wrote:
> I'm not aware of any formatting
> functionality in goimports that is not already in gofmt.

Import clustering exists in goimports and not in gofmt.

Ian Lance Taylor

unread,
Feb 14, 2015, 5:48:16 PM2/14/15
to Dan Kortschak, Florin Patan, golang-nuts
The gofmt rule as I understand is simple: imports can be grouped, and
each group of imports is independently sorted lexically.

I don't know quite what goimports does. If the goimports rule can be
written down in a way that is deterministic, perhaps it can be added
to gofmt.

Ian

Sebastien Binet

unread,
Feb 14, 2015, 5:53:19 PM2/14/15
to Ian Lance Taylor, Dan Kortschak, Florin Patan, golang-nuts
goimports clusters imports by:
- first: "stdlib imports",
- then: "3rd-party imports".

so given this initial import list:

import (
"os"
"fmt"
"github.com/user/pkg"
"io"
"golang.org/x/net"
)

goimports will rewrite it as:

import (
"fmt"
"io"
"os"

"github.com/user/pkg"
"golang.org/x/net"
)

re-applying goimports or gofmt will preserve that clustering though,
so there's no hysteresis effect.

-s

Will Norris

unread,
Feb 14, 2015, 5:59:02 PM2/14/15
to Sebastien Binet, Ian Lance Taylor, Dan Kortschak, Florin Patan, golang-nuts
goimports also breaks appengine packages out into a separate import group.  But yes, it should be deterministic.

Rob Pike

unread,
Feb 14, 2015, 6:33:13 PM2/14/15
to Will Norris, Sebastien Binet, Ian Lance Taylor, Dan Kortschak, Florin Patan, golang-nuts
Please let's stop debating the nuances of these "style" guidelines. Gofmt was created to remove the foundations for all such discussion, although we all know that's not sufficient to stop debate. The issue of how to lay out the imports at the top of a file, data there much more for the compiler than for the programmer, is literally meaningless.

Goimports isn't going away. Neither is gofmt. They do different things and are useful in different ways.

Goimports output is gofmt-safe. That's all that matters.

-rob

Dan Kortschak

unread,
Feb 14, 2015, 7:13:05 PM2/14/15
to Rob Pike, Will Norris, Sebastien Binet, Ian Lance Taylor, Florin Patan, golang-nuts
On Sat, 2015-02-14 at 15:32 -0800, Rob Pike wrote:
> Please let's stop debating the nuances of these "style" guidelines.
> Gofmt was created to remove the foundations for all such discussion,
> although we all know that's not sufficient to stop debate. The issue
> of how to lay out the imports at the top of a file, data there much
> more for the compiler than for the programmer, is literally
> meaningless.
>
> Goimports isn't going away. Neither is gofmt. They do different things
> and are useful in different ways.
>
> Goimports output is gofmt-safe. That's all that matters.

This is what I find quite funny about this. goimports adds complexity to
the system (not in the additional functionality that is core to its
operation, but the import clustering). This is an addition that leads to
these kinds of bike-shedding arguments. This would not be an issue
except for the fact that it leads to divergence in import styles within
teams (between those who use goimports and those who do not) that in
turn result in diff noise.



Luna Duclos

unread,
Feb 14, 2015, 7:34:56 PM2/14/15
to Dan Kortschak, Rob Pike, Will Norris, Sebastien Binet, Ian Lance Taylor, Florin Patan, golang-nuts

Daniel Skinner

unread,
Feb 15, 2015, 1:26:23 AM2/15/15
to golan...@googlegroups.com, r...@golang.org, wi...@willnorris.com, seb....@gmail.com, ia...@golang.org, flori...@gmail.com
And the the diff noise in question quite literally all starts with a single line break. I've seen this come up before (goimports vs gofmt) but everything starts with grouping std lib packages and external packages.

goimports does not do this I'm sorry to say, it only appears to do this for the average usage case.

gofmt respects your choices in grouping. goimports sort-of respects this. If you group a single external and single std lib package twice, line break between the two groups, goimports will end up placing every single import on an individual line.

The issue raised is always with backporting goimports functionality to gofmt.

The real issue always seems to be (at least to me) with updating goimports to respect users choice of grouping packages as gofmt does.

Daniel Skinner

unread,
Feb 15, 2015, 1:51:41 AM2/15/15
to golan...@googlegroups.com, wi...@willnorris.com, seb....@gmail.com, ia...@golang.org, dan.ko...@adelaide.edu.au, flori...@gmail.com
> data there much more for the compiler than for the programmer, is literally meaningless

If it was literally meaningless, it wouldn't be there to begin with. The fact that gofmt allows us to group imports willie-nillie is a fault of gofmt.

As far as I know, it's the only fault that I've noted.

I personally prefer a default of 2 groups, stand lib and external (sort of what goimports does by default). Interleaved domain names plus single words in a single block of text makes me cringe when I need to fix an import statement for a duplicate package I'm developing that exists in two locations on my local disk.

Dan Kortschak

unread,
Feb 15, 2015, 4:08:38 AM2/15/15
to Daniel Skinner, golan...@googlegroups.com, r...@golang.org, wi...@willnorris.com, seb....@gmail.com, ia...@golang.org, flori...@gmail.com
Yes, this would be my preferred path.
Reply all
Reply to author
Forward
0 new messages