Ibnjunaid
Ibnjunaid

Reputation: 512

fmt.Println vs os.Stdout.Write

I had this code where I convert a string into a []byte slice using json.Marshal. When printing, why does fmt.Println() write numbers to stdout while os.Stdout.Write writes the string.

My question is how does fmt.Println parse the []byte.

package main

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

func main(){
    str := "My string"
    dat,_:= json.Marshal(str)
    fmt.Println(dat)
    os.Stdout.Write(dat)
}

I get the following Output

[34 77 121 32 115 116 114 105 110 103 34]
"My string"

Upvotes: 0

Views: 8000

Answers (1)

Marc
Marc

Reputation: 21045

fmt.Println generates the friendly format for a byte slice. Because byte slices can contain anything at all (and not just printable characters), it shows you the individual byte values. Per the docs: a byte slice is printed out as:

the uninterpreted bytes of the string or slice

On the other hand, os.Stdout.Write writes the byte slice to standard out. Because they are printable characters, your terminal renders them properly.

Try it with non-printable characters, and the reason for fmt.Println's behavior will become clear:

func main() {
    dat := []byte{0, 1, 2, 3, 4}
    fmt.Println(dat)
    os.Stdout.Write(dat)
}

Outputs:

[0 1 2 3 4]
XXXX // four non-printable character placeholders (based on your terminal)

As for json, its output is a byte slice since this is the most useful format to be passed to a writer (network, disk, storage, etc...).

Upvotes: 7

Related Questions