短链接服务用Base62编码自增ID实现唯一无碰撞映射,内存map存储键值对,HTTP 302重定向跳转,支持高并发需sync.RWMutex保护。

核心思路:用哈希+映射表实现短链接生成与跳转
URL短链接服务本质是将长URL映射为短字符串(如 abc123),用户访问短链接时,服务查表重定向到原始URL。Golang 实现的关键在于:唯一性保证、高效查询、避免碰撞、支持高并发。不需要复杂数据库,用内存 map + 持久化(如 Redis 或 BoltDB)即可起步。
生成短链接:Base62 编码 + 自增ID 或哈希去重
推荐使用「自增ID转 Base62」方式,简单、有序、无碰撞、易扩展。Base62(0–9 + a–z + A–Z)比 Base64 更适合 URL,不包含 +/ 和 = 等需编码的字符。
- 维护一个全局递增的整数 ID(可用原子操作或数据库自增字段)
- 将 ID 转为 Base62 字符串(例如 ID=12345 → "vj3")
- 将
vj3 → https://example.com/very/long/path存入映射表(map 或存储) - 返回完整短链接,如
https://s.co/vj3
若需支持分布式,可用 Snowflake ID 或 Redis INCR + 前缀隔离;若坚持哈希(如 MD5 取前6位),务必加碰撞检测和重试逻辑。
跳转逻辑:HTTP 302 重定向 + 路由匹配
收到请求如 GET /vj3 时,提取路径段 vj3,查表获取原始 URL,返回 302 临时重定向响应:
立即学习“go语言免费学习笔记(深入)”;
- 用
http.HandleFunc或gorilla/mux定义通配路由,如/{code} - 根据
code查询映射表(注意并发安全,用sync.RWMutex保护 map) - 查到则调用
http.Redirect(w, r, targetURL, http.StatusFound) - 查不到返回 404,可加日志或统计失败请求
基础可运行示例(内存版,含 Base62 转换)
以下代码可直接保存为 main.go 运行,访问 http://localhost:8080/api/shorten 提交长链接,再访问 http://localhost:8080/{code} 即跳转:
// Base62 字符集
const base62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func toBase62(n int64) string {
if n == 0 {
return "0"
}
var result []byte
for n > 0 {
result = append(result, base62[n%62])
n /= 62
}
// 反转字节切片
for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
result[i], result[j] = result[j], result[i]
}
return string(result)
}
var (
mu sync.RWMutex
store = make(map[string]string) // code → long URL
nextID int64 = 1
)
func shortenHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
longURL := r.FormValue("url")
if longURL == "" {
http.Error(w, "Missing 'url' parameter", http.StatusBadRequest)
return
}
mu.Lock()
code := toBase62(nextID)
nextID++
store[code] = longURL
mu.Unlock()
json.NewEncoder(w).Encode(map[string]string{"short": "http://localhost:8080/" + code})
}
func redirectHandler(w http.ResponseWriter, r *http.Request) {
code := strings.TrimPrefix(r.URL.Path, "/")
mu.RLock()
longURL, ok := store[code]
mu.RUnlock()
if !ok {
http.NotFound(w, r)
return
}
http.Redirect(w, r, longURL, http.StatusFound)
}
func main() {
http.HandleFunc("/api/shorten", shortenHandler)
http.HandleFunc("/", redirectHandler)
fmt.Println("Server running on :8080")
http.ListenAndServe(":8080", nil)
}
该版本轻量、无依赖,适合学习和原型验证。上线前建议替换为 Redis 存储、增加 HTTPS、限流、防刷、自定义短码、过期时间等能力。










