go
66 lines · 8 steps
Building a query URL from a Filter struct in Go
A Filter struct turns optional search criteria into a safely encoded URL query string.
Explained by
highlit
1package search
2
3import (
4 "net/url"
5 "strconv"
6 "strings"
7 "time"
8)
9
10type Filter struct {
11 Query string
12 Categories []string
13 MinPrice float64
14 MaxPrice float64
15 InStock bool
16 UpdatedAt time.Time
17 Page int
18 PerPage int
19 SortBy string
20}
21
22func (f Filter) URL(base string) (string, error) {
23 u, err := url.Parse(base)
24 if err != nil {
25 return "", err
26 }
27
28 q := u.Query()
29
30 if s := strings.TrimSpace(f.Query); s != "" {
31 q.Set("q", s)
32 }
33 for _, c := range f.Categories {
34 q.Add("category", c)
35 }
36 if f.MinPrice > 0 {
37 q.Set("price_min", strconv.FormatFloat(f.MinPrice, 'f', 2, 64))
38 }
39 if f.MaxPrice > 0 {
40 q.Set("price_max", strconv.FormatFloat(f.MaxPrice, 'f', 2, 64))
41 }
42 if f.InStock {
43 q.Set("in_stock", "true")
44 }
45 if !f.UpdatedAt.IsZero() {
46 q.Set("updated_since", f.UpdatedAt.UTC().Format(time.RFC3339))
47 }
48
49 page := f.Page
50 if page < 1 {
51 page = 1
52 }
53 perPage := f.PerPage
54 if perPage < 1 || perPage > 100 {
55 perPage = 25
56 }
57 q.Set("page", strconv.Itoa(page))
58 q.Set("per_page", strconv.Itoa(perPage))
59
60 if f.SortBy != "" {
61 q.Set("sort", f.SortBy)
62 }
63
64 u.RawQuery = q.Encode()
65 return u.String(), nil
66}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Only setting query params for non-empty values keeps URLs clean and avoids sending meaningless defaults.
- 2Clamping pagination inputs to sane bounds protects downstream services from bad or hostile values.
- 3Using url.Values and Encode handles escaping for you, so never hand-concatenate query strings.
Related explainers
go
package handlers import ( "net/http"
Content negotiation in Gin handlers
content-negotiation
struct-tags
rest-api
Intermediate
4 steps
go
package ratelimit import ( "context"
A token bucket rate limiter in Go
rate-limiting
concurrency
goroutines
Intermediate
7 steps
go
package handlers type BookURI struct { Collection string `uri:"collection" binding:"required,alphanum"`
Validating URI params in a Gin handler
input validation
struct binding
error handling
Intermediate
7 steps
go
package cache import ( "context"
Cache-aside reads with singleflight in Go
caching
singleflight
concurrency
Advanced
8 steps
go
package httpx import ( "net/http"
A retrying HTTP transport in Go
http
middleware
retry
Intermediate
8 steps
go
package config import ( "fmt"
Loading typed config from environment variables in Go
configuration
environment-variables
type-parsing
Beginner
8 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/building-a-query-url-from-a-filter-struct-in-go-explained-go-1c4c/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.