Golang : Create unique title slugs example
A simple example on how to create title slug from a string and also demonstrate what you can do in case the title slug is not unique after querying the database. In this example, we append the number from 1 to 10 in case there's a conflict of title slugs in the database. The range of numbers from 1 to 10 should be sufficient. Feel free to increase to 100 to ensure there are more rooms to generate unique title slugs.
Here you go!
package main
import (
"fmt"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
"regexp"
"strconv"
"strings"
"unicode"
)
func isMn(r rune) bool {
return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks
}
func stringToSlug(s string) (string, error) {
str := []byte(strings.ToLower(s))
// convert all spaces to dash
regE := regexp.MustCompile("[[:space:]]")
str = regE.ReplaceAll(str, []byte("-"))
// remove all blanks such as tab
regE = regexp.MustCompile("[[:blank:]]")
str = regE.ReplaceAll(str, []byte(""))
// remove all punctuations with the exception of dash
regE = regexp.MustCompile("[!/:-@[-`{-~]")
str = regE.ReplaceAll(str, []byte(""))
regE = regexp.MustCompile("/[^\x20-\x7F]/")
str = regE.ReplaceAll(str, []byte(""))
regE = regexp.MustCompile("`&(amp;)?#?[a-z0-9]+;`i")
str = regE.ReplaceAll(str, []byte("-"))
regE = regexp.MustCompile("`&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);`i")
str = regE.ReplaceAll(str, []byte("\\1"))
regE = regexp.MustCompile("`[^a-z0-9]`i")
str = regE.ReplaceAll(str, []byte("-"))
regE = regexp.MustCompile("`[-]+`")
str = regE.ReplaceAll(str, []byte("-"))
strReplaced := strings.Replace(string(str), "&", "", -1)
strReplaced = strings.Replace(strReplaced, `"`, "", -1)
strReplaced = strings.Replace(strReplaced, "&", "-", -1)
strReplaced = strings.Replace(strReplaced, "--", "-", -1)
if strings.HasPrefix(strReplaced, "-") || strings.HasPrefix(strReplaced, "--") {
strReplaced = strings.TrimPrefix(strReplaced, "-")
strReplaced = strings.TrimPrefix(strReplaced, "--")
}
if strings.HasSuffix(strReplaced, "-") || strings.HasSuffix(strReplaced, "--") {
strReplaced = strings.TrimSuffix(strReplaced, "-")
strReplaced = strings.TrimSuffix(strReplaced, "--")
}
// normalize unicode strings and remove all diacritical/accents marks
// see https://www.socketloop.com/tutorials/golang-normalize-unicode-strings-for-comparison-purpose
t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
slug, _, err := transform.String(t, strReplaced)
if err != nil {
return "", err
}
return strings.TrimSpace(slug), nil
}
func main() {
testStr := "?This is a test-title with question mark ? and& \" exclaimation mark !"
testSlug, err := stringToSlug(testStr)
if err != nil {
panic(err)
}
fmt.Printf("%v to:\n %v\n", testStr, testSlug)
// in case you encounter a situation where the slug title is not unique after you query the database.
// just append a number the string with a number to make it unique
// NOTE : You will have to make a function of your own here to query your database
newSlug := ""
for i := 1; i <= 10; i++ {
newSlug = testSlug + "-" + strconv.Itoa(i)
// here is where you want to query your database
// if newSlug is unique, break
// let's pretend that number 5 is unique after querying
// the database 5 times.
if i == 5 {
break
}
}
// our unique slug title
fmt.Println(newSlug)
}
Output:
?This is a test-title with question mark ? and& " exclaimation mark ! to:
this-is-a-test-title-with-question-mark-and-exclaimation-mark
this-is-a-test-title-with-question-mark-and-exclaimation-mark-5
NOTE: Before inserting the title slugs into your database, it would be advisable to trim the title first.
References:
https://www.socketloop.com/tutorials/golang-format-strings-to-seo-friendly-url-example
https://www.socketloop.com/tutorials/golang-increment-string-example
See also : Golang : Format strings to SEO friendly URL example
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+6.7k Golang : How to setup a disk space used monitoring service with Telegram bot
+10.9k Golang : Proper way to test CIDR membership of an IP 4 or 6 address example
+9.7k Golang : Check if user agent is a robot or crawler example
+9k Golang : How to check if a string with spaces in between is numeric?
+10.8k Golang : Read until certain character to break for loop
+5.8k Fix ERROR 2003 (HY000): Can't connect to MySQL server on 'IP address' (111)
+14.8k Golang : How to check if IP address is in range
+7.3k Golang : Set horizontal, vertical scroll bars policies and disable interaction on Qt image
+5.1k PHP : Hide PHP version information from curl
+6.4k Golang : Experimental emojis or emoticons icons programming language
+14.4k Golang : Get URI segments by number and assign as variable example