是否有内置方式或合理的标准软件包,可让您将标准UUID转换为短字符串,从而启用较短的URL?
即利用了较大范围的字符,例如[A-Za-z0-9]输出较短的字符串。
[A-Za-z0-9]
我知道我们可以使用base64对字节进行编码,如下所示,但是我正在创建一个看起来像“单词”的字符串,即no +和/:
+
/
id = base64.StdEncoding.EncodeToString(myUuid.Bytes())
甲通用唯一标识符(UUID)是一个128位的值,它是16个字节。对于人类可读的显示,许多系统使用规范格式,该规范格式使用带有插入的连字符的十六进制文本,例如:
123e4567-e89b-12d3-a456-426655440000
这有长度16*2 + 4 = 36。您可以选择省略为您提供的连字符:
16*2 + 4 = 36
fmt.Printf("%x\n", uuid) fmt.Println(hex.EncodeToString(uuid)) // Output: 32 chars 123e4567e89b12d3a456426655440000 123e4567e89b12d3a456426655440000
您可以选择使用base32编码(与使用1个符号编码4位的十六进制编码相反):
fmt.Println(base32.StdEncoding.EncodeToString(uuid)) // Output: 26 chars CI7EKZ7ITMJNHJCWIJTFKRAAAA======
=传输时修剪尾随标志,因此始终为26个字符。请注意,您必须先附加,"======"然后才能使用解码字符串base32.StdEncoding.DecodeString()。
=
"======"
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.RawURLEncoding
[0-9a-zA-Z]
-
_
对于您来说很不幸,base64字符串除之外可能还包含2个额外的字符[0-9a-zA-Z]。继续阅读。
如果您对这两个额外的字符不熟悉,则可以选择将base64字符串转换为类似于Go中的解释后字符串文字的 解释后转义字符串 。例如,如果要在解释的字符串文字中插入反斜杠,则必须将其加倍,因为反斜杠是表示序列的特殊字符,例如:
fmt.Println("One backspace: \\") // Output: "One backspace: \"
我们可以选择做类似的事情。我们必须指定一个特殊字符:顺其自然9。
9
推理: base64.RawURLEncoding使用字符集:A..Za..z0..9-_,因此9代表带有字母数字字符的最高代码(61个十进制= 111101b)。请参见下面的优势。 因此,只要base64字符串包含a9,就将其替换为99。每当base64字符串包含多余的字符时,请使用 序列 代替它们:
A..Za..z0..9-_
99
9 => 99 - => 90 _ => 91
这是一个简单的替换表,可以通过以下值捕获strings.Replacer:
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字符。 公平交易。
23
逻辑: 为简单起见,我们假设所有可能的uuid都具有相同的概率(uuid并非完全随机,因此不是这种情况,但我们将其放在一边,因为这只是一种估计)。最后一个base64符号将永远不会是可替换字符(这就是为什么我们选择特殊字符9代替like的原因A),21个字符可能会变成可替换序列。一个可替换的机会:3/64 = 0.047,因此平均而言,这意味着21 * 3/64 = 0.98个序列,这些序列将1个字符转换为2个字符,因此,这等于附加字符的数量。
A
要进行解码,请使用以下捕获的逆解码表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上尝试所有示例。