Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active June 28, 2022 12:05
Show Gist options
  • Save Integralist/20ff7427d3df5cc02d5a619ca0cd9695 to your computer and use it in GitHub Desktop.
Save Integralist/20ff7427d3df5cc02d5a619ca0cd9695 to your computer and use it in GitHub Desktop.
[Go Guru and Vim-Go] #go #golang #guru #interfaces #vim #vim-go

Go Guru

See official doc: Using Go Guru

go get golang.org/x/tools/cmd/guru
guru -help

Guru command line usage:

guru <mode> <position:byte offset>

Here's an example go program:

type statusHandler int
 
func (s statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    code := int(s)
    w.WriteHeader(code)
    io.WriteString(w, http.StatusText(code))
}

With cursor over the statusHandler type:

guru implements ~/code/go/src/github.com/integralist/http-interface/main.go:#812

This tells us that it implements the http.Handler interface:

/Users/markmcdonnell/code/go/src/github.com/integralist/http-interface/main.go:40.6-40.18: basic type statusHandler
/usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:82.6-82.12:  implements net/http.Handler

With cursor over the ServeHTTP method:

guru implements ~/code/go/src/github.com/integralist/http-interface/main.go:#836

This tells us that it implements the http.Handler interface's signature ServeHTTP method:

/Users/markmcdonnell/code/go/src/github.com/integralist/http-interface/main.go:42.24-42.32: concrete method func (statusHandler).ServeHTTP(w net/http.ResponseWriter, r *net/http.Request)
/usr/local/Cellar/go/1.10.3/libexec/src/net/http/server.go:83.2-83.10:  implements method (net/http.Handler).ServeHTTP

Note: to convert a line into a byte range you can use in Vim :echo eval(line2byte(line("."))+col("."))


// this is a duplicate of fmt.Stringer interface
type stringit interface {
    String() string
}
 
type testthing struct{}
 
func (t testthing) String() string {
    return "a test thing"
}

With cursor over the testhing type:

guru implements ~/code/go/src/github.com/integralist/http-interface/main.go:#722

This tells us that the testthing struct is satisfying multiple interfaces. This helps me to realize that maybe my new interface isn't necessary and that maybe I should consider re-using an existing interface:

/Users/markmcdonnell/code/go/src/github.com/integralist/http-interface/main.go:33.6-33.14: struct type testthing
/usr/local/Cellar/go/1.10.3/libexec/src/fmt/print.go:62.6-62.13:                           implements fmt.Stringer
/Users/markmcdonnell/code/go/src/github.com/integralist/http-interface/main.go:29.6-29.13: implements stringit
/usr/local/Cellar/go/1.10.3/libexec/src/runtime/error.go:66.6-66.13:                       implements runtime.stringer

With cursor over the interface itself:

guru implements ~/code/go/src/github.com/integralist/http-interface/main.go:#676

This shows us everything that sastifies this interface:

main.go|29 col 6| interface type stringit
/usr/local/Cellar/go/1.10.3/libexec/src/bytes/buffer.go|17 col 6|     is implemented by pointer type *bytes.Buffer
/usr/local/Cellar/go/1.10.3/libexec/src/context/context.go|316 col 6| is implemented by pointer type *context.cancelCtx

...many things satisfy this...

Vim-Go integration with Guru

vim-go uses :GoReferrers to look up references and :GoImplements to show what interface the given type is implementing.

type foo interface {
	bar(string) string
}

type thing struct{}

func (t thing) bar(x string) string {
	fmt.Println(x)
	return "y"
}

If I execute :GoImplements while cursor is on top of bar method, I'll see:

main.go|35 col 16| concrete method func (thing).bar(x string) string
main.go|30 col 2| implements method (foo).bar
  • :GoCallers: lists callers of this function.
  • :GoCallees: lists functions called by this function.
  • :GoReferrers: lists every instance where this function is called.
  • :GoDescribe: lists selected identifiers definition (inc. method set + struct fields).
  • :GoImplements: lists all interfaces the selected identifier satisfies.
  • :GoWhicherrs: lists all possible error types returned.
  • :GoChannelPeers: lists sends/receives on a <- channel.

Vim-Go: Other Features

  • :GoRename: rename all references to identifier across project.
  • :GoImpl: implement stubs for specified interface.
  • :GoDecls: list all function and type declarations for the current file.
  • :GoDef: takes you to the source of the identifier (i.e. where it's defined).
  • :GoTest: run all your tests (can also pass ./...).
  • :GoTestFunc: run the specific test function under your cursor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment