go - 我们如何知道字节数组上的结构类型

标签 go struct

我正在寻找一些解决方案来了解散列的结构类型。是否可以在不尝试错误方法的情况下做到这一点(转换为特定类型并查看转换是否成功)?

请检查代码:

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "reflect"
)

type T struct {
    A int64
    B float64
}

type D struct {
    A int64
    B float64
    C string
}


func main() {
    // Create a struct and write it.
    t := T{A: 0xEEFFEEFF, B: 3.14}
    buf := &bytes.Buffer{}
    err := binary.Write(buf, binary.BigEndian, t)
    if err != nil {
        panic(err)
    }
    fmt.Println(buf.Bytes())

    out := getType(buf)
    fmt.Println(out)
}

func getType(v interface{})(r string){
    fmt.Println(reflect.TypeOf(v))
    switch t := v.(type) {
        case T:
            return "Is type T"
        case D:
            return "Is type D"
        default:
            _ = t
            return "unknown"
    }
}

最佳答案

encoding/binary包没有写出类型信息,无法判断写入/序列化的类型。

而且您的处境比您最初认为的更糟:即使尝试解码为不同类型的值也可能成功而不会出错,因此甚至没有一种可靠的方法来判断类型。

例如,如果您序列化这种类型的值:

type T struct {
    A int64
    B float64
}

您可以将其读入此类型的值:

type T2 struct {
    B float64
    A int64
}

它不会给出错误,因为两个结构的大小相同,但显然你会在字段中得到不同的数字。

如果您使用 encoding/gob,您的位置会好一些,因为 gob 包确实传输类型信息,并且编码类型 T 的值然后将其解码为类型 T2 的值将起作用: 字段顺序无关紧要,额外或缺少字段也不会造成问题。

看这个例子:

// Create a struct and write it.
t := T{A: 0xEEFFEEFF, B: 3.14}
fmt.Println("Encoding:", t)
buf := &bytes.Buffer{}
fmt.Println(binary.Write(buf, binary.BigEndian, t))
fmt.Println(buf.Bytes())

fmt.Println(gob.NewEncoder(buf).Encode(t))

t2 := T2{}
fmt.Println(binary.Read(buf, binary.BigEndian, &t2))
fmt.Println(t2)

t2 = T2{}
fmt.Println(gob.NewDecoder(buf).Decode(&t2))
fmt.Println(t2)

输出(在 Go Playground 上尝试):

Encoding: {4009750271 3.14}
<nil>
[0 0 0 0 238 255 238 255 64 9 30 184 81 235 133 31]
<nil>
<nil>
{1.9810798573e-314 4614253070214989087}
<nil>
{3.14 4009750271}

如果你想在读取类型之前能够检测到它,你必须自己处理:你必须传输类型信息(例如类型的名称)。或者更好的是,使用已经执行此操作的序列化方法,例如 Google's protocol buffers ,这是它的 Go 实现:github.com/golang/protobuf .

关于go - 我们如何知道字节数组上的结构类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41589055/

相关文章:

struct - 如何在 julia 中复制结构

c - 带指针的 C 数组队列

go - 如何实现 Python functools.wraps 等效?

go - 无法从 Go lang 中的结构类型 channel 中获取值

go:暴露的别名结构无法分配给内部结构文字

c++ - 为什么将 char 数组复制到结构中时 memcpy 不起作用?

c - 如何在匿名成员中存储结构数组?

c++ - 如何序列化结构并将其存储在 MySQL 数据库中?

mongodb - mongodb无法在Go中执行事务,并且总是得到无法在多文档事务中创建 namespace

concurrency - sync.WaitGroup 不等待