go 47 lines · 8 steps

Turning titles into URL slugs in Go

A small package that strips accents, lowercases, and hyphenates any string into a clean, collision-free URL slug.

Explained by highlit
1package slug
2 
3import (
4 "regexp"
5 "strings"
6 "unicode"
7 
8 "golang.org/x/text/runes"
9 "golang.org/x/text/transform"
10 "golang.org/x/text/unicode/norm"
11)
12 
13var (
14 nonAlphanumeric = regexp.MustCompile(`[^a-z0-9]+`)
15 dashRuns = regexp.MustCompile(`-{2,}`)
16)
17 
18func Make(title string) string {
19 t := transform.Chain(
20 norm.NFD,
21 runs.Remove(runes.In(unicode.Mn)),
22 norm.NFC,
23 )
24 
25 ascii, _, err := transform.String(t, title)
26 if err != nil {
27 ascii = title
28 }
29 
30 ascii = strings.ToLower(ascii)
31 ascii = nonAlphanumeric.ReplaceAllString(ascii, "-")
32 ascii = dashRuns.ReplaceAllString(ascii, "-")
33 ascii = strings.Trim(ascii, "-")
34 
35 return ascii
36}
37 
38func MakeUnique(title string, exists func(string) bool) string {
39 base := Make(title)
40 candidate := base
41 
42 for i := 2; exists(candidate); i++ {
43 candidate = base + "-" + strconv.Itoa(i)
44 }
45 
46 return candidate
47}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Decompose-then-strip with NFD plus removing combining marks is the reliable way to fold accented characters to plain ASCII.
  2. 2Precompiling regexes at package scope avoids recompiling them on every call.
  3. 3Uniqueness can be layered on top of a pure slug function by probing a caller-supplied existence check.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Turning titles into URL slugs in Go — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code