Add "Template-Rendering"

Virgil 2026-02-19 16:21:21 +00:00
parent 83be85ad0f
commit b843cd268a

161
Template-Rendering.-.md Normal file

@ -0,0 +1,161 @@
# Template Rendering
The `Render` method combines the store's key-value data with Go's `text/template` package, enabling dynamic configuration files, API payloads, and text generation from stored values.
## How It Works
1. All key-value pairs in the specified group are loaded into a `map[string]string`
2. The map is passed as the data context to `text/template`
3. The rendered output is returned as a string
```go
func (s *Store) Render(tmplStr, group string) (string, error)
```
The template receives the full group as its root data object. Each store key becomes a field accessible with `{{ .keyname }}`.
## Basic Usage
```go
s, _ := store.New(":memory:")
s.Set("user", "pool", "pool.lthn.io:3333")
s.Set("user", "wallet", "iz...")
tmpl := `{"pool":"{{ .pool }}","wallet":"{{ .wallet }}"}`
out, _ := s.Render(tmpl, "user")
// out = `{"pool":"pool.lthn.io:3333","wallet":"iz..."}`
```
## Go Template Syntax
Templates use the standard Go `text/template` syntax. Here is a quick reference for the most useful features with go-store.
### Variable Access
Access store values using dot notation:
```
{{ .keyname }}
```
For keys containing special characters, use the `index` function:
```
{{ index . "my-key" }}
{{ index . "key.with.dots" }}
```
### Conditionals
Check if a key has a value:
```
{{ if .theme }}Theme: {{ .theme }}{{ end }}
```
Default values using `or`:
```
{{ or .theme "dark" }}
```
### Ranges and Pipelines
Since the data is a flat `map[string]string`, range iterates over all keys:
```
{{ range $key, $val := . }}
{{ $key }} = {{ $val }}
{{ end }}
```
### Built-in Functions
Go templates include these functions out of the box:
| Function | Example | Description |
|----------|---------|-------------|
| `index` | `{{ index . "key" }}` | Access map value by key string |
| `len` | `{{ len . }}` | Number of keys in the group |
| `eq` | `{{ if eq .theme "dark" }}` | String equality |
| `ne` | `{{ if ne .lang "" }}` | String inequality |
| `and` | `{{ if and .pool .wallet }}` | Logical AND |
| `or` | `{{ or .theme "default" }}` | Logical OR / default value |
| `print` | `{{ print .host ":" .port }}` | String concatenation |
## Practical Examples
### JSON Configuration
```go
s.Set("mining", "pool", "pool.lthn.io:3333")
s.Set("mining", "wallet", "iz4xK...")
s.Set("mining", "threads", "4")
tmpl := `{
"pool": "{{ .pool }}",
"wallet": "{{ .wallet }}",
"threads": {{ .threads }}
}`
out, _ := s.Render(tmpl, "mining")
```
### INI-Style Configuration
```go
s.Set("app", "name", "MyApp")
s.Set("app", "version", "1.0.0")
s.Set("app", "debug", "true")
tmpl := `[application]
name={{ .name }}
version={{ .version }}
debug={{ .debug }}`
out, _ := s.Render(tmpl, "app")
```
### Environment Variables
```go
s.Set("env", "DATABASE_URL", "sqlite:///data/app.db")
s.Set("env", "LOG_LEVEL", "info")
s.Set("env", "PORT", "8080")
tmpl := `{{ range $key, $val := . }}{{ $key }}={{ $val }}
{{ end }}`
out, _ := s.Render(tmpl, "env")
```
### HTML Fragment
```go
s.Set("site", "title", "My Site")
s.Set("site", "description", "A great site")
tmpl := `<head>
<title>{{ .title }}</title>
<meta name="description" content="{{ .description }}">
</head>`
out, _ := s.Render(tmpl, "site")
```
## Error Handling
`Render` can fail at three stages:
1. **Database query** — the group cannot be read from SQLite
2. **Template parsing** — the template string has invalid syntax
3. **Template execution** — a referenced key does not exist in the map
For missing keys, Go templates produce `<no value>` by default rather than failing. To fail explicitly on missing keys, use `template.Option("missingkey=error")` (not currently exposed — use `index` with a conditional instead).
### Safe Access Pattern
```go
tmpl := `{{ if .optional }}Value: {{ .optional }}{{ else }}(not set){{ end }}`
```
## Related
- [[Home]] — Package overview and schema
- [[API-Reference]] — Full method signatures and error documentation