github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/src/cmd/go/internal/fmtcmd/fmt.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package fmtcmd implements the ``go fmt'' command. 6 package fmtcmd 7 8 import ( 9 "os" 10 "path/filepath" 11 "runtime" 12 "strings" 13 "sync" 14 15 "cmd/go/internal/base" 16 "cmd/go/internal/cfg" 17 "cmd/go/internal/load" 18 "cmd/go/internal/str" 19 ) 20 21 func init() { 22 base.AddBuildFlagsNX(&CmdFmt.Flag) 23 } 24 25 var CmdFmt = &base.Command{ 26 Run: runFmt, 27 UsageLine: "fmt [-n] [-x] [packages]", 28 Short: "gofmt (reformat) package sources", 29 Long: ` 30 Fmt runs the command 'gofmt -l -w' on the packages named 31 by the import paths. It prints the names of the files that are modified. 32 33 For more about gofmt, see 'go doc cmd/gofmt'. 34 For more about specifying packages, see 'go help packages'. 35 36 The -n flag prints commands that would be executed. 37 The -x flag prints commands as they are executed. 38 39 To run gofmt with specific options, run gofmt itself. 40 41 See also: go fix, go vet. 42 `, 43 } 44 45 func runFmt(cmd *base.Command, args []string) { 46 gofmt := gofmtPath() 47 procs := runtime.GOMAXPROCS(0) 48 var wg sync.WaitGroup 49 wg.Add(procs) 50 fileC := make(chan string, 2*procs) 51 for i := 0; i < procs; i++ { 52 go func() { 53 defer wg.Done() 54 for file := range fileC { 55 base.Run(str.StringList(gofmt, "-l", "-w", file)) 56 } 57 }() 58 } 59 for _, pkg := range load.PackagesAndErrors(args) { 60 if pkg.Error != nil { 61 if strings.HasPrefix(pkg.Error.Err, "build constraints exclude all Go files") { 62 // Skip this error, as we will format 63 // all files regardless. 64 } else { 65 base.Errorf("can't load package: %s", pkg.Error) 66 continue 67 } 68 } 69 // Use pkg.gofiles instead of pkg.Dir so that 70 // the command only applies to this package, 71 // not to packages in subdirectories. 72 files := base.RelPaths(pkg.InternalAllGoFiles()) 73 for _, file := range files { 74 fileC <- file 75 } 76 } 77 close(fileC) 78 wg.Wait() 79 } 80 81 func gofmtPath() string { 82 gofmt := "gofmt" 83 if base.ToolIsWindows { 84 gofmt += base.ToolWindowsExtension 85 } 86 87 gofmtPath := filepath.Join(cfg.GOBIN, gofmt) 88 if _, err := os.Stat(gofmtPath); err == nil { 89 return gofmtPath 90 } 91 92 gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt) 93 if _, err := os.Stat(gofmtPath); err == nil { 94 return gofmtPath 95 } 96 97 // fallback to looking for gofmt in $PATH 98 return "gofmt" 99 }