goimports: gofmt + fix (add/remove) imports

4,346 views
Skip to first unread message

Brad Fitzpatrick

unread,
Jun 1, 2013, 3:12:32 PM6/1/13
to golang-nuts
I made a thing on a plane:


It's gofmt + it fixes your includes, adding missing ones and removing unreferenced ones.

You can make it your editor's on-save hook, and then not worry about imports.  Now we can keep golang-nuts language complaints solely about generics.

Henrik Johansson

unread,
Jun 1, 2013, 3:19:33 PM6/1/13
to Brad Fitzpatrick, golang-nuts

:D

--
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/groups/opt_out.
 
 

robfig

unread,
Jul 11, 2013, 10:25:26 AM7/11/13
to golan...@googlegroups.com, Brad Fitzpatrick
Love it, thanks! 

Here's a very basic emacs integration that falls back to the usual gofmt if goimports is not available.

(Disclaimer: I do not know elisp -- probably a much better way to do it without copying from go-mode.el wholesale)

=== 

Does it leave spaces between imports for anyone else?  e.g. after removing some imports:

import (
"fmt"

"io/ioutil"

"net/url"
"path"
"regexp"
"strings"
)

which requires further manipulation to remove the extra blank lines.  Assuming that's not intentional, would a pull request be welcome?

Thanks again

Rajiv Kurian

unread,
Jul 11, 2013, 4:10:33 PM7/11/13
to golan...@googlegroups.com
I demand generics!!!

andrey mirtchovski

unread,
Jul 11, 2013, 4:25:12 PM7/11/13
to Rajiv Kurian, golang-nuts
> I demand generics!!!

we have top men working on it right now.

Stan Steel

unread,
Jul 11, 2013, 5:12:28 PM7/11/13
to Brad Fitzpatrick, golang-nuts
This is great!  Thank you for creating this. 

For those who are using GoClipse, I just tested this and it works well.  You can set the path to goimports Under the Go preferences. 
Navigate to Window>Preferences>Go and set the path to goimports in the "Go formatter (gofmt)" path field.  Ctrl+Shift+F activates
the import+fmt function.


David DENG

unread,
Jul 11, 2013, 7:15:47 PM7/11/13
to golan...@googlegroups.com
For adding, I have an simple idea:

The app only uncomments lines of importings. Removing is only commenting.

Then one can safely control the behavial. When one file is done debugging, he can simply remove all comments.

David

Martin Schmidt

unread,
Jul 13, 2013, 7:23:06 AM7/13/13
to golan...@googlegroups.com
Since the code exists now and people will use it. Does something speak heavily against making the fix imports behavior (just uncommenting unused imports seems like a good idea) an option as a flag in golangs official gofmt?

Jan Mercl

unread,
Jul 13, 2013, 1:46:51 PM7/13/13
to Martin Schmidt, golang-nuts

Which package should gofmt "autoimport" when it sees a 'template' qualifier? html/template or text/template or github.com/somenick/template?

-j

Dominik Honnef

unread,
Jul 13, 2013, 3:03:26 PM7/13/13
to golan...@googlegroups.com
gofmt does not change code, it reformats it. Your code behaves exactly
the same before and after gofmt. And in my opinion this should not
change, not even with a flag.

Rob Figueiredo

unread,
Jul 13, 2013, 3:14:03 PM7/13/13
to golang-nuts
What about these? 

usage: gofmt [flags] [path ...]
-r="": rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')
-s=false: simplify code

Dominik Honnef

unread,
Jul 13, 2013, 5:05:08 PM7/13/13
to golan...@googlegroups.com
`-s` still won't semantically change your program. What it changes/removes
is code that doesn't affect the program's behaviour, it's akin to
removing parentheses that aren't required.

Adding or removing imports can change the behaviour of your program, or
whether it compiles at all.

And I don't think `-r` fits into the equation at all; it is very
explicit in that it requires the user to say what to change.

Maybe I should've been more explicit, too: gofmt doesn't semantically
change code unless the user tells it exactly what to change. It doesn't
guess.

Rob Figueiredo

unread,
Jul 14, 2013, 12:32:05 PM7/14/13
to golang-nuts
Hm, I see the distinction.  

But you must agree that it is a fine (and arbitrary) line between applying a requested transformation/rewrite and having that requested transformation be "try to fix the imports", even as that imports transformation can be fully and reasonably specified?  


Martin Schmidt

unread,
Jul 14, 2013, 12:41:46 PM7/14/13
to golan...@googlegroups.com

