如何用Golang開發(fā)一個短鏈接服務(wù) 使用map內(nèi)存存儲實現(xiàn)

golangmap實現(xiàn)短鏈接服務(wù)的核心是通過兩個map維護長短鏈雙向映射,配合自增id生成base62短串,并通過http接口提供生成和跳轉(zhuǎn)功能。1. 使用shorttolong和longtoshort兩個map實現(xiàn)雙向映射,避免重復(fù)生成相同短鏈;2. 通過自增id結(jié)合base62編碼生成唯一短標識符;3. 利用net/http庫創(chuàng)建shorten接口接收長鏈接生成短鏈、redirect接口根據(jù)短鏈跳轉(zhuǎn)原鏈接;4. 數(shù)據(jù)存儲于內(nèi)存適合原型開發(fā),但需注意重啟丟失、并發(fā)安全及沖突風(fēng)險。

如何用Golang開發(fā)一個短鏈接服務(wù) 使用map內(nèi)存存儲實現(xiàn)

短鏈接服務(wù)的核心是將一個長 URL 映射成一個簡短的字符串,用戶訪問這個短串就能跳轉(zhuǎn)到原始地址。如果你只是想快速實現(xiàn)一個基礎(chǔ)版本,用 golang 的 map 做內(nèi)存存儲是一個簡單又直接的辦法。

如何用Golang開發(fā)一個短鏈接服務(wù) 使用map內(nèi)存存儲實現(xiàn)

下面我們就來看看怎么一步步用 Golang + map 實現(xiàn)一個最簡單的短鏈接服務(wù)。

如何用Golang開發(fā)一個短鏈接服務(wù) 使用map內(nèi)存存儲實現(xiàn)


1. 設(shè)計數(shù)據(jù)結(jié)構(gòu)和映射關(guān)系

我們使用兩個 map 來保存長短鏈接之間的雙向映射:

立即學(xué)習(xí)go語言免費學(xué)習(xí)筆記(深入)”;

  • 一個用于短鏈 → 長鏈(供跳轉(zhuǎn)時查找)
  • 一個用于長鏈 → 短鏈(避免重復(fù)生成)
var shortToLong = make(map[string]string) var longToShort = make(map[string]string)

這樣設(shè)計的好處是,當用戶提交相同的長鏈接時,我們可以直接返回之前生成的短鏈接,而不是每次都生成新的。

如何用Golang開發(fā)一個短鏈接服務(wù) 使用map內(nèi)存存儲實現(xiàn)


2. 生成短鏈接標識符

短鏈接的關(guān)鍵在于生成一個唯一的、較短的字符串作為標識。常見做法是使用 Base62 編碼(0-9a-zA-Z),也可以結(jié)合遞增 ID 或隨機生成。

這里我們采用一個簡單的自增 ID 方式,每次生成后轉(zhuǎn)換為 Base62:

func generateShortKey(id int) string {     const base62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"     result := ""     for id > 0 {         id--         result = string(base62[id%62]) + result         id /= 62     }     return result }

比如 ID=1 會生成 “a”,ID=10000 會生成 “27g”,足夠簡潔且不易沖突。


3. 處理請求邏輯

我們使用 Go 的標準庫 net/http 搭建一個簡單的 HTTP 服務(wù),包含兩個接口:

  • /shorten:接收長鏈接,返回短鏈接
  • /{key}:根據(jù)短鏈接 key 跳轉(zhuǎn)到原鏈接

接口一:生成短鏈接

var counter = 1  func shortenHandler(w http.ResponseWriter, r *http.Request) {     longURL := r.URL.Query().Get("url")     if longURL == "" {         http.Error(w, "Missing 'url' parameter", http.StatusBadRequest)         return     }      if short, exists := longToShort[longURL]; exists {         fmt.Fprintf(w, "Short URL: http://localhost:8080/%sn", short)         return     }      short := generateShortKey(counter)     counter++      shortToLong[short] = longURL     longToShort[longURL] = short      fmt.Fprintf(w, "Short URL: http://localhost:8080/%sn", short) }

接口二:跳轉(zhuǎn)處理

func redirectHandler(w http.ResponseWriter, r *http.Request) {     parts := strings.Split(r.URL.Path, "/")     if len(parts) < 2 || parts[1] == "" {         http.Error(w, "Invalid short URL", http.StatusBadRequest)         return     }      key := parts[1]     if longURL, exists := shortToLong[key]; exists {         http.Redirect(w, r, longURL, http.StatusFound)     } else {         http.NotFound(w, r)     } }

然后注冊路由并啟動服務(wù):

func main() {     http.HandleFunc("/shorten", shortenHandler)     http.HandleFunc("/", redirectHandler)      fmt.Println("Starting server at :8080")     if err := http.ListenAndServe(":8080", nil); err != nil {         log.Fatal(err)     } }

4. 測試一下

你可以通過瀏覽器或者 cURL 來測試:

  • 生成短鏈接:

    curl "http://localhost:8080/shorten?url=https://example.com/really-long-path?query=abc"
  • 訪問短鏈接跳轉(zhuǎn):

    curl -v http://localhost:8080/a

注意事項和優(yōu)化空間

雖然上面的方法已經(jīng)能跑起來,但還是有些需要注意的地方:

  • 重啟數(shù)據(jù)丟失:因為數(shù)據(jù)存在內(nèi)存里,程序重啟就會清空。如果要持久化,可以考慮加個文件或數(shù)據(jù)庫寫入。
  • 并發(fā)安全問題:多個請求同時操作 map 可能會有競態(tài)條件。可以用 sync.Mutex 或者換成 sync.Map。
  • 短鏈沖突風(fēng)險:如果使用隨機生成而不是自增 ID,需要檢查是否已存在該 key。
  • 性能限制:內(nèi)存存儲適合小規(guī)模使用,如果數(shù)據(jù)量大了就需要上 redis 這樣的緩存系統(tǒng)。

基本上就這些。用 map 實現(xiàn)短鏈接服務(wù)雖然簡單,但很適合練手或做原型開發(fā)。等你熟悉流程后,再擴展功能、換存儲方式都不難。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊14 分享