Add "Template-Rendering"

Virgil 2026-02-19 16:59:31 +00:00
parent 361dddf56b
commit d5dbfaa19a

122
Template-Rendering.-.md Normal file

@ -0,0 +1,122 @@
# Template Rendering
go-store includes a built-in template engine that renders Go `text/template` strings using key-value pairs from a group as template variables.
## Render Method
```go
func (s *Store) Render(tmplStr, group string) (string, error)
```
Loads all key-value pairs from the specified group, then executes the Go template string with those values as the data context.
### Basic Usage
```go
s, _ := store.New(":memory:")
_ = s.Set("site", "name", "Core Platform")
_ = s.Set("site", "domain", "core.help")
_ = s.Set("site", "version", "2.1.0")
output, err := s.Render("Welcome to {{.name}} ({{.domain}}) v{{.version}}", "site")
// output == "Welcome to Core Platform (core.help) v2.1.0"
```
### Template Syntax
The template uses standard Go `text/template` syntax. The data context is a `map[string]string` where keys are the store keys and values are the store values.
| Syntax | Description |
|--------|-------------|
| `{{.key}}` | Insert the value for `key` |
| `{{if .key}}...{{end}}` | Conditional block |
| `{{range $k, $v := .}}...{{end}}` | Iterate all key-value pairs |
| `{{.key \| printf "%q"}}` | Pipe through a function |
### Configuration File Generation
A common use case is generating configuration files from stored settings:
```go
_ = s.Set("nginx", "server_name", "api.core.help")
_ = s.Set("nginx", "port", "8080")
_ = s.Set("nginx", "root", "/var/www/html")
tmpl := `server {
listen {{.port}};
server_name {{.server_name}};
root {{.root}};
}`
output, err := s.Render(tmpl, "nginx")
```
### Environment File Generation
```go
_ = s.Set("env", "APP_NAME", "Core")
_ = s.Set("env", "APP_DEBUG", "false")
_ = s.Set("env", "DB_HOST", "localhost")
tmpl := `APP_NAME={{.APP_NAME}}
APP_DEBUG={{.APP_DEBUG}}
DB_HOST={{.DB_HOST}}`
envFile, _ := s.Render(tmpl, "env")
_ = os.WriteFile(".env", []byte(envFile), 0644)
```
### Iterating All Values
Use `range` to iterate over all stored key-value pairs:
```go
tmpl := `{{range $k, $v := .}}{{$k}}={{$v}}
{{end}}`
output, _ := s.Render(tmpl, "env")
```
Note: map iteration order in Go is not guaranteed, so the output order may vary.
## How It Works
Internally, `Render` performs three steps:
1. **Query**: Fetches all rows from the `kv` table where `grp` matches the group
2. **Parse**: Parses the template string with `template.New("render").Parse(tmplStr)`
3. **Execute**: Executes the template with the `map[string]string` as the data context
```go
// Equivalent manual implementation
vars, _ := s.GetAll("site")
tmpl, _ := template.New("t").Parse("Hello {{.name}}")
var buf strings.Builder
tmpl.Execute(&buf, vars)
result := buf.String()
```
The `Render` method combines these steps with proper error handling for each stage.
## Error Handling
`Render` returns errors from three potential failure points:
| Error | Cause |
|-------|-------|
| `store.Render: query:` | Database query failed |
| `store.Render: scan:` | Row scanning failed |
| `store.Render: parse:` | Invalid Go template syntax |
| `store.Render: exec:` | Template execution failed (e.g. missing function) |
```go
output, err := s.Render("{{.missing_func | nonexistent}}", "group")
if err != nil {
// err contains "store.Render: parse:" or "store.Render: exec:"
}
```
If the group has no keys, the template receives an empty map. Referencing `{{.key}}` for a missing key produces an empty string (Go template default behaviour).
See also: [[Home]] | [[API-Reference]]