SoFunction
Updated on 2025-03-05

Detailed explanation of the Golang HTML template usage guide example

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>© {{.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">&laquo;</a>
            <a href="?page={{subtract .CurrentPage 1}}" rel="external nofollow"  class="page-link prev">&lsaquo;</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">&rsaquo;</a>
            <a href="?page={{.TotalPages}}" rel="external nofollow"  class="page-link last">&raquo;</a>
        {{end}}
    {{end}}
</div>
{{end}}

3. Complete application example

3.1 Blog system template

&lt;!-- templates/blog/ --&gt;
{{define "content"}}
&lt;div class="blog-list"&gt;
    &lt;div class="filters"&gt;
        &lt;div class="search"&gt;
            &lt;input type="text" placeholder="Search for articles..." 
                   value="{{.Query}}" &gt;
        &lt;/div&gt;
        &lt;div class="categories"&gt;
            {{range .Categories}}
            &lt;a href="/blog?category={{.Slug}}" rel="external nofollow"  
               class="category {{if eq $.CurrentCategory .Slug}}active{{end}}"&gt;
                {{.Name}} ({{.Count}})
            &lt;/a&gt;
            {{end}}
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="articles"&gt;
        {{range .Posts}}
        &lt;article class="post-card"&gt;
            {{if .Image}}
            &lt;div class="post-image"&gt;
                &lt;img src="{{.Image}}" alt="{{.Title}}"&gt;
            &lt;/div&gt;
            {{end}}
            &lt;div class="post-content"&gt;
                &lt;h2&gt;&lt;a href="/blog/{{.Slug}}" rel="external nofollow" &gt;{{.Title}}&lt;/a&gt;&lt;/h2&gt;
                &lt;div class="post-meta"&gt;
                    &lt;span class="author"&gt;{{.Author}}&lt;/span&gt;
                    &lt;span class="date"&gt;{{formatDate .CreatedAt "2006-01-02"}}&lt;/span&gt;
                    &lt;span class="category"&gt;{{.Category}}&lt;/span&gt;
                &lt;/div&gt;
                &lt;p class="excerpt"&gt;{{truncate .Content 200}}&lt;/p&gt;
                &lt;div class="tags"&gt;
                    {{range .Tags}}
                    &lt;a href="/blog?tag={{.}}" rel="external nofollow"  class="tag"&gt;{{.}}&lt;/a&gt;
                    {{end}}
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/article&gt;
        {{else}}
        &lt;div class="no-posts"&gt;
            No article yet
        &lt;/div&gt;
        {{end}}
    &lt;/div&gt;
    {{template "pagination" .Pagination}}
&lt;/div&gt;
{{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) &lt;= 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 =&gt; {
        ('submit', function(e) {
            const requiredFields = ('[required]');
            let valid = true;
            (field =&gt; {
                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 = () =&gt; {
            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!