Golang中gob.Decode和Encode的疑难问题求助
Golang中gob.Decode和Encode的疑难问题求助 大家好,这是我第一次在论坛发帖。
我想将一些结构体写入二进制文件,经过搜索,我找到了以下两个函数来实现这个功能。
func writeGob(path string, object interface{}, offset int64) error {
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0777)
if err != nil {
PrintError("Error intentando abrir el archivo")
return errors.New("Error intentado abrir el archivo")
}
file.Seek(offset, 0)
encoder := gob.NewEncoder(file)
encoder.Encode(object)
file.Close()
return err
}
func readGob(path string, offset int64, object interface{}) error {
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 666)
if err != nil {
PrintError("Error intentando abrir el archivo: " + err.Error())
return errors.New("Error intentando abrir el archivo")
}
file.Seek(offset, 0)
decoder := gob.NewDecoder(file)
err = decoder.Decode(object)
file.Close()
return err // must be nil
}
这是我正在使用的两个结构体。
type Ebr struct {
PartStatus uint8
PartFit uint8
PartStart int64
PartSize int64
PartName [16]uint8
PartNext int64
}
type Mbr struct {
MbrTamanio int64
MbrFechaCreacion [20]uint8
MbrDiskSignature int64
DiskFit uint8
MbrPartition [4]Partition
}
简单来说,这是一个为大学作业实现的微型 ext2 文件系统。
一切进展顺利,直到我尝试读取一个 Ebr 结构体时遇到了以下错误:
gob: Duplicate types received
这是发生错误的代码行。
var ebr = new(Ebr)
err := readGob(c.Args["path"].(string), ext.PartStart, ebr)
我在谷歌上搜索了这个错误,但没有找到任何帮助。所以,如果你能帮助我,我将非常感激。
更多关于Golang中gob.Decode和Encode的疑难问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢您的回复。我一直在调试,偏移量似乎是相同的。我进行了一些测试,先写入EBR,然后立即读取,一切正常。但是,如果尝试从代码的另一部分读取它,就会出现错误。
更多关于Golang中gob.Decode和Encode的疑难问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
ext.PartStart
您很可能从错误的偏移量开始读取,导致 gob 内部机制误解了它试图解码的内容。
// 代码示例(如有)应放置于此
这个错误通常发生在多次调用 gob.Decode() 时,解码器遇到重复注册的类型定义。Gob 需要在编解码双方注册相同的类型,但多次注册会导致此错误。
在你的代码中,每次调用 readGob() 都会创建新的解码器,但文件可能包含多个 gob 数据。当解码器遇到已经注册过的类型时,就会报 “Duplicate types received” 错误。
以下是修复方案:
import (
"bytes"
"encoding/gob"
"os"
)
// 在 init 函数中注册类型,确保只注册一次
func init() {
gob.Register(Ebr{})
gob.Register(Mbr{})
gob.Register(Partition{}) // 如果 Partition 是自定义类型也需要注册
}
func writeGob(path string, object interface{}, offset int64) error {
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0777)
if err != nil {
return err
}
defer file.Close()
_, err = file.Seek(offset, 0)
if err != nil {
return err
}
encoder := gob.NewEncoder(file)
return encoder.Encode(object)
}
func readGob(path string, offset int64, object interface{}) error {
file, err := os.OpenFile(path, os.O_RDONLY, 0666)
if err != nil {
return err
}
defer file.Close()
_, err = file.Seek(offset, 0)
if err != nil {
return err
}
// 使用缓冲读取器避免重复类型问题
var buf bytes.Buffer
_, err = buf.ReadFrom(file)
if err != nil {
return err
}
decoder := gob.NewDecoder(&buf)
return decoder.Decode(object)
}
如果文件包含多个连续的 gob 数据,应该使用同一个解码器连续解码:
func readMultipleGobs(path string) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
decoder := gob.NewDecoder(file)
// 读取第一个结构
var mbr Mbr
if err := decoder.Decode(&mbr); err != nil {
return err
}
// 读取第二个结构(使用同一个解码器)
var ebr Ebr
if err := decoder.Decode(&ebr); err != nil {
return err
}
return nil
}
对于你的具体使用场景,确保在程序启动时注册所有相关类型,并且对于包含多个 gob 数据的文件,使用同一个解码器实例进行连续解码。

