我需要提取字节缓冲区中的各个字段.我想出了这个解决方案:

func (fs *FileSystem) readSB() {
    // fs.f is a *os.File
    buf := make([]byte, 1024)
    fs.f.ReadAt(buf, 1024)

    // Offset: type
    var p *bytes.Buffer

    // 0: uint32
    p = bytes.NewBuffer(buf[0:])
    binary.Read(p, binary.LittleEndian, &fs.sb.inodeCount)
    // 4: uint32
    p = bytes.NewBuffer(buf[4:])
    binary.Read(p, binary.LittleEndian, &fs.sb.blockCount)
    // 20: uint32
    p = bytes.NewBuffer(buf[20:])
    binary.Read(p, binary.LittleEndian, &fs.sb.firstDataBlock)
    // 24: uint32
    p = bytes.NewBuffer(buf[24:])
    binary.Read(p, binary.LittleEndian, &fs.sb.blockSize)
    fs.sb.blockSize = 1024 << fs.sb.blockSize
    // 32: uint32
    p = bytes.NewBuffer(buf[32:])
    binary.Read(p, binary.LittleEndian, &fs.sb.blockPerGroup)
    // 40: uint32
    p = bytes.NewBuffer(buf[40:])
    binary.Read(p, binary.LittleEndian, &fs.sb.inodePerBlock)
}

有没有更好/更惯用/更直截了当的方法来做这件事呢?

  • 我想让偏移量保持显式
  • 我希望从字节缓冲区读取,而不是在可能的情况下从文件中查找和读取.

推荐答案

通过使用.Next()跳过不想读取的字节,可以避免每次都创建新缓冲区:

{
    // Offset: type
    p := bytes.NewBuffer(buf)

    // 0: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.inodeCount)

    // 4: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.blockCount)

    // Skip [8:20)
    p.Next(12)

    // 20: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.firstDataBlock)

    // 24: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.blockSize)
    fs.sb.blockSize = 1024 << fs.sb.blockSize

    // Skip [28:32)
    p.Next(4)

    // 32: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.blockPerGroup)

    // Skip [36:40)
    p.Next(4)

    // 40: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.inodePerBlock)
}

或者,您可以避免逐个块读取,而创建使用binary.Read直接读取的头 struct :

type Head struct {
    InodeCount      uint32  //  0:4
    BlockCount      uint32  //  4:8
    Unknown1        uint32  //  8:12
    Unknown2        uint32  // 12:16
    Unknown3        uint32  // 16:20
    FirstBlock      uint32  // 20:24
    BlockSize       uint32  // 24:28
    Unknown4        uint32  // 28:32
    BlocksPerGroup  uint32  // 32:36
    Unknown5        uint32  // 36:40
    InodesPerBlock  uint32  // 40:44
}

func main() {
    var header Head

    err = binary.Read(file, binary.LittleEndian, &header)

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

    log.Printf("%#v\n", header)
}

Go相关问答推荐

如何在Go中使用a-h/tempson渲染预格式的内容?

golang-jWT签名无效

Golang Cososdb-gremlin连接

CGO Linux到Windows交叉编译中的未知类型名称

禁用Golang中的终端

如何使用我的 struct 化日志(log)记录格式使人panic ?

在Golang中Mergesort的递归/并行实现中出现死锁

Kafka golang 生产者在错误后更改分区计数

正则表达式模式,确保至少一个字符与其他条件一起存在

如何处理 Go 的 firebase admin sdk 错误?

在 Golang 模板中计算时间/持续时间

具有两个或多个模型的 GORM 查询

如何根据 Go 中第二次出现的分隔符拆分字符串?

我相信我正确地在 sRGB 和线性 RGB 之间进行了转换,那么为什么深色的结果看起来更糟呢?

在我的情况下,如何以正确的方式测试方法?

自定义指标未显示在 prometheus web ui 中,grafana 中也是如此

分配空切片而不引用其类型?

gqlgen go,通过添加一个解析器来减少数据库调用

如何将实际上是类型为 reflect.Int32 的类型切片的 interface{} 转换为 int32 的切片?

Go 赋值涉及到自定义类型的指针