在 Web 开发中,Slug 是 URL 中的友好标识符,通常用于文章、分类或页面的路径,比如:
arduino
https://example.com/blog/go-slug-generator
在 Go 语言的 Web 项目中,Slug 生成器需要满足以下需求:
- 支持中英文:中文转换为拼音,英文保持不变。
- 去除特殊字符 :仅保留字母、数字和
-
(连字符)。 - 确保唯一性 :如果数据库中已存在相同的 Slug,则自动添加递增后缀(如
example
,example-1
)。
本文将带你一步步实现这个功能!🔥
1. Slug 生成器的实现
(1) 代码示例
go
package utils
import (
"dagicms-server/global"
"fmt"
"github.com/mozillazg/go-pinyin"
"regexp"
"strings"
)
// GenerateSlug 生成 SEO 友好的 slug(支持中英文,去除特殊字符,确保唯一性)
func GenerateSlug(title string, tableName string, id uint) string {
// 1. 处理标题,转换中文为拼音,并保留英文
baseSlug := ConvertToSlug(title)
// 2. 只保留字母、数字、空格和连字符
reg := regexp.MustCompile(`[^a-zA-Z0-9\s-]`)
baseSlug = reg.ReplaceAllString(baseSlug, "")
// 3. 替换空格为连字符
baseSlug = strings.ReplaceAll(baseSlug, " ", "-")
// 4. 处理连字符,去除多余的 `--`
baseSlug = cleanHyphens(baseSlug)
// 5. 如果转换后的 slug 为空,设置默认值
if baseSlug == "" {
baseSlug = "untitled"
}
// 6. 检查数据库,确保 slug 唯一
finalSlug := baseSlug
counter := 1
for {
var exists bool
query := fmt.Sprintf("SELECT EXISTS(SELECT 1 FROM %s WHERE slug = ? AND id != ?)", tableName)
global.GVA_DB.Raw(query, finalSlug, id).Scan(&exists)
if !exists {
break
}
// 若已存在,添加递增数字后缀
finalSlug = fmt.Sprintf("%s-%d", baseSlug, counter)
counter++
}
return finalSlug
}
// ConvertToSlug 处理中英文,转换中文为拼音,英文保留
func ConvertToSlug(input string) string {
var result []string
for _, r := range input {
if isChinese(r) {
// 将中文字符转换为拼音
pinyinArgs := pinyin.NewArgs()
pinyinList := pinyin.LazyPinyin(string(r), pinyinArgs)
if len(pinyinList) > 0 {
result = append(result, pinyinList[0]) // 取拼音
}
} else {
result = append(result, string(r)) // 直接保留英文
}
}
return strings.Join(result, "")
}
// isChinese 判断字符是否为中文
func isChinese(r rune) bool {
return r >= 0x4E00 && r <= 0x9FA5
}
// cleanHyphens 处理连字符,避免 "--" 出现
func cleanHyphens(input string) string {
for strings.Contains(input, "--") {
input = strings.ReplaceAll(input, "--", "-")
}
return strings.Trim(input, "-")
}
2. 代码解析
(1) 处理标题,确保 SEO 友好
css
baseSlug := ConvertToSlug(title)
-
该函数会将 中文转换为拼音,保留英文字符。
-
例如:
scssConvertToSlug("Go 语言编程") // 结果: "Go-yu-yan-bian-cheng" ConvertToSlug("Hello 世界") // 结果: "Hello-shi-jie"
(2) 过滤特殊字符
ini
reg := regexp.MustCompile(`[^a-zA-Z0-9\s-]`)
baseSlug = reg.ReplaceAllString(baseSlug, "")
- 该正则表达式确保只保留:大小写字母、数字、空格、连字符
-
。
(3) 处理空格,确保 URL 友好
ini
baseSlug = strings.ReplaceAll(baseSlug, " ", "-")
- 将所有空格替换为
-
,避免出现%20
这样的 URL 编码问题。
(4) 避免 --
连字符问题
ini
baseSlug = cleanHyphens(baseSlug)
- 该函数确保不会出现
--
,如"hello--world"
会变成"hello-world"
。
(5) 数据库检查,确保唯一性
perl
query := fmt.Sprintf("SELECT EXISTS(SELECT 1 FROM %s WHERE slug = ? AND id != ?)", tableName)
global.GVA_DB.Raw(query, finalSlug, id).Scan(&exists)
if exists {
finalSlug = fmt.Sprintf("%s-%d", baseSlug, counter)
}
-
若数据库已存在相同的 Slug,则自动添加数字后缀,确保唯一性:
example → example-1 → example-2
3. 代码示例
在 Go 项目 中使用这个 Slug 生成器:
go
package main
import (
"fmt"
"your_project/utils"
)
func main() {
title1 := "Go 语言编程"
title2 := "Hello 世界"
title3 := "Golang URL 生成"
slug1 := utils.GenerateSlug(title1, "articles", 1)
slug2 := utils.GenerateSlug(title2, "articles", 2)
slug3 := utils.GenerateSlug(title3, "articles", 3)
fmt.Println(slug1) // 输出: go-yu-yan-bian-cheng
fmt.Println(slug2) // 输出: hello-shi-jie
fmt.Println(slug3) // 输出: golang-url-sheng-cheng
}
4. 总结
✅ 支持中英文 :中文转换拼音,英文保持原样
✅ 去除特殊字符 :仅保留字母、数字和 -
✅ 避免 --
问题 :确保 slug 规范
✅ 唯一性检查:避免数据库冲突
🚀 这样,我们就实现了一个 SEO 友好的 Slug 生成器 ,并且可以轻松集成到 Django / Go Web 项目 中!
👉 如果觉得有用,请点赞 👍 或者分享你的改进建议! 🚀