go
56 lines · 8 steps
Rendering HTML pages with Gin handlers
Two Gin handlers fetch data through a repository and render templates, with graceful error pages when something fails.
Explained by
highlit
1package handlers
2
3import (
4 "net/http"
5 "time"
6
7 "github.com/gin-gonic/gin"
8)
9
10type ArticleHandler struct {
11 Articles ArticleRepository
12}
13
14func (h *ArticleHandler) Index(c *gin.Context) {
15 articles, err := h.Articles.Recent(c.Request.Context(), 20)
16 if err != nil {
17 c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
18 "title": "Something went wrong",
19 "message": "We couldn't load the articles right now.",
20 })
21 return
22 }
23
24 c.HTML(http.StatusOK, "articles/index.tmpl", gin.H{
25 "title": "Latest Articles",
26 "articles": articles,
27 "year": time.Now().Year(),
28 "flash": flashFrom(c),
29 })
30}
31
32func (h *ArticleHandler) Show(c *gin.Context) {
33 article, err := h.Articles.BySlug(c.Request.Context(), c.Param("slug"))
34 if err != nil {
35 c.HTML(http.StatusNotFound, "error.tmpl", gin.H{
36 "title": "Not found",
37 "message": "That article has wandered off.",
38 })
39 return
40 }
41
42 c.HTML(http.StatusOK, "articles/show.tmpl", gin.H{
43 "title": article.Title,
44 "article": article,
45 "year": time.Now().Year(),
46 })
47}
48
49func flashFrom(c *gin.Context) string {
50 if v, ok := c.Get("flash"); ok {
51 if s, ok := v.(string); ok {
52 return s
53 }
54 }
55 return ""
56}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Holding a repository on the handler struct keeps data access injectable and testable instead of hard-wired.
- 2Checking the error before rendering lets each failure return its own status code and friendly page.
- 3A small helper that type-asserts context values isolates fragile lookups so handlers stay readable.
Related explainers
go
package main import ( "errors"
Parsing and validating CLI flags in Go
cli-parsing
validation
error-handling
Intermediate
8 steps
java
public class ThumbnailProcessor { private static final int MAX_CONCURRENCY = 4;
Bounded parallel thumbnail rendering in Java
concurrency
thread-pool
futures
Intermediate
7 steps
go
package cache import ( "container/list"
Building a generic LRU cache in Go
lru-cache
generics
linked-list
Intermediate
8 steps
go
package model import ( "encoding/json"
Custom JSON marshaling in Go
json
serialization
interfaces
Intermediate
5 steps
go
func (h *TransactionHandler) ExportCSV(c *gin.Context) { ctx := c.Request.Context() filters := parseTransactionFilters(c)
Streaming a CSV export in Gin
streaming
csv-export
database-cursor
Intermediate
8 steps
php
<?php namespace App\Rules;
How a custom phone validation rule works in Laravel
validation
custom-rules
dependency
Intermediate
6 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/rendering-html-pages-with-gin-handlers-explained-go-e3bd/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.