108

I have a project currently organized something like this:

~/code/go
         /bin
         /pkg
         /src
             /proj/main.go
                  /some_package/package.go
                  /some_other_package/some_other_package.go

Now if I want to use the go fmt tool on my whole project it seems that the only way is to do it separately for each directory in my projects source tree:

go fmt proj
go fmt proj/package
go fmt proj/some_other_package

Is there some way to tell the fmt command to run on the whole source tree?

Chris
  • 17,119
  • 5
  • 57
  • 60

6 Answers6

140

You can use three dots (...) as a wildcard. So for example, the following command will format all github.com packages:

go fmt github.com/...

This wildcard also works with other go commands like go list, go get and so. There is no need to remember such an ugly find command.

tux21b
  • 90,183
  • 16
  • 117
  • 101
  • 7
    @Chris, Using `...` as the wildcard is explained [there](http://golang.org/cmd/go/#Description_of_package_lists) – kostix Nov 18 '12 at 11:31
  • 1
    I wonder why it is done this way as opposed to just using standard wildcard patterns like : `github.com/*` or globbing syntax like `github.com/**/*.go` – chakrit Jul 22 '13 at 14:00
92

If you use gofmt instead of go fmt, it's recursive. For example, following command

gofmt -s -w .

(notice the little dot at end) recursively formats, simplifies, and saves result into every file under current directory. I have a shell alias gf defined as gofmt -s -w . and find it quite handy.

Try gofmt -l . (list files whose formatting differs from gofmt's) first if you want :-)

Song Gao
  • 2,008
  • 15
  • 18
  • 12
    `gofmt -l -s -w .` yields a behavior similar to `go fmt` (saving the files & printing the files that have been modified). Without the `-l` flag, the file names are not printed. – cr7pt0gr4ph7 Feb 10 '15 at 09:21
  • 2
    `git ls-files | grep ".go$" | xargs gofmt -l -s -w` to only do this to source files which are checked in to your repo. – Dave Aug 04 '16 at 14:45
  • does that affect only go files or all files in the directory? – CME64 May 14 '19 at 21:58
50

Also, you can try to run command:

go fmt ./...

from your project directory.

cn007b
  • 16,596
  • 7
  • 59
  • 74
  • 1
    Doesn't work if `.` is a symbolic link. I found [Song's answer](https://stackoverflow.com/a/13333931/1102648) works with symlink. – ssgao Jan 06 '20 at 16:31
6
find proj -type f -iregex '.*\.go' -exec go fmt '{}' +

Explanation

  • find proj: find everything in this directory...
    • -type f: ...that is a file
    • -iregex '.*\.go': ...and case-insensitively matches the regular expression .*\.go
  • ...and execute go fmt followed by as many matched files as the operating system can handle passing to an executable in one go.
icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • Nice command, it's too bad the fmt tool can't do that automatically. I did make a couple of tweaks though: `find src` instead of `find proj` to run it from `$GOROOT`, and `\;` instead of `+` since the fmt tool doesn't work when it's given files that are in different directories. – Chris Nov 10 '12 at 04:52
  • Useful command, but I would like to do something like this `git status | egrep '\.go$' .... ` and use your command how can I do that? – Cristian Nov 08 '16 at 14:05
  • @Cristian: You'll probably need to do some processing with `awk` or `cut` or something to munge it down to just a list of file names; once that's done, though, you should be able to use `xargs`, e.g. `... | xargs go fmt`. – icktoofay Dec 16 '16 at 06:21
5

if you are using GoLand IDE, right click on project and you will find Go Tools. enter image description here

sgauri
  • 694
  • 8
  • 18
3

The command gofmt ./... mentioned by some, does not work on Windows (at least on my Win7).

Instead of it, I used gofmt -d .\ which works recursively. I use the -d flag because I want to list the changes I need to make in order to pass the check.

NB: golint ./... does work on Windows, just gofmt ./... doesn't.

Csongor Halmai
  • 3,239
  • 29
  • 30