Yurkol
Yurkol

Reputation: 1482

Implementing io.Writer interface in Go

I am trying to create a structure type which satisfies io.Writer interface via Write method:

package main

import (
    "fmt"
)

type Person struct {
    name []byte
}

func (p Person) Write(data []byte) (n int, err error) {
    p.name = data
    return len(data), nil
}

func main() {
    b := []byte("Dave")
    person := Person{}
    fmt.Fprint(person, b)
    fmt.Printf("Person name: %s\n", person.name)
}

but instruction

fmt.Fprint(person, b)

doesn't work, person.Name remains empty slice. Why?

Upvotes: 4

Views: 8979

Answers (2)

Eugene Lisitsky
Eugene Lisitsky

Reputation: 12845

Two cents about value and pointer receivers. Function Write satisfying io.Writer can be defined both ways:

func (p Person) Write(data []byte) (n int, err error) {
...
}

This way function operates on a copy of the Person, that's why you don't see changes after function finishes.

And:

func (p *Person) Write(data []byte) (n int, err error) {
...
}

This way function works with a pointer to the original Person. That's why after the function end changes are visible.

Upvotes: 11

janos
janos

Reputation: 124646

If you want the Write function to modify the receiver object, you must make the receiver a pointer:

func (p *Person) Write(data []byte) (n int, err error) {
    p.name = data
    return len(data), nil
}

The fmt.Fprint function uses the default format for its operands. That's not what you want, you want to write the content of b as "%s", so you need to use fmt.Fprintf instead:

func main() {
    b := []byte("Dave")
    person := Person{}
    fmt.Fprintf(&person, "%s", b)
    fmt.Printf("Person name: %s\n", person.name)
}

See on the playground.

Upvotes: 7

Related Questions