Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions internal/exercises/catalog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,11 @@ projects:
- "Use time.Parse() to parse time strings with known layouts"
- "Use time.LoadLocation() to work with different timezones"
- "Extract time components using .Date() and .Clock() methods"
- slug: 40_text_templates
title: "Text Templates"
difficulty: beginner
topics: ["text/template", "strings", "formatting"]
hints:
- "Use Go's text/template package to create and execute templates."
- "Define template actions like {{.Field}} to inject data."
- "Use template functions like printf for formatting."
31 changes: 31 additions & 0 deletions internal/exercises/solutions/40_text_templates/text_templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package exercises

import (
"bytes"
"text/template"
)

// RenderTemplate takes a template string and data map, returns the rendered string or error.
func RenderTemplate(tmplStr string, data map[string]any) (string, error) {
tmpl, err := template.New("exercise").Parse(tmplStr)
if err != nil {
return "", err
}

var buf bytes.Buffer
err = tmpl.Execute(&buf, data)
if err != nil {
return "", err
}

return buf.String(), nil
}

// FormatUserGreeting returns a greeting using text/template with user's name
func FormatUserGreeting(name string) (string, error) {
const greetingTmpl = "Hello, {{.Name}}!"
data := map[string]any{
"Name": name,
}
return RenderTemplate(greetingTmpl, data)
}
16 changes: 16 additions & 0 deletions internal/exercises/templates/40_text_templates/text_templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package exercises

import (
"bytes"
"text/template"
)

// RenderTemplate takes a template string and data map, returns the rendered string or error.
func RenderTemplate(tmplStr string, data map[string]any) (string, error) {
return "", nil
}

// FormatUserGreeting returns a greeting using text/template with user's name
func FormatUserGreeting(name string) (string, error) {
return "", nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package exercises

import (
"testing"
)

func TestRenderTemplate(t *testing.T) {
t.Run("Success", func(t *testing.T) {
tmpl := "Name: {{.Name}}, Age: {{.Age}}"
data := map[string]any{
"Name": "Alice",
"Age": 30,
}

result, err := RenderTemplate(tmpl, data)
if err != nil {
t.Errorf("RenderTemplate returned error: %v", err)
}
expected := "Name: Alice, Age: 30"
if result != expected {
t.Errorf("RenderTemplate = %q, want %q", result, expected)
}
})

t.Run("InvalidSyntax", func(t *testing.T) {
tmpl := "Hello {{.Name"
data := map[string]any{"Name": "Bob"}

_, err := RenderTemplate(tmpl, data)
if err == nil {
t.Error("Expected error for invalid template syntax, got nil")
}
})

t.Run("MissingData", func(t *testing.T) {
tmpl := "Hello, {{.MissingField}}!"
data := map[string]any{"Name": "Charlie"}

_, err := RenderTemplate(tmpl, data)
if err != nil {
t.Errorf("RenderTemplate unexpectedly returned error: %v", err)
}
expected := "Hello, <no value>!"
if result, _ := RenderTemplate(tmpl, data); result == expected {
}
})
}

func TestFormatUserGreeting(t *testing.T) {
t.Run("Success", func(t *testing.T) {
result, err := FormatUserGreeting("Bob")
if err != nil {
t.Errorf("FormatUserGreeting returned error: %v", err)
}
expected := "Hello, Bob!"
if result != expected {
t.Errorf("FormatUserGreeting = %q, want %q", result, expected)
}
})

t.Run("EmptyName", func(t *testing.T) {
result, err := FormatUserGreeting("")
if err != nil {
t.Errorf("FormatUserGreeting returned error: %v", err)
}
expected := "Hello, !"
if result != expected {
t.Errorf("FormatUserGreeting = %q, want %q", result, expected)
}
})
}