go.rice is a Go package that makes working with resources such as html,js,css,images and templates easy. During development go.rice
will load required files directly from disk. Upon deployment it's easy to add all resource files to a executable using the rice
tool, without changing the source code for your package. go.rice provides methods to add resources to a binary in different scenarios.
The first thing go.rice does is finding the correct absolute path for your resource files. Say you are executing a binary in your home directory, but your html-files
are in $GOPATH/src/yourApplication/html-files
. go.rice
will lookup the correct path for that directory (relative to the location of yourApplication). All you have to do is include the resources using rice.FindBox("html-files")
.
This works fine when the source is available to the machine executing the binary, which is the case when installing the executable with go get
or go install
. But it does not work when you wish to provide a single binary without source. This is where the rice
tool comes in. It analyses source code and finds call's to rice.FindBox(..)
. Then it adds the required directories to the executable binary, There are two strategies to do this. You can 'embed' the assets by generating go source code and then compile them into the executable binary, or you can 'append' the assets to the executable binary after compiling. In both cases the rice.FindBox(..)
call detects the embedded or appended resources and load those, instead of looking up files from disk.
Use go install
to install the package the rice
tool.
go install github.com/TheTinkerDad/go.rice
go install github.com/TheTinkerDad/go.rice/rice
Import the package: import "github.com/TheTinkerDad/go.rice"
Serving a static content folder over HTTP with a rice Box:
http.Handle("/", http.FileServer(rice.MustFindBox("http-files").HTTPBox()))
http.ListenAndServe(":8080", nil)
Serve a static content folder over HTTP at a non-root location:
box := rice.MustFindBox("cssfiles")
cssFileServer := http.StripPrefix("/css/", http.FileServer(box.HTTPBox()))
http.Handle("/css/", cssFileServer)
http.ListenAndServe(":8080", nil)
Note the trailing slash in /css/
in both the call to
http.StripPrefix
and http.Handle
.
Loading a template:
// find a rice.Box
templateBox, err := rice.FindBox("example-templates")
if err != nil {
log.Fatal(err)
}
// get file contents as string
templateString, err := templateBox.String("message.tmpl")
if err != nil {
log.Fatal(err)
}
// parse and execute the template
tmplMessage, err := template.New("message").Parse(templateString)
if err != nil {
log.Fatal(err)
}
tmplMessage.Execute(os.Stdout, map[string]string{"Message": "Hello, world!"})
Never call FindBox()
or MustFindBox()
from an init()
function, as there is no guarantee the boxes are loaded at that time.
Always call FindBox()
or MustFindBox()
with string literals e.g. FindBox("example")
. Do not use string constants or variables. This will prevent the rice tool to fail with error Error: found call to rice.FindBox, but argument must be a string literal.
.
The rice
tool lets you add the resources to a binary executable so the files are not loaded from the filesystem anymore. This creates a 'standalone' executable. There are multiple strategies to add the resources and assets to a binary, each has pro's and con's but all will work without requiring changes to the way you load the resources.
Execute this method before building. It generates a single Go source file called rice-box.go for each package. The generated go file contains all assets. The Go tool compiles this into the binary.
The downside with this option is that the generated go source file can become large, which may slow down compilation and requires more memory to compile.
Execute the following commands:
rice embed-go
go build
A Note on Symbolic Links: embed-go
uses the os.Walk
function from the standard library. The os.Walk
function does not follow symbolic links. When creating a box, be aware that any symbolic links inside your box's directory are not followed. When the box itself is a symbolic link, the rice tool resolves its actual location before adding the contents.
This method changes an already built executable. It appends the resources as zip file to the binary. It makes compilation a lot faster. Using the append method works great for adding large assets to an executable binary.
A downside for appending is that it does not provide a working Seek method.
Run the following commands to create a standalone executable.
go build -o example
rice append --exec example
Similar to the append
command, this method changes an already-built executable by adding appending a zipfile. The difference from append
is that it does not require for the source code to be accessible; in order to achieve this, you have to specify a list of directories to append.
Run the following commands to create a standalone executable.
go build -o example
rice append --exec example -d foo -d bar
Run rice --help
for information about all flags and subcommands.
You can use the --help
flag on each sub-command. For example: rice append --help
.
When opening a new box, the rice.FindBox(..)
tries to locate the resources in the following order:
- embedded (generated as
rice-box.go
) - appended (appended to the binary executable after compiling)
- 'live' from filesystem
This project is licensed under a Simplified BSD license. Please read the LICENSE file.
You will find package documentation at godoc.org/github.com/TheTinkerDad/go.rice.