how gofmt work

I use “gofmt” everyday, but I do not what happened in deeply when I do. Let me see deeply understand the command’s function.

I used branch release-go1.7

At first, let me check the options.

🍣 k-1$ gofmt -h                                                                          
usage: gofmt [flags] [path ...]
-cpuprofile string
write cpu profile to this file
-d display diffs instead of rewriting files
-e report all errors (not just the first 10 on different lines)
-l list files whose formatting differs from gofmt's
-r string
rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')
-s simplify code
-w write result to (source) file instead of stdout

OK. Usually, I just run it without option. So check the behavior without any options. ( each options are next time!!)

Let’s start deep dive gofmt.

function “main” is always start point.

func main() {
// call gofmtMain in a separate function
// so that it can use defer and have them
// run before the exit.

In the main function, “gofmtMain” is called. 
See that function as below.

At first, it calls “flag.Parse”, so each word is analyzed by that function.

func gofmtMain() {
flag.Usage = usage

Then initiates “initParse()” & “initRewrite()”.


“intParse()” is just called for formatting comment also.
“initRewrite()” which is written in rewrite.go is actual function called to format codes.

The following variables are in initRewrite.

pattern := parseExpr(f[0], "pattern")
replace := parseExpr(f[1], "replacement")
rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) }

As written in source code, rewriteFile applies the rewrite rule ‘pattern -> replace’ to an entire file.

I will see rewriteFile function more next time.