Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

io.Writer in Go - beginner trying to understand them

Tags:

go

writer

As a beginner in Go, I have problems understanding io.Writer.

My target: take a struct and write it into a json file.

Approach:
- use encoding/json.Marshal to convert my struct into bytes
- feed those bytes to an os.File Writer

This is how I got it working:

package main

import (
    "os"
    "encoding/json"
)

type Person struct {
    Name string
    Age uint
    Occupation []string
}

func MakeBytes(p Person) []byte {
    b, _ := json.Marshal(p)
    return b
}

func main() {
    gandalf := Person{
        "Gandalf",
        56,
        []string{"sourcerer", "foo fighter"},
    }

    myFile, err := os.Create("output1.json")
    if err != nil {
        panic(err)
    }
    myBytes := MakeBytes(gandalf)
    myFile.Write(myBytes)
}

After reading this article, I changed my program to this:

package main

import (
    "io"
    "os"
    "encoding/json"
)

type Person struct {
    Name string
    Age uint
    Occupation []string
}

// Correct name for this function would be simply Write
// but I use WriteToFile for my understanding
func (p *Person) WriteToFile(w io.Writer) {
    b, _ := json.Marshal(*p)
    w.Write(b)
}

func main() {
    gandalf := Person{
        "Gandalf",
        56,
        []string{"sourcerer", "foo fighter"},
    }

    myFile, err := os.Create("output2.json")
    if err != nil {
        panic(err)
    }
    gandalf.WriteToFile(myFile)
}

In my opinion, the first example is a more straightforward and easier to understand for a beginner... but I have the feeling that the 2nd example is the Go idiomatic way of achieving the target.

Questions:
1. is above assumption correct (that 2nd option is Go idiomatic) ?
2. Is there a difference in the above options ? Which option is better ?
3. other ways to achieve the same target ?

Thank you,

WM

like image 314
whyme Avatar asked May 04 '17 21:05

whyme


People also ask

What is io Writer in Golang?

The io.Writer interface is used by many packages in the Go standard library and it represents the ability to write a byte slice into a stream of data. More generically allows you to write data into something that implements the io.Writer interface.

What is reader and Writer in Golang?

Reader/Writer are basic interfaces designed in Golang. For example, if a struct have a function like: type Example struct { }func (e *Example) Write(p byte[]) (n int, err error) {}func (e *Example) Read(p byte[]) (n int, err error) {}


1 Answers

The benefit of using the second method is that if you are passing a Writer interface, you can pass anything which implements Write -- that is not only a file but a http.ResponseWriter, for example, or stdout os.Stdout, without changing the struct methods.

You can see this handy blog post on the package io walkthrough. The author makes the case that passing as parameter readers and writers makes your code more flexible, in part because so many functions use the Reader and Writer interface.

As you come to use Go more, you'll notice how much the standard library leans on Reader and Writer interfaces, and probably come to appreciate it :)

So this function (renamed):

// writes json representation of Person to Writer
func (p *Person) WriteJson(w io.Writer) error {
    b, err := json.Marshal(*p)
    if err != nil {
        return err
    }
    _, err = w.Write(b)
    if err != nil {
        return err
    }
    return err
}

Would write to a File, http Response, a user's Stdout, or even a simple byte Buffer; making testing a bit simpler.

I renamed it because of what is does; that is, this function takes a Person struct and:

  1. Marshals the struct into a json representation
  2. Writes the json to a Writer
  3. Returns any errors arising from marshalling/writing

One more thing, you might be confused as to what a Writer is, because it is not a data type, but rather an interface -- that is a behavior of a data type, a predefined method that a type implements. Anything that implements the Write() method, then, is considered a writer.

This can be a bit difficult for beginners to grasp at first, but there are lots of resources online to help understand interfaces (and ReadWriters are some of the more common interfaces to encounter, along with Error() (ei. all errors)).

like image 87
Nevermore Avatar answered Nov 02 '22 04:11

Nevermore