go 56 lines · 7 steps

Parsing search query params in a Go handler

An HTTP handler that safely reads, validates, and defaults query parameters before running a search.

Explained by highlit
1package handlers
2 
3import (
4 "encoding/json"
5 "net/http"
6 "strconv"
7 "strings"
8)
9 
10type searchParams struct {
11 Query string
12 Tags []string
13 Page int
14 PerPage int
15 SortDesc bool
16}
17 
18func SearchHandler(w http.ResponseWriter, r *http.Request) {
19 if err := r.ParseForm(); err != nil {
20 http.Error(w, "invalid form encoding", http.StatusBadRequest)
21 return
22 }
23 
24 p := searchParams{
25 Query: strings.TrimSpace(r.FormValue("q")),
26 Page: 1,
27 PerPage: 25,
28 SortDesc: r.FormValue("order") == "desc",
29 }
30 
31 for _, tag := range r.Form["tag"] {
32 if tag = strings.TrimSpace(tag); tag != "" {
33 p.Tags = append(p.Tags, tag)
34 }
35 }
36 
37 if page, err := strconv.Atoi(r.FormValue("page")); err == nil && page > 0 {
38 p.Page = page
39 }
40 if per, err := strconv.Atoi(r.FormValue("per_page")); err == nil && per > 0 && per <= 100 {
41 p.PerPage = per
42 }
43 
44 results, total, err := searchArticles(r.Context(), p)
45 if err != nil {
46 http.Error(w, "search failed", http.StatusInternalServerError)
47 return
48 }
49 
50 w.Header().Set("Content-Type", "application/json")
51 json.NewEncoder(w).Encode(map[string]any{
52 "results": results,
53 "total": total,
54 "page": p.Page,
55 })
56}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Start from sensible defaults and only overwrite them when incoming input parses and passes bounds checks.
  2. 2Validating page and per-page limits at the edge protects downstream queries from abusive or malformed input.
  3. 3Guarding each failure with an early return keeps the happy path flat and readable.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Parsing search query params in a Go handler — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code