// Example 1: Web Server with Templates package main
import ( “html/template” “log” “net/http” “time” )
// Article represents a blog post type Article struct { Title string Content string PublishedAt time.Time Author string Tags []string }
func main() { // Define custom functions for templates funcMap := template.FuncMap{ “formatDate”: func(t time.Time) string { return t.Format(“January 2, 2006”) }, “join”: func(sep string, items []string) string { result := "" for i, item := range items { if i > 0 { result += sep } result += item } return result }, }
// Parse templates with function map
tmpl, err := template.New("").Funcs(funcMap).ParseGlob("templates/*.html")
if err != nil {
log.Fatalf("Error parsing templates: %v", err)
}
// Handler for the blog article
http.HandleFunc("/article", func(w http.ResponseWriter, r *http.Request) {
article := Article{
Title: "Understanding Go Templates",
Content: "Go templates are a powerful way to generate textual output based on data...",
PublishedAt: time.Date(2023, 5, 15, 12, 0, 0, 0, time.UTC),
Author: "Jane Smith",
Tags: []string{"golang", "templates", "web-development"},
}
err := tmpl.ExecuteTemplate(w, "article.html", article)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
// Start the server
log.Println("Starting server on :8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
/* templates/layout.html:
<main>
{{block "content" .}}{{end}}
</main>
<footer>
<p>© 2023 My Blog</p>
</footer>
*/
/* templates/article.html: {{template “layout.html” .}}
{{define “title”}}{{.Title}} | My Blog{{end}}
{{define “content”}}
{{.Title}}
<div class="content">
{{.Content}}
</div>
{{if .Tags}}
<div class="tags">
Tags: {{join ", " .Tags}}
</div>
{{end}}
// Example 2: Data-driven Email Template Generator package main
import ( “bytes” “fmt” “log” “text/template” “time” )
type Customer struct { Name string Email string LastPurchase time.Time }
type Product struct { Name string Description string Price float64 ImageURL string }
type EmailData struct { Customer Customer RecommendedProducts []Product CouponCode string ExpiryDate time.Time }
func generateEmail(customer Customer) (string, error) { // Create email data data := EmailData{ Customer: customer, RecommendedProducts: []Product{ { Name: “Wireless Headphones”, Description: “High-quality noise-cancelling headphones”, Price: 129.99, ImageURL: “https://example.com/images/headphones.jpg”, }, { Name: “Smart Watch”, Description: “Track your fitness and stay connected”, Price: 199.99, ImageURL: “https://example.com/images/smartwatch.jpg”, }, }, CouponCode: “WELCOME20”, ExpiryDate: time.Now().AddDate(0, 0, 14), // 14 days from now }
// Define template functions
funcMap := template.FuncMap{
"formatDate": func(t time.Time) string {
return t.Format("January 2, 2006")
},
"formatPrice": func(price float64) string {
return fmt.Sprintf("$%.2f", price)
},
"daysSince": func(t time.Time) int {
return int(time.Since(t).Hours() / 24)
},
}
// Define email templates
const emailTemplate = `
{{define “text”}} Hello {{.Customer.Name}},
We noticed it’s been {{daysSince .Customer.LastPurchase}} days since your last purchase. We have some recommendations just for you!
{{range .RecommendedProducts}}
- {{.Name}} - {{formatPrice .Price}} {{.Description}}
{{end}}
Use coupon code {{.CouponCode}} for 20% off your next purchase! Valid until {{formatDate .ExpiryDate}}.
Thank you for shopping with us! {{end}}
{{define “html”}}
Hello {{.Customer.Name}},
<p>We noticed it's been <strong>{{daysSince .Customer.LastPurchase}} days</strong> since your last purchase.
We have some recommendations just for you!</p>
{{range .RecommendedProducts}}
<div class="product">
<h2>{{.Name}} - {{formatPrice .Price}}</h2>
<p>{{.Description}}</p>
<img src="{{.ImageURL}}" alt="{{.Name}}" style="max-width: 200px;">
</div>
{{end}}
<p>Use coupon code <span class="coupon">{{.CouponCode}}</span> for 20% off your next purchase!</p>
<p>Valid until <strong>{{formatDate .ExpiryDate}}</strong>.</p>
<p>Thank you for shopping with us!</p>
{{end}}
`
tmpl, err := template.New("email").Funcs(funcMap).Parse(emailTemplate)
if err != nil {
return "", fmt.Errorf("template parsing error: %v", err)
}
// Generate text version
var textBuffer bytes.Buffer
err = tmpl.ExecuteTemplate(&textBuffer, "text", data)
if err != nil {
return "", fmt.Errorf("text template execution error: %v", err)
}
// Generate HTML version
var htmlBuffer bytes.Buffer
err = tmpl.ExecuteTemplate(&htmlBuffer, "html", data)
if err != nil {
return "", fmt.Errorf("HTML template execution error: %v", err)
}
// In a real application, you would use these to send an email
// For this example, we'll just return the HTML version
return htmlBuffer.String(), nil
}
func main() { customer := Customer{ Name: “John Doe”, Email: “[email protected]”, LastPurchase: time.Now().AddDate(0, 0, -30), // 30 days ago }
emailHTML, err := generateEmail(customer)
if err != nil {
log.Fatalf("Error generating email: %v", err)
}
fmt.Println("Generated email HTML:")
fmt.Println(emailHTML)
}
// Example 3: Configuration File Generator package main
import ( “fmt” “os” “path/filepath” “text/template” )
type DatabaseConfig struct { Host string Port int User string Password string Database string MaxConns int SSL bool }
type ServerConfig struct { Host string Port int LogLevel string TLS bool CertFile string KeyFile string RateLimit int }
type Config struct { Environment string Database DatabaseConfig Server ServerConfig Features map[string]bool }
func generateConfigs(baseConfig Config) error { // Define environments to generate configs for environments := []string{“dev”, “staging”, “production”}
// Create templates directory if it doesn't exist
if err := os.MkdirAll("configs", 0755); err != nil {
return fmt.Errorf("failed to create configs directory: %v", err)
}
// Define template functions
funcMap := template.FuncMap{
"indent": func(n int, s string) string {
padding := ""
for i := 0; i < n; i++ {
padding += " "
}
return padding + s
},
"toLowerCase": func(s string) string {
return s
},
}
// Define templates for different output formats
templates := map[string]string{
"json": `{
“environment”: ”{{.Environment}}”,
“database”: {
“host”: ”{{.Database.Host}}”,
“port”: {{.Database.Port}},
“user”: ”{{.Database.User}}”,
“password”: ”{{.Database.Password}}”,
“database”: ”{{.Database.Database}}”,
“maxConns”: {{.Database.MaxConns}},
“ssl”: {{.Database.SSL}}
},
“server”: {
“host”: ”{{.Server.Host}}”,
“port”: {{.Server.Port}},
“logLevel”: ”{{.Server.LogLevel}}”,
“tls”: {{.Server.TLS}},
“certFile”: ”{{.Server.CertFile}}”,
“keyFile”: ”{{.Server.KeyFile}}”,
“rateLimit”: {{.Server.RateLimit}}
},
“features”: {
{{first := true}}
{{range key, value := .Features}}
{{if first}}{{first = false}}{{else}},{{end}}
"{{key}}”: {{value}}
{{end}}
}
}`,
"yaml": `environment: {{.Environment}}
database:
host: {{.Database.Host}}
port: {{.Database.Port}}
user: {{.Database.User}}
password: {{.Database.Password}}
database: {{.Database.Database}}
maxConns: {{.Database.MaxConns}}
ssl: {{.Database.SSL}}
server:
host: {{.Server.Host}}
port: {{.Server.Port}}
logLevel: {{.Server.LogLevel}}
tls: {{.Server.TLS}}
certFile: {{.Server.CertFile}}
keyFile: {{.Server.KeyFile}}
rateLimit: {{.Server.RateLimit}}
features:
{{range key, value := .Features}}
{{key}}: {{$value}}
{{end}}, "toml": environment = ”{{.Environment}}”
[database] host = ”{{.Database.Host}}” port = {{.Database.Port}} user = ”{{.Database.User}}” password = ”{{.Database.Password}}” database = ”{{.Database.Database}}” maxConns = {{.Database.MaxConns}} ssl = {{.Database.SSL}}
[server] host = ”{{.Server.Host}}” port = {{.Server.Port}} logLevel = ”{{.Server.LogLevel}}” tls = {{.Server.TLS}} certFile = ”{{.Server.CertFile}}” keyFile = ”{{.Server.KeyFile}}” rateLimit = {{.Server.RateLimit}}
[features] {{range value := .Features}} {{key}} = {{value}} {{end}}`, }
// Parse templates
parsedTemplates := make(map[string]*template.Template)
for format, templateContent := range templates {
tmpl, err := template.New(format).Funcs(funcMap).Parse(templateContent)
if err != nil {
return fmt.Errorf("error parsing %s template: %v", format, err)
}
parsedTemplates[format] = tmpl
}
// Generate configs for each environment and format
for _, env := range environments {
// Create a copy of the base config and customize for this environment
envConfig := baseConfig
envConfig.Environment = env
// Adjust configuration based on environment
switch env {
case "dev":
envConfig.Database.Host = "localhost"
envConfig.Database.SSL = false
envConfig.Server.TLS = false
envConfig.Server.RateLimit = 0 // No rate limiting in dev
case "staging":
envConfig.Database.Host = "staging-db.example.com"
envConfig.Database.SSL = true
envConfig.Server.TLS = true
envConfig.Server.RateLimit = 100
case "production":
envConfig.Database.Host = "db.example.com"
envConfig.Database.SSL = true
envConfig.Server.TLS = true
envConfig.Server.RateLimit = 50
envConfig.Server.LogLevel = "warn" // Less verbose in production
}
// Generate each format
for format, tmpl := range parsedTemplates {
// Create file name
fileName := filepath.Join("configs", fmt.Sprintf("config.%s.%s", env, format))
// Create file
file, err := os.Create(fileName)
if err != nil {
return fmt.Errorf("error creating config file %s: %v", fileName, err)
}
defer file.Close()
// Execute template
if err := tmpl.Execute(file, envConfig); err != nil {
return fmt.Errorf("error executing template for %s: %v", fileName, err)
}
fmt.Printf("Generated config file: %s\n", fileName)
}
}
return nil
}
func main() { // Base configuration config := Config{ Environment: “base”, // Will be overridden Database: DatabaseConfig{ Port: 5432, User: “app_user”, Password: “secret_password”, // In a real app, use environment variables Database: “myapp”, MaxConns: 20, }, Server: ServerConfig{ Host: “0.0.0.0”, Port: 8080, LogLevel: “info”, CertFile: “certs/server.crt”, KeyFile: “certs/server.key”, }, Features: map[string]bool{ “newUserSignup”: true, “analytics”: true, “notifications”: true, “betaFeature”: false, }, }
if err := generateConfigs(config); err != nil {
fmt.Printf("Error generating configs: %v\n", err)
os.Exit(1)
}
fmt.Println("Configuration files generated successfully!")
}