将Go中的UUID输出为短字符串 [英] Output UUID in Go as a short string

查看:992
本文介绍了将Go中的UUID输出为短字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



I.e。利用更大范围的字符,例如 [A-Za-z0-9] 输出较短的字符串。


$ b $我知道我们可以使用base64对字节进行编码,如下所示,但是我创建了一个字符串,看起来像一个word,即没有 + /

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


解决方案

A 普遍唯一标识符(UUID)是一个128位值,为16字节。对于可读显示,许多系统使用带有插入连字符字符的十六进制文本的规范格式,例如:

  123e4567-e89b -12d3-a456-426655440000 

这个长度 16 * 2 + 4 = 36 。您可以选择省略提供给您的连字号:

  fmt.Printf(%x\\\
,uuid)
fmt.Println(hex.EncodeToString(uuid))

//输出:32个字符
123e4567e89b12d3a456426655440000
123e4567e89b12d3a456426655440000
/ pre>

您可以选择使用base32编码(其编码5位与1个符号,而对于使用1个符号编码4位的十六进制编码):

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

//输出:26个字符
CI7EKZ7ITMJNHJCWIJTFKRAAAA ======

修剪尾随的 = 发送时的符号,所以这个永远是26个字符。请注意,您必须在使用 base32.StdEncoding.DecodeString()====== $ c>。

如果这对你来说还是太长,可以使用base64编码(编码6位1个符号):

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

//输出:22个字符
Ej5FZ-注意, base64.RawURLEncoding 生成一个base64字符串(无填充)对于URL包含是安全的,因为符号表中的2个额外的字符(超出 [0-9a-zA-Z] )是 - _ ,两者都可以安全地包含在URL中。



不幸的是,base64字符串可能包含超出 [0-9a-zA-Z] 的2个额外的字符。所以请继续阅读。



解释后的转义字符串



如果您与这两个额外的字符不同,选择将base64字符串转换为与Go中解释的字符串文字相似的解释的转义字符串。例如,如果要在解释的字符串文字中插入反斜杠,则必须加倍,因为反斜杠是指示序列的特殊字符,例如:

  fmt.Println(One backspace:\\)//输出:一个退格:\

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



推理: strong> base64.RawURLEncoding 使用字符集: A..Za..z0..9 -_ ,所以 9 代表具有字母数字字符的最高代码(61位十进制= 111101b)。请看下面的优点。

所以每当base64字符串包含一个 9 ,将其替换为 99 。每当base64字符串包含额外的字符时,请使用序列,而不是它们:

  9 = > 99 
- => 90
_ => 91

这是一个简单的替换表,可以通过值 strings.Replacer

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

并使用它:

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

//输出:
Ej5FZ90ibEtOkVkJmVUQAAA
/ pre>

这将稍微增加长度,因为有时会使用2个字符的序列而不是1个字符,但是增益将只有 [0-9a-zA-Z] 将根据需要使用字符。平均长度将少于1个额外的字符: 23 chars。



逻辑:为了简单起见,我们假设所有可能的uuids具有相等的概率(uuid是不是完全随机的,所以情况并非如此,但让我们把它放在一边,因为这只是一个估计)。最后的base64符号永远不会是可替换的字符(这就是为什么我们选择特殊字符为 9 而不是像 A ),21个字符可能会变成可更换的顺序。一个可替换的机会:3/64 = 0.047,所以平均而言这意味着21 * 3/64 = 0.98将1个字符变成2个字符序列的序列,所以这等于多余的字符数。 sup>



要解码,请使用以下 strings.Replacer捕获的逆解码表。

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

解码转义的base64字符串的示例代码:


$ b $
s:= escaper.Replace(base64.RawURLEncoding.EncodeToString(uuid))
dec,err: = base64.RawURLEncoding.DecodeString(unescaper.Replace(s))
fmt.Printf(%x,%v\\\
,dec,err)
pre>

输出:

  123e4567e89b12d3a456426655440000,< nil& 

尝试所有示例在 Go Playground


Is there a built in way, or reasonably standard package that allows you to convert a standard UUID into a short string that would enable shorter URL's?

I.e. taking advantage of using a larger range of characters such as [A-Za-z0-9] to output a shorter string.

I know we can use base64 to encode the bytes, as follows, but I'm after something that creates a string that looks like a "word", i.e. no + and /:

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

解决方案

A universally unique identifier (UUID) is a 128-bit value, which is 16 bytes. For human-readable display, many systems use a canonical format using hexadecimal text with inserted hyphen characters, for example:

123e4567-e89b-12d3-a456-426655440000

This has length 16*2 + 4 = 36. You may choose to omit the hypens which gives you:

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

// Output: 32 chars
123e4567e89b12d3a456426655440000
123e4567e89b12d3a456426655440000

You may choose to use base32 encoding (which encodes 5 bits with 1 symbol in contrast to hex encoding which encodes 4 bits with 1 symbol):

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

// Output: 26 chars
CI7EKZ7ITMJNHJCWIJTFKRAAAA======

Trim the trailing = signs when transmitting, so this will always be 26 chars. Note that you have to append "======" prior to decode the string using base32.StdEncoding.DecodeString().

If this is still too long for you, you may use base64 encoding (which encodes 6 bits with 1 symbol):

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

// Output: 22 chars
Ej5FZ-ibEtOkVkJmVUQAAA

Note that base64.RawURLEncoding produces a base64 string (without padding) which is safe for URL inclusion, because the 2 extra chars in the symbol table (beyond [0-9a-zA-Z]) are - and _, both which are safe to be included in URLs.

Unfortunately for you, the base64 string may contain 2 extra chars beyond [0-9a-zA-Z]. So read on.

Interpreted, escaped string

If you are alien to these 2 extra characters, you may choose to turn your base64 string into an interpreted, escaped string similar to the interpreted string literals in Go. For example if you want to insert a backslash in an interpreted string literal, you have to double it because backslash is a special character indicating a sequence, e.g.:

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

We may choose to do something similar to this. We have to designate a special character: be it 9.

Reasoning: base64.RawURLEncoding uses the charset: A..Za..z0..9-_, so 9 represents the highest code with alphanumeric character (61 decimal = 111101b). See advantage below.
So whenever the base64 string contains a 9, replace it with 99. And whenever the base64 string contains the extra characters, use a sequence instead of them:

9  =>  99
-  =>  90
_  =>  91

This is a simple replacement table which can be captured by a value of strings.Replacer:

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

And using it:

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

// Output:
Ej5FZ90ibEtOkVkJmVUQAAA

This will slightly increase the length as sometimes a sequence of 2 chars will be used instead of 1 char, but the gain will be that only [0-9a-zA-Z] chars will be used, as you wanted. The average length will be less than 1 additional character: 23 chars. Fair trade.

Logic: For simplicity let's assume all possible uuids have equal probability (uuid is not completely random, so this is not the case, but let's set this aside as this is just an estimation). Last base64 symbol will never be a replaceable char (that's why we chose the special char to be 9 instead of like A), 21 chars may turn into a replaceable sequence. The chance for one being replaceable: 3 / 64 = 0.047, so on average this means 21*3/64 = 0.98 sequences which turn 1 char into a 2-char sequence, so this is equal to the number of extra characters.

To decode, use an inverse decoding table captured by the following strings.Replacer:

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

Example code to decode an escaped base64 string:

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)

Output:

123e4567e89b12d3a456426655440000, <nil>

Try all the examples on the Go Playground.

这篇关于将Go中的UUID输出为短字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