1

I am writing a Go command-line tool that generates some files based on templates.

The templates are located in the Git repository alongside the code for the command-line tool itself.

I wanted to allow the following:

  1. The binary, wherever it is called from, should always find the templates directory.
  2. The templates directory can be overriden by the user if need be.

Since this is a Go application, I went with something like:

templateRoot := filepath.Join(
    os.Getenv("GOPATH"),
    "src/github.com/myuser/myproject/templates",
)

But being rather new to Go, I wonder if this approach is reliable enough: is it guaranteed that my application template will always be accessible at that path ?

What if someone vendorize my application into their own project ? Does that even make sense for a command-line tool ?

Because of 2., I obviously can't/won't use go-bindata because I want to allow for the templates to be overriden if need be.

In summary: what is a good strategy to reliably refer to non-go, static files in a Go command-line tool ?

ereOn
  • 53,676
  • 39
  • 161
  • 238
  • You can't use GOPATH, because GOPATH is only used for building the application. You install the files into one or more well-known locations, like any other program would. – JimB Mar 21 '17 at 12:39
  • Well, this one is not overridable. – Sergio Tulentsev Mar 21 '17 at 12:39
  • @JimB: Am I wrong to assume that `go get ` will "install" my command-line tool then ? I thought it was pretty idiomatic for Go tool to rely on the fact they were installed via `go get`. – ereOn Mar 21 '17 at 12:51
  • Related / possible duplicate of [how to reference a relative file from code and tests](http://stackoverflow.com/questions/31059023/how-to-reference-a-relative-file-from-code-and-tests/31059125#31059125). – icza Mar 21 '17 at 12:51
  • @ereOn: `go get` is a convenience for developers to fetch and build a go package. It relies on having a GOPATH (though there's a default now in go1.8), and GOBIN in your PATH. Many programs require extra steps not covered by the simple `go` tool, and have scripts or Makefiles to do the build. If you're targeting users that aren't developers, you ned to provide a way to install into standard system paths. Just provide a list of locations your program looks for templates. – JimB Mar 21 '17 at 12:56
  • @JimB That makes sense indeed. Thanks. BTW: I would accept this as an answer. – ereOn Mar 21 '17 at 13:25

1 Answers1

1

GOPATH is used for building the application. While you could look for GOPATH and check relative locations to each GOPATH entry at runtime, you can't be sure it will exist (unless of course you make it a prerequisite for running your application).

go get itself is a convenience for developers to fetch and build a go package. It relies on having a GOPATH (though there's a default now in go1.8), and GOBIN in your PATH. Many programs require extra steps not covered by the simple go tool, and have scripts or Makefiles to do the build. If you're targeting users that aren't developers, you need to provide a way to install into standard system paths anyway.

Do what any regular program would do, and use some well-known path to locate the template files. You can certainly add some logic in your program to check for a hierarchy of locations: relative to $GOPATH, relative to the binary, working directory, $HOME, etc; just provide a list of locations to the user that your program will look for templates.

JimB
  • 104,193
  • 13
  • 262
  • 255