我完全是个新手.我看了Coursera Introduction to Go Language个,但有些话题没有深入讨论.

为了练习围棋,我从CS50开始尽可能多地做练习.我现在正在处理example,我需要在其中读取BMP文件,将头内容复制到相应的数据 struct 中,更改此 struct 中的一些参数,然后将结果复制到新文件中.

我注意到的第一件事是,我不能将与我创建的 struct 的大小相对应的字节数读作二进制.这是由于在构建 struct 时可能发生的填充.我能够逐个字段地读取,并填充了 struct .

为了改进这一点,我试图迭代 struct ,获取每个字段的大小,从文件中读取相应的字节数,然后在迭代 struct 之后再次写入文件.

我陷入了最后一步(如果前面的步骤正确完成的话):我如何才能根据字段类型正确设置值?


package main

import (
    "bufio"
    "encoding/binary"
    "fmt"
    "os"
    "reflect"
)

type DWORD uint32
type WORD uint16
type BITMAPFILEHEADER struct {
    BfType      WORD
    BfSize      DWORD
    BfReserved1 WORD
    BfReserved2 WORD
    BfOffBits   DWORD
}

func main() {
    input_file, err := os.Open("harvard_bottomup.bmp")
    if err != nil {
        fmt.Println("Could not open the origin file.")
        fmt.Println(err)
    }

    var bf BITMAPFILEHEADER
    reader := bufio.NewReader(input_file)

    value := reflect.ValueOf(&bf).Elem()
    n := value.NumField()
    structType := value.Type()
    for i := 0; i < n; i++ {

        b := make([]byte, structType.Field(i).Type.Size())
        err = binary.Read(reader, binary.BigEndian, b)
        if err != nil {
            fmt.Println(err)
        }

        fmt.Printf("Field Name: %-15s %-15s  %02x\n", structType.Field(i).Name, structType.Field(i).Type, b)
        // I should now set the value, but I don't know how to switch between types
        // value.Field(i).Set...
    }

    input_file.Close()
}

PS:在此之前,我try 直接读取 struct 中的字段,但我做不到.

推荐答案

看起来您正在复制binary.Read函数中的功能.该函数将按指定字节顺序的数据解码为 struct 中的连续字段.您可以查看 struct 解码代码here.

以下是如何使用Read对文件头进行解码:

input_file, err := os.Open("harvard_bottomup.bmp")
if err != nil {
    fmt.Println("Could not open the origin file.")
    fmt.Println(err)
    return
}
defer input_file.Close()
reader := bufio.NewReader(input_file)

var bf BITMAPFILEHEADER
err = binary.Read(reader, binary.BigEndian, &bf)
if err != nil {
    fmt.Println(err)
    return
}

Go相关问答推荐

gorm如何声明未自动更新的unix时间戳米尔斯字段

在字符串与字符串子切片上使用len进行位转移产生意外输出

具有GRPC的RBAC(基于角色的访问控制)-网关生成的REST风格的API

Go:拆分一个由逗号分隔的键/值对字符串,并在给定的键/价值对中嵌入可能的逗号

Go:为什么我不能比较 net.Addr

Go:如何在不加载正文的情况下创建 http 代理通行证

golang gin 获取 cookie json

是否可以在调试期间在 VSCode 中预览 github.com/shopspring/decimal 值?

Golang 网络应用程序安全性:您是否应该判断输入是否为有效的 utf-8?

Golang 创建一个带有处理程序的模拟数据库并使用接口调用数据库

在本地 go 应用程序上获取秘密的正确策略

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

从 Makefile 运行时权限被拒绝

Go 泛型:自引用接口约束

Golang prometheus 显示自定义指标

vs 代码调试 go 测试不通过标志

如何在golang中使用ozzo验证进行时间最大验证

从 Go struct 中提取标签作为 reflect.Value

Go/Golang:如何从 big.Float 中提取最低有效数字?

即使没有竞争条件也没有得到任何输出