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

I try to serialize a structured data to file. I looked through some examples and made such construction:

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 is a method serializing its object to file called by it's id property. I looked through debugger - byte buffer contains data before writing. I mean object is fully initialized. Even n variable representing quantity of written bytes is more than a thousand - the file shouldn't be empty at all. The file is created but it is totally empty. What's wrong?

Upvotes: 3

Views: 3214

Answers (1)

icza
icza

Reputation: 417592

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.

Also note that you can directly write to an os.File, no need to create a buffered writer "around" it. (*os.File implements io.Writer).

Also note that you can create the gob.Encoder directly directed to the os.File, so even the bytes.Buffer is unnecessary.

Also os.MkdirAll() may fail, check its return value.

Also it's better to "concatenate" parts of a file path using filepath.Join() which takes care of extra / missing slashes at the end of folder names.

And last, it would be better to signal the failure of Serialize(), e.g. with an error return value, so the caller party has the chance to examine if the operation succeeded, and act accordingly.

So Order.Serialize() should look like this:

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
}

Upvotes: 4

Related Questions