Note
Sprout is an evolved variant of the Masterminds/sprig library, reimagined for modern Go versions. It introduces fresh functionalities and commits to maintaining the library, picking up where Sprig left off. Notably, Sprig had not seen updates for two years and was not compatible beyond Golang 1.13, necessitating the creation of Sprout.
Sprout was born out of the need for a modernized, maintained, and performant template function library. Sprig, the predecessor to Sprout, had not seen updates for two years and was not optimized for later versions of Golang. Sprout aims to fill this gap by providing a library that is actively maintained, compatible with the latest Go versions, and optimized for performance.
You can track our progress towards Sprout v1.0 by following the documentation page here.
- Motivation
- Roadmap to Sprout v1.0
- Transitioning from Sprig
- Usage
- Performence Benchmarks
- Development Philosophy (Currently in reflexion to create our)
Sprout is designed to be a drop-in replacement for Sprig in the v1.0, with the same function names and behavior. To use Sprout in your project, simply replace the Sprig import with Sprout:
import (
- "github.com/Masterminds/sprig/v3"
+ "github.com/go-sprout/sprout"
)
tpl := template.Must(
template.New("base").
- Funcs(sprig.FuncMap()).
+ Funcs(sprout.FuncMap()).
ParseGlob("*.tmpl")
)
To use Sprout in your project, import the library and use the FuncMap
function to add the template functions to your template:
import (
"github.com/go-sprout/sprout"
"text/template"
)
tpl := template.Must(
template.New("base").
Funcs(sprout.FuncMap()).
ParseGlob("*.tmpl")
)
You can customize the behavior of Sprout by creating a FunctionHandler
and passing it to the FuncMap
function or using the configuration functions provided by Sprout:
handler := sprout.NewFunctionHandler(
// Add your logger to the handler to log errors and debug information using the
// standard slog package or any other logger that implements the slog.Logger interface.
// By default, Sprout uses a slog.TextHandler.
sprout.WithLogger(slogLogger),
// Set the error handling behavior for the handler. By default, Sprout returns the default value of the return type without crashes or panics.
sprout.WithErrHandling(sprout.ErrHandlingReturnDefaultValue),
// Set the error channel for the handler. By default, Sprout does not use an error channel. If you set an error channel, Sprout will send errors to it.
// This options is only used when the error handling behavior is set to
// `ErrHandlingErrorChannel`
sprout.WithErrorChannel(errChan),
// Set the alias for a function. By default, Sprout use alias for some functions for backward compatibility with Sprig.
sprout.WithAlias("hello", "hi"),
)
// Use the handler with the FuncMap function. The handler will be used to handle all template functions.
tpl := template.Must(
template.New("base").
Funcs(sprout.FuncMap(sprout.WithFunctionHandler(handler))).
ParseGlob("*.tmpl")
)
Sprout uses the slog
package for logging. You can pass your logger
to the WithLogger
configuration function to log errors and debug information:
// Create a new logger using the slog package.
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
// Use the handler with the FuncMap function.
tpl := template.Must(
template.New("base").
Funcs(sprout.FuncMap(sprout.WithLogger(logger))).
ParseGlob("*.tmpl")
)
Sprout provides the ability to set an alias for a function. This feature is useful for backward compatibility with Sprig. You can set an alias for a function using the WithAlias
or WithAliases
configuration functions.
See more about the alias in the documentation.
sprout.NewFunctionHandler(
sprout.WithAlias("hello", "hi"),
)
Sprout provides three error handling behaviors:
ErrHandlingReturnDefaultValue
: Sprout returns the default value of the return type without crashes or panics.ErrHandlingPanic
: Sprout panics when an error occurs.ErrHandlingErrorChannel
: Sprout sends errors to the error channel.
You can set the error handling behavior using the WithErrHandling
configuration function:
sprout.NewFunctionHandler(
sprout.WithErrHandling(sprout.ErrHandlingReturnDefaultValue),
)
If you set the error handling behavior to ErrHandlingReturnDefaultValue
, Sprout will return the default value of the return type without crashes or panics to ensure a smooth user experience when an error occurs.
If you set the error handling behavior to ErrHandlingPanic
, Sprout will panic when an error occurs to ensure that the error is not ignored and sended back to template execution.
If you set the error handling behavior to ErrHandlingErrorChannel
, you can pass an error channel to the WithErrorChannel
configuration function. Sprout will send errors to the error channel:
errChan := make(chan error)
sprout.NewFunctionHandler(
sprout.WithErrHandling(sprout.ErrHandlingErrorChannel),
sprout.WithErrorChannel(errChan),
)
To see all the benchmarks, please refer to the benchmarks directory.
goos: linux
goarch: amd64
pkg: sprout_benchmarks
cpu: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
BenchmarkSprig-16 1 2152506421 ns/op 44671136 B/op 21938 allocs/op
BenchmarkSprout-16 1 1020721871 ns/op 37916984 B/op 11173 allocs/op
PASS
ok sprout_benchmarks 3.720s
Time improvement: ((2152506421 - 1020721871) / 2152506421) * 100 = 52.6% Memory improvement: ((44671136 - 37916984) / 44671136) * 100 = 15.1%
So, Sprout v0.3 is approximately 52.6% faster and uses 15.1% less memory than Sprig v3.2.3. ๐
You can see the full benchmark results here.
Our approach to extending and refining Sprout was guided by several key principles:
- Empowering layout construction through template functions.
- Designing template functions that avoid returning errors when possible, instead displaying default values for smoother user experiences.
- Ensuring template functions operate solely on provided data, without external data fetching.
- Maintaining the integrity of core Go template functionalities without overrides.