Golang中如何将Uint64转换为切片[]Uint8

Golang中如何将Uint64转换为切片[]Uint8 我正在使用 satori/uuid 包来获取 UUID 值 但在我这种情况下,获取新 UUID 后需要将其转换为简单的整数类型 我找到了一些解决方案,但不明白在处理完整数值后如何将其重新转换为 UUID 格式 如何高效简单地实现这一点? 谢谢!

例如 https://play.golang.org/p/A139r2NvfN7

newValue, _ := uuid.NewV4()
log.Println(newValue)
log.Printf("%T", newValue)
        
//convert to slice []uint8
b, _ := newValue.MarshalBinary()
log.Printf("%T, %v", b, b)

//convert to uint64
data := binary.BigEndian.Uint64(b)
log.Printf("%T, %v", data, data)

结果:

ee397b32-8ea1-46fd-99dc-a3c0c1267b87
uuid.UUID
[]uint8, [238 57 123 50 142 161 70 253 153 220 163 192 193 38 123 135]
uint64, 17165886911770871549

但是如何将 uint64 -> []uint8 -> uuid 转换? 最佳方案是在 uuid -> int 和 int -> uuid 之间转换 不使用 uint 格式 - 但我不明白如何实现 使用 runes 还是其他方法? 谢谢!


更多关于Golang中如何将Uint64转换为切片[]Uint8的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

NobbZ:

通常应避免在JSON中使用数字(特别是在需要精确值的情况下),因为JSON不区分浮点数和整数,它只认识"数字"类型。如果给定的整数字面量无法在读取器的整数类型中表示,则允许读取器将其静默强制转换为浮点数。理论上,读取器甚至不需要尝试将其转换为整型,它从一开始就可以将1读取为1.0。

谢谢! 是的,我了解UUID的String()方法

更多关于Golang中如何将Uint64转换为切片[]Uint8的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


func main() {
    fmt.Println("hello world")
}

你好 - 感谢描述

当我创建每个对象时(小型生成器 - 但可能是数千个对象(并且需要并发工作)) 我需要为每个对象提供唯一的ID 然后我想将新对象转换为json格式(使用需要ID int的google/jsonapi包) 以便通过http发送到下一步 我认为使用uuid是最独特的解决方案 可能我错了 也许我可以使用反射或其他方法 通过循环从uuid.String()转换字符到int … 我想

无法直接将 UUID 转换为简单的整数类型。UUID 是 128 位的,而 Go 中最大的整数类型只有 64 位。这意味着要将 UUID 存储为整数,您需要两个整数值。

您也不能将 uint64 转换为 UUID,因为 UUID 是 128 位的,需要两个 uint64 才能正确表示它。所以如果从 uint64 转换为 UUID,意味着您大大降低了 ID 的唯一性,因为只设置了 128 位中的 64 位。

为什么需要将其转换为简单的整数类型?您打算将这些数据用于什么目的?

至少给您一个代码片段,以下是我将 uint64 转换为 []byte 的方法:

我应该补充一点,还有 math/big 包,它包含 big.Int 类型。您可以使用它来表示大于 64 位的整数,尽管我不认为这是一个简单的整数。

@YongGopher 如果你想要一个能容纳在64位整数内的唯一标识符,就不能使用UUID。问题在于UUID的尺寸太大,无论进行何种处理都无法放入整数中。这就像试图将两升水装入一升容量的瓶子,物理上是不可能的。

如果你需要唯一ID,可以尝试生成随机的uint64数值并使用它们。这样最多能提供18,446,744,073,709,551,615个唯一值。而128位随机值拥有约340,282,366,920,938,463,463,374,607,431,768,211,455个可能值。发生冲突的概率会显著降低。

另一个需要考虑的因素是你使用的JSON系统是否支持64位数值。例如JavaScript的整数精度只能达到53位。因此需要注意对接的语言是否支持你所需的大整数。

如果要在JSON中包含UUID,最安全的方式是直接使用其字符串表示形式。

您使用的UUID包正确实现了Stringer接口,因此可以轻松地将其放入JSON中:

func (u UUID) String() string {
	buf := make([]byte, 36)

	hex.Encode(buf[0:8], u[0:4])
	buf[8] = '-'
	hex.Encode(buf[9:13], u[4:6])
	buf[13] = '-'
	hex.Encode(buf[14:18], u[6:8])
	buf[18] = '-'
	hex.Encode(buf[19:23], u[8:10])
	buf[23] = '-'
	hex.Encode(buf[24:], u[10:])

	return string(buf)
}

一般来说,您应该避免在JSON中使用数字(至少在需要精确值的情况下),因为JSON不区分浮点数和整数,它只知道"数字"。如果给定的整数字面量无法在读取器的整数类型中表示,允许读取器静默强制转换为浮点数。理论上,读取器甚至不需要尝试将其放入int类型中。它被允许从一开始就将1读取为1.0

在Golang中,将uint64转换回UUID格式需要理解UUID的结构。UUID是128位值,而uint64只有64位,所以直接转换会丢失数据。以下是完整的转换方案:

package main

import (
	"encoding/binary"
	"fmt"
	"log"

	"github.com/satori/go.uuid"
)

func main() {
	// 原始UUID
	originalUUID, _ := uuid.NewV4()
	log.Printf("原始UUID: %s", originalUUID)
	
	// UUID -> []byte
	uuidBytes, _ := originalUUID.MarshalBinary()
	log.Printf("UUID字节切片: %v", uuidBytes)
	
	// 从字节切片提取uint64(取前8字节)
	uuidToUint64 := binary.BigEndian.Uint64(uuidBytes[:8])
	log.Printf("转换后的uint64: %d", uuidToUint64)
	
	// uint64 -> UUID 转换
	reconstructedUUID := uint64ToUUID(uuidToUint64)
	log.Printf("重建的UUID: %s", reconstructedUUID)
}

func uint64ToUUID(value uint64) uuid.UUID {
	// 创建16字节的切片来存储UUID
	uuidBytes := make([]byte, 16)
	
	// 将uint64写入前8字节
	binary.BigEndian.PutUint64(uuidBytes[:8], value)
	
	// 后8字节可以填充默认值或随机值
	// 这里简单填充零值
	for i := 8; i < 16; i++ {
		uuidBytes[i] = 0
	}
	
	return uuid.UUID(uuidBytes)
}

如果你需要保留完整的128位UUID信息,应该使用两个uint64:

func uuidToUint64s(u uuid.UUID) (uint64, uint64) {
	bytes, _ := u.MarshalBinary()
	return binary.BigEndian.Uint64(bytes[:8]), binary.BigEndian.Uint64(bytes[8:])
}

func uint64sToUUID(high, low uint64) uuid.UUID {
	uuidBytes := make([]byte, 16)
	binary.BigEndian.PutUint64(uuidBytes[:8], high)
	binary.BigEndian.PutUint64(uuidBytes[8:], low)
	return uuid.UUID(uuidBytes)
}

// 使用示例:
func main() {
	originalUUID, _ := uuid.NewV4()
	fmt.Printf("原始UUID: %s\n", originalUUID)
	
	// 转换为两个uint64
	high, low := uuidToUint64s(originalUUID)
	fmt.Printf("高位uint64: %d, 低位uint64: %d\n", high, low)
	
	// 转换回UUID
	reconstructed := uint64sToUUID(high, low)
	fmt.Printf("重建的UUID: %s\n", reconstructed)
}

如果你只需要简单的整数表示而不关心UUID格式的完整性,可以直接使用第一个方法。但要注意这会丢失UUID的后64位信息。

回到顶部