Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 以短字符串形式输出Go中的UUID_String_Go_Encoding_Uuid - Fatal编程技术网

String 以短字符串形式输出Go中的UUID

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字节。对于人类可读的显示,许多系统使用标准格式,使用带有插入连字符的十六进

是否有一个内置的或合理的标准包,允许您将标准UUID转换为一个短字符串,以支持更短的URL

即,利用更大范围的字符(如
[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)
   }
}