亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Go 中將 UUID 輸出為短字符串

在 Go 中將 UUID 輸出為短字符串

Go
一只斗牛犬 2022-01-17 19:57:24
是否有內置方式或合理的標準包允許您將標準 UUID 轉換為可以啟用更短 URL 的短字符串?即利用更大范圍的字符[A-Za-z0-9]來輸出更短的字符串。我知道我們可以使用 base64 對字節進行編碼,如下所示,但我想要創建一個看起來像“單詞”的字符串,即 no+和/:id = base64.StdEncoding.EncodeToString(myUuid.Bytes())
查看完整描述

3 回答

?
12345678_0001

TA貢獻1802條經驗 獲得超5個贊

通用唯一標識符 (UUID)是一個 128 位值,即 16 個字節。對于人類可讀的顯示,許多系統使用帶有插入連字符的十六進制文本的規范格式,例如:


123e4567-e89b-12d3-a456-426655440000

這有長度16*2 + 4 = 36。您可以選擇省略為您提供的連字符:


fmt.Printf("%x\n", uuid)

fmt.Println(hex.EncodeToString(uuid))


// Output: 32 chars

123e4567e89b12d3a456426655440000

123e4567e89b12d3a456426655440000

您可以選擇使用 base32 編碼(它使用 1 個符號對 5 位進行編碼,而十六進制編碼使用 1 個符號對 4 位進行編碼):


fmt.Println(base32.StdEncoding.EncodeToString(uuid))


// Output: 26 chars

CI7EKZ7ITMJNHJCWIJTFKRAAAA======

傳輸時修剪尾隨=符號,因此始終為 26 個字符。請注意,您必須"======"在使用base32.StdEncoding.DecodeString().


如果這對您來說仍然太長,您可以使用 base64 編碼(用 1 個符號編碼 6 位):


fmt.Println(base64.RawURLEncoding.EncodeToString(uuid))


// Output: 22 chars

Ej5FZ-ibEtOkVkJmVUQAAA

請注意,這base64.RawURLEncoding會生成一個 base64 字符串(沒有填充),它可以安全地包含在 URL 中,因為符號表中的 2 個額外字符(超出[0-9a-zA-Z])是-和_,它們都可以安全地包含在 URL 中。


不幸的是,base64 字符串可能包含 2 個額外的字符[0-9a-zA-Z]。所以請繼續閱讀。


解釋,轉義字符串

如果你對這兩個額外的字符不熟悉,你可以選擇將你的 base64 字符串轉換成一個解釋的、轉義的字符串,類似于 Go 中的解釋字符串文字。例如,如果您想在解釋的字符串文字中插入反斜杠,則必須將其加倍,因為反斜杠是表示序列的特殊字符,例如:


fmt.Println("One backspace: \\") // Output: "One backspace: \"

我們可能會選擇做類似的事情。我們必須指定一個特殊字符:be it 9。


推理: base64.RawURLEncoding使用 charset: A..Za..z0..9-_,因此9用字母數字字符表示最高代碼(十進制 61 = 111101b)。請參閱下面的優勢。

因此,只要 base64 字符串包含 a9,請將其替換為99. 并且每當 base64 字符串包含額外字符時,請使用序列而不是它們:


9  =>  99

-  =>  90

_  =>  91

這是一個簡單的替換表,可以通過以下值捕獲strings.Replacer:


var escaper = strings.NewReplacer("9", "99", "-", "90", "_", "91")

并使用它:


fmt.Println(escaper.Replace(base64.RawURLEncoding.EncodeToString(uuid)))


// Output:

Ej5FZ90ibEtOkVkJmVUQAAA

這會稍微增加長度,因為有時會使用 2 個字符的序列而不是 1 個字符,但好處是只[0-9a-zA-Z]使用字符,如您所愿。平均長度將少于 1 個附加字符:23字符。公平貿易。


邏輯:為簡單起見,我們假設所有可能的 uuid 具有相同的概率(uuid 不是完全隨機的,所以情況并非如此,但我們將其放在一邊,因為這只是一個估計)。最后一個 base64 符號永遠不會是可替換的字符(這就是為什么我們選擇特殊字符9而不是 like A),21 個字符可能會變成可替換的序列。一個被替換的機會:3 / 64 = 0.047,所以平均而言這意味著 21*3/64 = 0.98 個序列將 1 個字符轉換為 2 個字符序列,因此這等于額外字符的數量。


要解碼,請使用以下捕獲的逆解碼表strings.Replacer:


var unescaper = strings.NewReplacer("99", "9", "90", "-", "91", "_")

解碼轉義的 base64 字符串的示例代碼:


fmt.Println("Verify decoding:")

s := escaper.Replace(base64.RawURLEncoding.EncodeToString(uuid))

dec, err := base64.RawURLEncoding.DecodeString(unescaper.Replace(s))

fmt.Printf("%x, %v\n", dec, err)

輸出:


123e4567e89b12d3a456426655440000, <nil>

嘗試Go Playground上的所有示例。


查看完整回答
反對 回復 2022-01-17
?
函數式編程

TA貢獻1807條經驗 獲得超9個贊

正如這里所建議的那樣,如果您只想將一個相當隨機的字符串用作 slug,最好不要打擾 UUID。


您可以簡單地使用 go 的本機 math/rand 庫來制作所需長度的隨機字符串:


import (

"math/rand"

"encoding/hex"

)



b := make([]byte, 4) //equals 8 characters

rand.Read(b) 

s := hex.EncodeToString(b)


查看完整回答
反對 回復 2022-01-17
?
元芳怎么了

TA貢獻1798條經驗 獲得超7個贊

另一種選擇是math/big。雖然base64有 22 個字符的恒定輸出,math/big但可以減少到 2 個字符,具體取決于輸入:


package main


import (

   "encoding/base64"

   "fmt"

   "math/big"

)


type uuid [16]byte


func (id uuid) encode() string {

   return new(big.Int).SetBytes(id[:]).Text(62)

}


func main() {

   var id uuid

   for n := len(id); n > 0; n-- {

      id[n - 1] = 0xFF

      s := base64.RawURLEncoding.EncodeToString(id[:])

      t := id.encode()

      fmt.Printf("%v %v\n", s, t)

   }

}

結果:


AAAAAAAAAAAAAAAAAAAA_w 47

AAAAAAAAAAAAAAAAAAD__w h31

AAAAAAAAAAAAAAAAAP___w 18owf

AAAAAAAAAAAAAAAA_____w 4GFfc3

AAAAAAAAAAAAAAD______w jmaiJOv

AAAAAAAAAAAAAP_______w 1hVwxnaA7

AAAAAAAAAAAA_________w 5k1wlNFHb1

AAAAAAAAAAD__________w lYGhA16ahyf

AAAAAAAAAP___________w 1sKyAAIxssts3

AAAAAAAA_____________w 62IeP5BU9vzBSv

AAAAAAD______________w oXcFcXavRgn2p67

AAAAAP_______________w 1F2si9ujpxVB7VDj1

AAAA_________________w 6Rs8OXba9u5PiJYiAf

AAD__________________w skIcqom5Vag3PnOYJI3

AP___________________w 1SZwviYzes2mjOamuMJWv

_____________________w 7N42dgm5tFLK9N8MT7fHC7

https://golang.org/pkg/math/big


查看完整回答
反對 回復 2022-01-17
  • 3 回答
  • 0 關注
  • 991 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號