走。将 []byte 写入文件导致零字节文件

Go. Writing []byte to file results in zero byte file

我尝试将结构化数据序列化到文件中。我查看了一些示例并进行了这样的构建:

func (order Order) Serialize(folder string) {
    b := bytes.Buffer{}
    e := gob.NewEncoder(&b)
    err := e.Encode(order)
    if err != nil { panic(err) }

    os.MkdirAll(folder, 0777)
    file, err := os.Create(folder + order.Id)
    if err != nil {  panic(err) }
    defer file.Close()


    writer := bufio.NewWriter(file)
    n, err := writer.Write(b.Bytes())

    fmt.Println(n)

    if err != nil {
        panic(err)
    }
}

Serialize 是一种将其对象序列化为由其 id 属性 调用的文件的方法。我查看了调试器 - 字节缓冲区包含写入前的数据。我的意思是对象已完全初始化。即使 n 表示写入字节数的变量也超过一千 - 文件根本不应该为空。该文件已创建,但它完全是空的。怎么了?

bufio.Writer (as the package name hints) uses a buffer to cache writes. If you ever use it, you must call Writer.Flush() when you're done writing to it to ensure the buffered data gets written to the underlying io.Writer.

另请注意,您可以直接写入 os.File,无需创建缓冲写入器 "around"。 (*os.File 实施 io.Writer)。

另请注意,您可以创建 gob.Encoder directly directed to the os.File, so even the bytes.Buffer 是不必要的。

另外 os.MkdirAll() 可能会失败,请检查其 return 值。

此外,最好使用 filepath.Join() 对文件路径的 "concatenate" 部分进行处理,这样可以处理文件夹名称末尾多余的/缺失的斜杠。

最后,最好发出 Serialize() 失败的信号,例如具有 error return 值,因此调用方有机会检查操作是否成功,并采取相应行动。

所以 Order.Serialize() 应该是这样的:

func (order Order) Serialize(folder string) error {
    if err := os.MkdirAll(folder, 0777); err != nil {
        return err
    }

    file, err := os.Create(filepath.Join(folder, order.Id))
    if err != nil {
        return err
    }
    defer file.Close()

    if err := gob.NewEncoder(file).Encode(order); err != nil {
        return err
    }

    return nil
}