【问题标题】:Go convert to float from string which represent binary从代表二进制的字符串转换为浮点数
【发布时间】:2021-10-12 22:40:26
【问题描述】:

转到 gRPC 元数据,获取并转换值。

在我的日志中,我看到元数据正在被翻译成另一种类型(我认为是字节数组)

"latitude-bin":"\ufffd\u0019\u0014\ufffd\ufffdϑL","longitude-bin":"@Z\ufffd\ufffd\ufffd\u000e\ufffdD"

如果我没记错的话,这两个值都应该是 Double。 我想在 Golang 中将这些值转换为 Double 或 float64,但我对我的方法有点不确定,因为我不知道 latitude-bin 或 longitude-bin 的类型,我也不知道重现这些值(从我的客户的日志中获取)

这是我的方法

// GetLangitute get latitude from metadata `latitude-bin` and return nil when fails
func GetLangitute(ctx context.Context) *float64 {
    metadataList := getMetaDataListByKey(ctx, latitudeBin)
    if metadataList != nil {
        s := metadataList[metadataIndex]
        b := []byte(s)
        // TODO: 
        // I'm still a bit unsure about this approach
        data := math.Float64frombits(binary.BigEndian.Uint64(b))
        return &data
    }

    return nil
}

func getMetaDataListByKey(ctx context.Context, key string) []string {
    md, ok := metadata.FromIncomingContext(ctx)
    if !ok {
        return nil
    }

    metadataList := md.Get(key)
    if isEmpty(metadataList) {
        return nil
    }

    return metadataList
}

func isEmpty(metadataList []string) bool {
    return len(metadataList) == 0
}

我尝试使用单元测试进行测试并且看起来不错,但我仍然不确定预期的结果,因为我无法重现它,这是我的单元测试

f := math.Float64frombits(uint64(6662343813755067509))
// ...
name: "Given key exist in metadata",
            args: args{
                ctx: metadata.NewIncomingContext(
                    context.Background(),
                    metadata.Pairs("latitude-bin", `\ufffd\u0019\u0014\ufffd\ufffdϑL`),
                ),
            },
            want: &f,
// ...
t.Run(tt.name, func(t *testing.T) {
    got := GetLangitute(tt.args.ctx)
    if tt.want != nil {
        if *got != *tt.want {
            t.Errorf("GetLangitute() = %v, want %v", got, tt.want)
        }
    } else {
        assert.Nil(t, got)
    }
})

【问题讨论】:

    标签: arrays go binary byte grpc


    【解决方案1】:

    不幸的是,您的输入 JSON 似乎已经“搞砸”了。 JSON 中的纬度和经度值是 8 字节值,但它们不代表原始值。原始值丢失。

    Go 将字符串存储为 UTF-8 编码的字节序列。在将其他类型转换为字符串(例如int)时,遇到无效值时,转换将导致Unicode替换字符0xFFFD。

    您的输入包含多个这些符文:\ufffd。这意味着生成输入 JSON 的编码算法有问题并导致信息丢失。您不太可能重现原始的纬度和经度值。

    您必须修复源代码的编码部分。

    注意:如果您的输入有效/正确,您可以像这样简单地将 string 值转换为 []byte:

    b := []byte(s)
    

    无论s 是否包含有效的UTF-8 序列,上述转换都会产生s 的字节。

    【讨论】:

    • 你说得对,好像有东西截取了值。我与 FE 团队交谈,他们向我们发送了这样的值 41cdcd6500000000 他们告诉我们如何使用 Kotlin 生成这些值,我注意到这些值与服务器日志相比有所不同
    • 这里是如何从客户端(Kotlin)pl.kotl.in/kte_JvwIA生成值
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2011-05-18
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多