如何将未知大小的字节切片转换为字节数组?

我需要解组一些数据,在一种情况下,编组的数据表示一个以字节数组为键的映射。


切片不允许作为映射键,但数组可以。但这里的问题是,据我所知,无法创建具有非常量大小的数组。


例子:


package main


import (

    "fmt"

    "reflect"

)


func getHashable(value interface{}) interface{} {

    rfl := reflect.ValueOf(value)

    if rfl.Kind() == reflect.Slice && rfl.Type().Elem().Kind() == reflect.Uint8 {

        slice, ok := value.([]uint8)

        if !ok {

            panic(fmt.Errorf("Could not coerce to []uint8"))

        }

        var arr [len(slice)]uint8 // This fails

        copy(arr, slice)

        value = arr

    }

    return value

}


func unmarshalMap(serialized []byte) map[interface{}]interface{} {

    result := make(map[interface{}]interface{})

    for len(serialized) > 0 {

        var value interface{}

        key, bytesConsumed := deserializeValue(serialized)

        serialized = serialized[bytesConsumed:]

        value, bytesConsumed = deserializeValue(serialized)

        serialized = serialized[bytesConsumed:]

        result[getHashable(key)] = value

    }

}

如果 deserializeValue() 返回 []byte,则它不能作为键存储在结果映射中。数组可以工作,但我无法创建数组,因为直到运行时我才知道需要什么大小,而且它只允许编译时间常量。


简化版https://play.golang.org/p/wkYGs3S-uSD失败并出现错误


./prog.go:15:12: non-constant array bound len(slice)

如何使用已解组的字节数组作为 Go 地图中的键?


翻阅古今
浏览 103回答 2
2回答

交互式爱情

虽然使用 astring显然是更好的方法,但如果您不控制的代码使用字节数组作为键,那么您可以使用反射将字节切片转换为数组作为接口。varr := reflect.New(reflect.ArrayOf(len(slice), reflect.TypeOf(uint8(0))))reflect.Copy(varr.Elem(), reflect.ValueOf(slice))return varr.Elem().Interface()在使用它之前请考虑其他选项。游乐场: https: //play.golang.org/p/CXsxZwgjiRR

收到一只叮咚

使用string而不是固定大小的字节数组。一个字符串可以保存任意的字节序列。func getHashable(value interface{}) interface{} {    rfl := reflect.ValueOf(value)    if rfl.Kind() == reflect.Slice && rfl.Type().Elem().Kind() == reflect.Uint8 {        value = string(rfl.Bytes())    }    return value}如果您只需要处理[]byte而不是命名类型[]byte,请使用类型断言而不是反射:func getHashable(value interface{}) interface{} {    switch value := value.(type) {    case []byte:         return string(value)    default:         return value    }}如果地图的用户需要区分字符串键和从 []byte 创建的键,请定义一个字符串类型来区分这些值:type convertedSlice stringstring()将上面代码中的转换使用替换为convertedSlice().该应用程序可以通过以下方式检查转换后的密钥:_, ok := key.(convertedSlice) // ok is true if key is converted slice.并将密钥转换回 []byte :cv, ok := key.(convertedSice)if ok {   key = []byte(cv)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go