gofmt does not change code, it reformats it. Your code behaves exactly
the same before and after gofmt. And in my opinion this should not
change, not even with a flag.

good point.

As for -r  i would say "a.b -> false" is less specific than a flag for removing unused imports. a and b are just freely matchable atoms without any semantics besides being part of the go language. While unused imports has more semantics attached to it. There is no guessing involved in removing them. But then again the flag could just be in the compiler not
being so pedantic about them in the first place. So it does not seem to be the right place to be in gofmt if included at all in golang.

Alfonso Vega-Garcia

unread,
Jul 16, 2013, 2:46:54 AM7/16/13
to Martin Schmidt, golang-nuts
Thanks Brad, I've replaced gofmt with goimports and this is a practical and useful tool for standard packages.

one suggestion is to support non standard packages by means of a config file in the home directory that keeps a table similar to [1] in any human readable format.
It would be nice to automatically add known import/identifier pairs in the program, eg:

gomock.NewController(t)

goimports would add "gomock.NewController": "code.google.com/p/gomock/gomock"




-- Alfonso

Alfonso Vega-Garcia | Software Engineer |  vegacom a t gmail.com
 


--

Brad Fitzpatrick

unread,
Jul 16, 2013, 2:50:32 AM7/16/13
to Alfonso Vega-Garcia, golang-nuts, Martin Schmidt

Yes. I'll be adding that for internal Google usage.

Jan Mercl

unread,
Jul 16, 2013, 2:53:28 AM7/16/13
to Brad Fitzpatrick, Alfonso Vega-Garcia, golang-nuts, Martin Schmidt
On Tue, Jul 16, 2013 at 8:50 AM, Brad Fitzpatrick <brad...@golang.org> wrote:

Yes. I'll be adding that for internal Google usage.


What import is automagically added for the unsatisfied qualifier 'template'?

text/template or html/template or github.com/whoever/template ?

-j

Brad Fitzpatrick

