gpt4 book ai didi

string - 在 Go 中将 UUID 输出为短字符串

转载 作者:IT王子 更新时间:2023-10-29 01:15:43 42 4
gpt4 key购买 nike

是否有内置方式或合理的标准包允许您将标准 UUID 转换为短字符串以启用更短的 URL?

即利用使用更大范围的字符(例如 [A-Za-z0-9])来输出更短的字符串。

我知道我们可以使用 base64 来对字节进行编码,如下所示,但是我想要创建一个看起来像“单词”的字符串,即没有 +/:

id = base64.StdEncoding.EncodeToString(myUuid.Bytes())

最佳答案

一个universally unique identifier (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 字符串可能包含 [0-9a-zA-Z] 之外的 2 个额外字符。请继续阅读。

解释、转义字符串

如果您不熟悉这 2 个额外的字符,您可以选择将您的 base64 字符串转换为类似于 Go 中的解释字符串文字的解释、转义字符串。例如,如果要在解释的字符串文字中插入反斜杠,则必须将其加倍,因为反斜杠是表示序列的特殊字符,例如:

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

我们可能会选择做类似的事情。我们必须指定一个特殊字符:9

推理 base64.RawURLEncoding 使用字符集:A..Za..z0..9-_,所以9 代表带有字母数字字符的最高代码(61 十进制 = 111101b)。请参阅下面的优势。
因此,只要 base64 字符串包含 9,就将其替换为 99。每当 base64 字符串包含额外字符时,使用 sequence 代替它们:

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 而不是像 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 上的所有示例。

关于string - 在 Go 中将 UUID 输出为短字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37934162/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com