Skip to content

go-sprout/sprout

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Sprout Logo

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.

Motivation

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.

Roadmap to Sprout v1.0

You can track our progress towards Sprout v1.0 by following the documentation page here.

Table of Contents

Transitioning from Sprig

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")
)

Usage

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")
)

Usage: Logger

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")
)

Usage: Alias

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"),
)

Usage: Error Handling

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),
)

Default Value

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.

Panic

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.

Error Channel

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),
)

Performence Benchmarks

To see all the benchmarks, please refer to the benchmarks directory.

Sprig v3.2.3 vs Sprout v0.2

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.

Development Philosophy (Currently in reflexion to create our)

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.

About

From sprig to sprout - Useful template functions for Go templates with steroids

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Languages

  • Go 99.9%
  • Makefile 0.1%