unread,
Jul 16, 2013, 2:58:31 AM7/16/13
to Jan Mercl, Alfonso Vega-Garcia, golang-nuts, Martin Schmidt
The standard library is always preferred over third-party packages (the hook I'll be adding).

Within the standard library, ambiguous stuff is ignored:

$ pwd
/Users/bradfitz/src/github.com/bradfitz/goimports

$ grep ambig zcommon.go
// "pprof.Profile" is ambiguous
// "rand.Int" is ambiguous
// "scanner.ScanComments" is ambiguous
// "scanner.Scanner" is ambiguous
// "template.FuncMap" is ambiguous
// "template.HTMLEscape" is ambiguous
// "template.HTMLEscapeString" is ambiguous
// "template.HTMLEscaper" is ambiguous
// "template.JSEscape" is ambiguous
// "template.JSEscapeString" is ambiguous
// "template.JSEscaper" is ambiguous
// "template.Must" is ambiguous
// "template.New" is ambiguous
// "template.ParseFiles" is ambiguous
// "template.ParseGlob" is ambiguous
// "template.Template" is ambiguous
// "template.URLQueryEscaper" is ambiguous

Jan Mercl

unread,
Jul 16, 2013, 4:07:51 AM7/16/13
to Brad Fitzpatrick, Alfonso Vega-Garcia, golang-nuts, Martin Schmidt
On Tue, Jul 16, 2013 at 8:58 AM, Brad Fitzpatrick <brad...@golang.org> wrote:
> The standard library is always preferred over third-party packages (the hook
> I'll be adding).
>
> Within the standard library, ambiguous stuff is ignored:
>
> $ pwd
> /Users/bradfitz/src/github.com/bradfitz/goimports
>
> $ grep ambig zcommon.go
> // "pprof.Profile" is ambiguous
> // "rand.Int" is ambiguous
> // "scanner.ScanComments" is ambiguous
> // "scanner.Scanner" is ambiguous
> // "template.FuncMap" is ambiguous
> // "template.HTMLEscape" is ambiguous
> // "template.HTMLEscapeString" is ambiguous
> // "template.HTMLEscaper" is ambiguous
> // "template.JSEscape" is ambiguous
> // "template.JSEscapeString" is ambiguous
> // "template.JSEscaper" is ambiguous
> // "template.Must" is ambiguous
> // "template.New" is ambiguous
> // "template.ParseFiles" is ambiguous
> // "template.ParseGlob" is ambiguous
> // "template.Template" is ambiguous
> // "template.URLQueryEscaper" is ambiguous

Thanks for the answer.

I think this means there can exist a source, lacking a proper
(forgotten) import; which, when "auto-corrected" by this tool, becomes
silently doing something else than intended. That's dangerous, IMHO. I
believe source code tools should never make any guesses. Assigning
priority for stdlib packages is a guess.

-j

Brad Fitzpatrick

unread,
Jul 16, 2013, 4:10:26 AM7/16/13
to Jan Mercl, golang-nuts, veg...@gmail.com, Martin Schmidt

Okay. Don't use it then.

Also: write tests.

Jan Mercl

unread,
Jul 16, 2013, 4:26:33 AM7/16/13
to Brad Fitzpatrick, golang-nuts, veg...@gmail.com, Martin Schmidt
On Tue, Jul 16, 2013 at 10:10 AM, Brad Fitzpatrick <brad...@golang.org> wrote:
> Okay. Don't use it then.
>
> Also: write tests.

I do. You do. Not everyone does.

-j

Brad Fitzpatrick

unread,
Jul 16, 2013, 4:39:32 AM7/16/13
to Jan Mercl, golang-nuts, veg...@gmail.com, Martin Schmidt

I'm seriously not worried.

A hundred things worry me more than os.RemoveAll("/") calling the standard library's pkg os and not github.com/foo/testingmock/os.RemoveAll

Volker Dobler

unread,
Jul 16, 2013, 4:57:57 AM7/16/13
to golan...@googlegroups.com
Am Dienstag, 16. Juli 2013 10:39:32 UTC+2 schrieb bradfitz:

I'm seriously not worried.

A hundred things worry me more than os.RemoveAll("/") calling the standard library's pkg os and not github.com/foo/testingmock/os.RemoveAll


You made my day!

V. 

Davor Bauk

unread,
Aug 18, 2014, 8:39:09 PM8/18/14
to golan...@googlegroups.com
I tried using goimports in Sublime Text 3 but all the App Engine packages get prefixed by "pkg" (eg. "pkg/appengine/datastore")

My Go related paths are set up as such:

export PATH=$HOME/SDK/go_appengine:$PATH
export GOPATH=$HOME/__WORK/_go/libs-external:$HOME/__WORK/_go/libs:$HOME/__WORK/_go/_projects:$HOME/SDK/go_appengine/goroot


Any ideas?

-ph

Brad Fitzpatrick

unread,
Aug 18, 2014, 11:58:50 PM8/18/14
to Davor Bauk, golang-nuts
Can you reproduce it with a less gigantic GOPATH?



--
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.

Davor Bauk

unread,
Aug 19, 2014, 1:32:31 AM8/19/14
to golan...@googlegroups.com, phi...@gmail.com
Actually, I got it to work.

Let me explain.

$HOME/__WORK/_go/libs-external
This is where I keep 3rd party libraries. 
('go get' installs libraries into the first entry in GOPATH by default)

$HOME/__WORK/_go/libs
This is where I keep my own libraries, shared by all projects

$HOME/__WORK/_go/_projects
This is my Go projects folder

$HOME/SDK/go_appengine/goroot
By adding this to GOPATH, and adding "installsuffix": "appengine" to GoSublime.sublime-settings, I got the autocompletion to work.
However, because it wasn't playing well with 'goimports', I decided to remove this path and the "installsuffix" option

Instead, I added 3 symlinks:
ln -s ~/SDK/go_appengine/goroot/src/pkg ~/SDK/go_appengine/gopath/src
ln -s ~/SDK/go_appengine/goroot/pkg ~/SDK/go_appengine/gopath/pkg/darwin_amd64_appengine
ln -s ~/SDK/go_appengine/goroot/bin ~/SDK/go_appengine/gopath/bin

and added $HOME/SDK/go_appengine/gopath to GOPATH

the final GOPATH looks like this:

export PATH=$HOME/SDK/go_appengine:$PATH
export GOPATH=$HOME/__WORK/_go/libs-external:$HOME/__WORK/_go/libs:$HOME/__WORK/_go/_projects:$HOME/SDK/go_appengine/gopath


both autocomplete and goimports now work as expected with App Engine packages in Sublime

-ph

Dmitri Shuralyov

unread,
Aug 19, 2014, 1:43:31 AM8/19/14
to golan...@googlegroups.com, phi...@gmail.com
> I made a thing on a plane

Wow... That's how history is made.
Reply all
Reply to author
Forward
0 new messages