String 以短字符串形式输出Go中的UUID
是否有一个内置的或合理的标准包,允许您将标准UUID转换为一个短字符串,以支持更短的URL 即,利用更大范围的字符(如String 以短字符串形式输出Go中的UUID,string,go,encoding,uuid,String,Go,Encoding,Uuid,是否有一个内置的或合理的标准包,允许您将标准UUID转换为一个短字符串,以支持更短的URL 即,利用更大范围的字符(如[a-Za-z0-9])输出更短的字符串 我知道我们可以使用base64对字节进行编码,如下所示,但我想要创建一个看起来像“单词”的字符串,即no+和//code>: id = base64.StdEncoding.EncodeToString(myUuid.Bytes()) A是一个128位的值,即16字节。对于人类可读的显示,许多系统使用标准格式,使用带有插入连字符的十六进
[a-Za-z0-9]
)输出更短的字符串
我知道我们可以使用base64对字节进行编码,如下所示,但我想要创建一个看起来像“单词”的字符串,即no+
和//code>:
id = base64.StdEncoding.EncodeToString(myUuid.Bytes())
A是一个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位):
传输时修剪尾随的=
符号,因此始终为26个字符。请注意,在使用base32.StdEncoding.DecodeString()
解码字符串之前,必须先附加“===”
如果这对您来说仍然太长,您可以使用base64编码(用1个符号编码6位):
请注意,base64.RawURLEncoding
生成一个base64字符串(无填充),该字符串对于URL包含是安全的,因为符号表中的两个额外字符(超出[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字符串包含额外字符时,请使用一个序列而不是它们:
9 => 99
- => 90
_ => 91
这是一个简单的替换表,其值为:
使用它:
fmt.Println(escaper.Replace(base64.RawURLEncoding.EncodeToString(uuid)))
// Output:
Ej5FZ90ibEtOkVkJmVUQAAA
这将略微增加长度,因为有时会使用2个字符的序列而不是1个字符,但好处是,根据您的需要,只使用[0-9a-zA-Z]
字符。平均长度将小于1个附加字符:23
chars。公平贸易
逻辑:为了简单起见,让我们假设所有可能的uuid都具有相同的概率(uuid不是完全随机的,所以情况并非如此,但我们将其放在一边,因为这只是一个估计)。最后一个base64符号永远不会是可替换字符(这就是为什么我们选择特殊字符为9
而不是像a
),21个字符可能会变成可替换序列。一个字符被替换的可能性:3/64=0.047,因此平均来说,这意味着21*3/64=0.98个序列将1个字符转换为2个字符的序列,因此这等于额外字符的数量
要解码,请使用以下字符串捕获的反向解码表。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>
123e4567e89b12d3a456426655440000,
按照建议,尝试.p>上的所有示例,如果您只想使用一个相当随机的字符串作为slug,最好不要使用UUID
您只需使用go的本机math/rand库即可生成所需长度的随机字符串:
import (
"math/rand"
"encoding/hex"
)
b := make([]byte, 4) //equals 8 characters
rand.Read(b)
s := hex.EncodeToString(b)
另一个选项是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)
}
}
结果:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa d__wH31
aaaaaaaaaaaaaaaaaapauuuuuuuuuuuw18owf
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaa d_____;u__;w jmaiJOv
aaaaaaaaaaaaaaa P________w1hvwxnaa7
AAAAAAAAAAAA uuuuuuuuuuuuuuuuuw 5k1wlNFHb1
aaaaaaaaaaa d________;w lYGhA16ahyf
aaaaaaaaaaaaa P__________;w 1sKyAAIxssts3
AAAAAAAA uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
AAAAA D_u______________________
AAAA P_uuuuuuuuuuuuuuuuuuuuuuw1f2si9ujpxvb7vdj1
AAAA uuuuuuuuuuuuuuuuuuuuuuuuuuuuw6rs8oxba9u5pijyiaf
AADÈuÈuÈuÈuÈuÈuÈuÈuÈuÈw skicqoom5vag3pnoyji3
AP-1SZWVIYZES2MJOAMJWV
_____________________w 7N42dgm5tFLK9N8MT7fHC7
如果您想避免使用非字母字符,可以选择base32?你只能对128位的信息进行如此小的编码。找到了这个包:使用和禁用填充。我以前用过这个包:太漂亮了。我不知道base64.RawURLEncoding
,最后一行替换破折号和下划线的代码对某些人来说肯定有用。谢谢你的详细回答。谢谢分享,这可能对一些人有用。然而,这个问题是专门针对呈现UUID提出的。这是一个多么好的建议。谢谢分享!
123e4567e89b12d3a456426655440000, <nil>
import (
"math/rand"
"encoding/hex"
)
b := make([]byte, 4) //equals 8 characters
rand.Read(b)
s := hex.EncodeToString(b)
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)
}
}