Golang HTML Template Usage Guide
1. Basic template example
1.1 Simple page template
<!-- templates/ --> <!DOCTYPE html> <html> <head> <title>{{.Title}}</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/css/" rel="external nofollow" > </head> <body> <header> <h1>{{.Title}}</h1> <nav> <a href="/" rel="external nofollow" >front page</a> <a href="/about" rel="external nofollow" >about</a> <a href="/contact" rel="external nofollow" >Contact Us</a> </nav> </header> <main> {{template "content" .}} </main> <footer> <p>&copy; {{.Year}} My website</p> </footer> </body> </html>
// package main import ( "html/template" "net/http" "time" ) func main() { ("/", func(w , r *) { tmpl := (("templates/")) data := struct { Title string Year int }{ Title: "My website", Year: ().Year(), } (w, data) }) (":8080", nil) }
1.2 List rendering
<!-- templates/ --> {{define "content"}} <div class="products"> <h2>Product List</h2> <div class="product-grid"> {{range .Products}} <div class="product-card"> <img src="{{.Image}}" alt="{{.Name}}"> <h3>{{.Name}}</h3> <p>{{.Description}}</p> <div class="price">{{formatPrice .Price}}</div> {{if .InStock}} <button class="buy-btn">Buy</button> {{else}} <button class="out-of-stock" disabled>out of stock</button> {{end}} </div> {{end}} </div> </div> {{end}}
type Product struct { Name string Description string Price float64 Image string InStock bool } func productsHandler(w , r *) { funcMap := { "formatPrice": func(price float64) string { return ("¥%.2f", price) }, } tmpl := ("").Funcs(funcMap) tmpl = (( "templates/", "templates/", )) data := struct { Title string Year int Products []Product }{ Title: "Product List", Year: ().Year(), Products: []Product{ { Name: "Product 1", Description: "This is the description of Product 1", Price: 99.99, Image: "/static/images/", InStock: true, }, // More products... }, } (w, data) }
2. Advanced template examples
2.1 Nested Template
<!-- templates/components/ --> {{define "header"}} <header class="site-header"> <div class="logo"> <img src="/static/images/" alt="Logo"> </div> <nav class="main-nav"> <ul> {{range .NavItems}} <li class="{{if eq $.CurrentPage .Link}}active{{end}}"> <a href="{{.Link}}" rel="external nofollow" >{{.Text}}</a> </li> {{end}} </ul> </nav> {{if .User}} <div class="user-menu"> <span>welcome, {{.}}</span> <a href="/logout" rel="external nofollow" >quit</a> </div> {{else}} <div class="auth-buttons"> <a href="/login" rel="external nofollow" class="btn btn-login">Log in</a> <a href="/register" rel="external nofollow" class="btn btn-register">register</a> </div> {{end}} </header> {{end}}
2.2 Form processing
<!-- templates/ --> {{define "content"}} <div class="form-container"> <h2>{{.FormTitle}}</h2> {{with .FormError}} <div class="error-message">{{.}}</div> {{end}} <form method="POST" action="{{.FormAction}}" enctype="multipart/form-data"> {{range .Fields}} <div class="form-group"> <label for="{{.ID}}">{{.Label}}{{if .Required}}*{{end}}</label> {{if eq .Type "text"}} <input type="text" name="{{.Name}}" value="{{.Value}}" {{if .Required}}required{{end}} {{with .Pattern}}pattern="{{.}}"{{end}}> {{else if eq .Type "textarea"}} <textarea name="{{.Name}}" {{if .Required}}required{{end}}>{{.Value}}</textarea> {{else if eq .Type "select"}} <select name="{{.Name}}" {{if .Required}}required{{end}}> {{range .Options}} <option value="{{.Value}}" {{if eq .Value $.Selected}}selected{{end}}> {{.Text}} </option> {{end}} </select> {{end}} {{with .Error}} <span class="field-error">{{.}}</span> {{end}} </div> {{end}} <div class="form-actions"> <button type="submit" class="btn btn-primary">{{.SubmitText}}</button> <button type="reset" class="btn btn-secondary">Reset</button> </div> </form> </div> {{end}}
2.3 Pagination Components
<!-- templates/components/ --> {{define "pagination"}} <div class="pagination"> {{if gt .TotalPages 1}} {{if gt .CurrentPage 1}} <a href="?page=1" rel="external nofollow" class="page-link first">«</a> <a href="?page={{subtract .CurrentPage 1}}" rel="external nofollow" class="page-link prev">‹</a> {{end}} {{range $i := range (sequence .TotalPages)}} {{if and (ge $i (subtract $.CurrentPage 2)) (le $i (add $.CurrentPage 2))}} <a href="?page={{add $i 1}}" rel="external nofollow" class="page-link {{if eq $i (subtract $.CurrentPage 1)}}active{{end}}"> {{add $i 1}} </a> {{end}} {{end}} {{if lt .CurrentPage .TotalPages}} <a href="?page={{add .CurrentPage 1}}" rel="external nofollow" class="page-link next">›</a> <a href="?page={{.TotalPages}}" rel="external nofollow" class="page-link last">»</a> {{end}} {{end}} </div> {{end}}
3. Complete application example
3.1 Blog system template
<!-- templates/blog/ --> {{define "content"}} <div class="blog-list"> <div class="filters"> <div class="search"> <input type="text" placeholder="Search for articles..." value="{{.Query}}" > </div> <div class="categories"> {{range .Categories}} <a href="/blog?category={{.Slug}}" rel="external nofollow" class="category {{if eq $.CurrentCategory .Slug}}active{{end}}"> {{.Name}} ({{.Count}}) </a> {{end}} </div> </div> <div class="articles"> {{range .Posts}} <article class="post-card"> {{if .Image}} <div class="post-image"> <img src="{{.Image}}" alt="{{.Title}}"> </div> {{end}} <div class="post-content"> <h2><a href="/blog/{{.Slug}}" rel="external nofollow" >{{.Title}}</a></h2> <div class="post-meta"> <span class="author">{{.Author}}</span> <span class="date">{{formatDate .CreatedAt "2006-01-02"}}</span> <span class="category">{{.Category}}</span> </div> <p class="excerpt">{{truncate .Content 200}}</p> <div class="tags"> {{range .Tags}} <a href="/blog?tag={{.}}" rel="external nofollow" class="tag">{{.}}</a> {{end}} </div> </div> </article> {{else}} <div class="no-posts"> No article yet </div> {{end}} </div> {{template "pagination" .Pagination}} </div> {{end}}
type BlogData struct { Query string CurrentCategory string Categories []Category Posts []Post Pagination Pagination } type Category struct { Name string Slug string Count int } type Post struct { Title string Slug string Content string Author string Image string Category string Tags []string CreatedAt } type Pagination struct { CurrentPage int TotalPages int TotalItems int } func blogHandler(w , r *) { funcMap := { "formatDate": func(t , layout string) string { return (layout) }, "truncate": func(s string, l int) string { if len(s) <= l { return s } return s[:l] + "..." }, } tmpl := ("").Funcs(funcMap) tmpl = (( "templates/", "templates/blog/", "templates/components/", )) data := BlogData{ Query: ().Get("q"), CurrentCategory: ().Get("category"), Categories: []Category{ {Name: "technology", Slug: "tech", Count: 10}, {Name: "Life", Slug: "life", Count: 5}, }, Posts: []Post{ { Title: "Sample Article", Slug: "example-post", Content: "This is the content of an example article...", Author: "Author's name", Category: "tech", Tags: []string{"Go", "Web"}, CreatedAt: (), }, }, Pagination: Pagination{ CurrentPage: 1, TotalPages: 5, TotalItems: 45, }, } (w, data) }
4. CSS style example
/* static/css/ */ /* Basic style */ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.6; margin: 0; padding: 0; color: #333; } /* Head style */ .site-header { background: #fff; box-shadow: 0 2px 4px rgba(0,0,0,0.1); padding: 1rem; } .main-nav ul { list-style: none; display: flex; gap: 1rem; } /* Product card style */ .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 2rem; padding: 2rem; } .product-card { border: 1px solid #eee; border-radius: 8px; overflow: hidden; transition: transform 0.2s; } .product-card:hover { transform: translateY(-5px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); } /* Form Style */ .form-container { max-width: 600px; margin: 2rem auto; padding: 2rem; background: #fff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .form-group { margin-bottom: 1.5rem; } /* Blog List Style */ .blog-list { max-width: 1200px; margin: 0 auto; padding: 2rem; } .post-card { display: grid; grid-template-columns: 200px 1fr; gap: 1.5rem; margin-bottom: 2rem; padding: 1rem; background: #fff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* Pagination style */ .pagination { display: flex; justify-content: center; gap: 0.5rem; margin: 2rem 0; } .page-link { padding: 0.5rem 1rem; border: 1px solid #ddd; border-radius: 4px; color: #333; text-decoration: none; } . { background: #007bff; color: #fff; border-color: #007bff; }
5. JavaScript interaction examples
// static/js/ ('DOMContentLoaded', function() { // Search function const searchInput = ('searchInput'); if (searchInput) { ('input', debounce(function(e) { const query = ; = `/blog?q=${encodeURIComponent(query)}`; }, 500)); } // Form Verification const forms = ('form'); (form => { ('submit', function(e) { const requiredFields = ('[required]'); let valid = true; (field => { if (!()) { valid = false; ('error'); } else { ('error'); } }); if (!valid) { (); alert('Please fill in all required fields'); } }); }); }); // Tool functionfunction debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }
Summarize
Template organization
- Use nested templates to implement code reuse
- Keep the template structure clear
- Use template functions reasonably
Best Practices
- Using semantic HTML
- Keep CSS modular
- Implement responsive design
- Add appropriate interaction effects
Performance optimization
- Cache compiled templates
- Compress static resources
- Accelerate with CDN
- Implement lazy loading
This is the end of this article about the guide to using Golang HTML templates. For more information about Golang HTML templates, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!