整数溢出-golang

整数溢出-golang,go,Go,我遇到一些整数溢出错误。 我使用golang和go micro作为微服务框架构建了一个微服务应用程序。 我使用NAT作为消息代理 我的微服务有效载荷的格式为 map[string]interface{} 当我发布包含uint64的有效负载时,会出现问题,例如 var id uint64 = 512281913614499841 message := map[string]inteface{} message["id"] = id 这是由cockroachdb生成的唯一ID,当订阅者

我遇到一些整数溢出错误。 我使用golang和go micro作为微服务框架构建了一个微服务应用程序。 我使用NAT作为消息代理

我的微服务有效载荷的格式为

 map[string]interface{}
当我发布包含uint64的有效负载时,会出现问题,例如

 var id uint64 = 512281913614499841

 message := map[string]inteface{}
 message["id"] = id
这是由cockroachdb生成的唯一ID,当订阅者以字节形式接收此消息并将其解组到uint64时,我意识到发生了溢出,值变为

512281913614499840 //this should be 512281913614499841
请注意末尾的0而不是1

我已经创建了两个函数overFlowError和noOverflow-见下文

函数OverflowerError模拟导致溢出的代码

noOverflow打印正确的结果,因为我在这个格式map[string][struct]中使用有效负载,而不是map[string]接口

type UserType struct {
    Email string `json:"email"`
    ID    int64  `json:"id"`
}
func overFlowError() {

        var id int64 = 512281913614499841

        user := UserType{
            Email: "example",
            ID:    id,
        }

        message := map[string]interface{}{
            "data": user,
        }

        //mashal to byte to simulate service payload
        servicePayload, err := json.Marshal(message)

        if err != nil {
            log.Println(err)
        }

        var receivedMessage map[string]interface{}

        json.Unmarshal(servicePayload, &receivedMessage)

        var myUser UserType

        mapstructure.Decode(receivedMessage["data"], &myUser)

        log.Println("---receivedMessage:", myUser.ID) //prints 512281913614499840 - incorrect
    }
无溢流

type UserType struct {
    Email string `json:"email"`
    ID    int64  `json:"id"`
}
func noOverflow() {

        var id int64 = 512281913614499841

        message := map[string]UserType{}

        message["data"] = UserType{
            Email: "example",
            ID:    id,
        }

        byteMessage, err := json.Marshal(message)

        if err != nil {
            log.Println(err)
        }

        var msgMap map[string]UserType

        json.Unmarshal(byteMessage, &msgMap)

        log.Println("---myUser:", msgMap["data"].ID) // prints 512281913614499841 - correct
    }
为了避免大量的代码重写,我留下了第一个选项,我在OverflowerError函数中模拟了这个选项,并在上面进行了解释


这个问题有解决办法吗?

这不是整数溢出。实际上,问题是JSON数字往往表示为浮点,而float32的位太少,无法容纳正确的值。即使是Go默认使用的float64也不太合适

查看所有答案,不仅仅是被接受的答案,还有。或者,查看旧问题及其公认的答案

根据需要哪种互操作性,您可以继续将它们解码为数字,但可以使用更复杂的解码器和/或自定义解组器,也可以将其作为字符串用JSON编码。在实践中,当使用JSON跨GO+Python + Type Script +各种C++库时,WE1求助于字符串编码。最终我们发现这要可靠得多。我们不必对32位整数这样做,只需对64位整数这样做

要使用非默认解码器,请特别参见及其选项


1We这里不是royal we,而是$job,在这里,除了TypeScript之外,我已经接触了所有这些内容。

您可以将回购协议中的代码添加到这个问题中吗?这是因为id的值超出了float64的精度范围。您可以将其封送为字符串并在接收时对其进行解析,也可以使用json.Decoder和json.Decoder.UseNumber,而不是json.Unmarshal,然后解析数字。感谢leaf,我之前尝试了第一种解决方案,但它不是最好的解决方案,因为字符串不是预期的类型。我正在寻找一个更自然、更优雅的解决方案。对于第二种解决方案,我正在考虑这样的结构中的uint64字段如何工作:键入User struct{ID uint64},因为在反序列化时这也会溢出。我来看看json.decoderpackage@ykel您从ID字段中查看哪些数值属性,以便不希望它成为字符串?你是加、减、除还是乘?@zerkms,如果没有其他更好的方法,我将使用leaf的第一个解决方案。