write to a slice of bytes

9,823 views
Skip to first unread message

Mathieu Lonjaret

unread,
Oct 14, 2010, 8:25:46 AM10/14/10
to golang-nuts
Hello,

I'd like to write to slice of bytes through the use of a writer.
I've tried that:

var out []byte = make([]byte, 7)
w := bytes.NewBuffer(out)
var foo []byte = []byte{84, 240, 4, 66, 80, 4, 79}
w.Write(foo)
for i:=0; i<len(out); i++ {
print(out[i], "\n")
}

but all I get is zeroes when printing.
What am I doing wrong please?

Thanks,
Mathieu

xf wang

unread,
Oct 14, 2010, 8:35:42 AM10/14/10
to Mathieu Lonjaret, golan...@googlegroups.com
var out []byte = make([]byte, 7)

make return value

new return pointer

xf wang

unread,
Oct 14, 2010, 9:01:38 AM10/14/10
to Mathieu Lonjaret, golan...@googlegroups.com
it seems make also work


        out:=make([]byte, 0, 7)
   
       w := bytes.NewBuffer(out)       
  foo:=[]byte{84, 240, 4, 66, 80, 4, 79}        
       n,_:=w.Write(foo)    
  fmt.Println(out[0:7])

the len(out) should be 0

chris dollin

unread,
Oct 14, 2010, 9:03:18 AM10/14/10
to Mathieu Lonjaret, golang-nuts

Your slice `out` has capacity AND LENGTH 7. There is no room in
it for bytes.Write to write any bytes, so it has to grow a new slice
(with initial contents copied from `out`) to write to.

[the documentation for NewBuffer says:

It can also be used to to size the internal buffer for writing.
To do that, buf should have the desired capacity but a length
of zero.

which is why I knew about the length-and-capacity issue.
]

So your `out` slice is unchanged. You can change the make call
to give out capacity 7 and length 0:

var out []byte = make([]byte, 0, 7)

However, this doesn't visibly help, because the slice `out` has
been passed in to NewBuffer by value -- so changes to the
slice that bytes.Write is using /will not affect/ the length and
capacity of `out`. [They will change the underlying array, until
it has to expand the slice.]

Fortunately Buffer has a method Bytes() which returns a slice
of the (unread, but you didn't read anything, so that's OK) bytes
of the buffer, so you can print that out instead:

package main

import "bytes"
import "fmt"

func main() {
var out []byte = make([]byte, 0, 7)


w := bytes.NewBuffer(out)
var foo []byte = []byte{84, 240, 4, 66, 80, 4, 79}

n, err := w.Write(foo)
fmt.Printf( "w = %v\n", w.Bytes() )
}

Or you could reslice `out` and print its bytes out to show that
the underlying array has been used:

fmt.Printf( "w = %v\n", out[0:7] )

Chris

--
Chris "allusive" Dollin

chris dollin

unread,
Oct 14, 2010, 9:05:29 AM10/14/10
to xf wang, Mathieu Lonjaret, golan...@googlegroups.com

Only if you want to initialise the new buffer with no bytes to read.
(Which is true in the OPs case, but not true in general.)

fango

unread,
Oct 14, 2010, 9:27:31 AM10/14/10
to golang-nuts
I think it worth pointing out, as it is clearly stated in the package
doc, NewBuffer(out) uses out to init a buf for 'read', and Write(foo)
is to append. I guess Write is a misnomer, Append is better.

On Oct 14, 8:25 pm, Mathieu Lonjaret <mathieu.lonja...@gmail.com>
wrote:

chris dollin

unread,
Oct 14, 2010, 9:34:45 AM10/14/10
to fango, golang-nuts
On 14 October 2010 14:27, fango <fan.h...@gmail.com> wrote:
> I think it worth pointing out, as it is clearly stated in the package
> doc, NewBuffer(out) uses out to init a buf for 'read',

or write:

It is intended to prepare a Buffer to read existing data. It


can also be used to to size the internal buffer for writing.

Second sentence in the quote.

> and Write(foo) is to append. I guess Write is a misnomer, Append
> is better.

Write is better, because then bytes.Buffer satisfies the io.Writer
interface.

Russ Cox

unread,
Oct 14, 2010, 9:53:25 AM10/14/10
to Mathieu Lonjaret, golang-nuts
>        var out []byte = make([]byte, 7)
>        w := bytes.NewBuffer(out)

Here out is the initial content of the buffer.
But the buffer is a separate thing than out.
It would be very surprising (in Go) if passing
out to a function could later cause out to change
its value (and len(out) is part of its value).

>        var foo []byte = []byte{84, 240, 4, 66, 80, 4, 79}
>        w.Write(foo)
>        for i:=0; i<len(out); i++ {
>                print(out[i], "\n")
>        }

Right: print w.Bytes() instead. A simple version of your program:

package main

import (
"bytes"
"fmt"
)

func main() {
var w bytes.Buffer
w.Write([]byte("hello"))
fmt.Println(w.Bytes())
}

Russ

chris dollin

unread,
Oct 14, 2010, 10:13:58 AM10/14/10
to r...@golang.org, Mathieu Lonjaret, golang-nuts
On 14 October 2010 14:53, Russ Cox <r...@golang.org> wrote:
>>        var out []byte = make([]byte, 7)
>>        w := bytes.NewBuffer(out)
>
> Here out is the initial content of the buffer.
> But the buffer is a separate thing than out.
> It would be very surprising (in Go) if passing
> out to a function could later cause out to change
> its value (and len(out) is part of its value).

And the byte array that the slice refers to isn't?

Chris

--
Chris "it's factal all the way down" Dollin

Russ Cox

unread,
Oct 14, 2010, 10:17:13 AM10/14/10
to chris dollin, Mathieu Lonjaret, golang-nuts
>> Here out is the initial content of the buffer.
>> But the buffer is a separate thing than out.
>> It would be very surprising (in Go) if passing
>> out to a function could later cause out to change
>> its value (and len(out) is part of its value).
>
> And the byte array that the slice refers to isn't?

No, the value of the slice is [ptr to elem 0, len, cap].
http://research.swtch.com/2009/11/go-data-structures.html

Russ

chris dollin

unread,
Oct 14, 2010, 10:26:55 AM10/14/10
to r...@golang.org, Mathieu Lonjaret, golang-nuts

Yes, I understand the data structure just fine, but that
particular use of the term "value of the slice" means that
s[i] = x doesn't change the value of the slice s; consistent
but disconcerting particularly to newcomers to Go, who
may wonder why the length of a slice is part of it but the
value of its elements isn't.

Russ Cox

unread,
Oct 14, 2010, 10:34:07 AM10/14/10
to chris dollin, Mathieu Lonjaret, golang-nuts
> Yes, I understand the data structure just fine, but that
> particular use of the term "value of the slice" means that
> s[i] = x doesn't change the value of the slice s; consistent
> but disconcerting particularly to newcomers to Go, who
> may wonder why the length of a slice is part of it but the
> value of its elements isn't.

Sure. But that's still what the value of the slice is.
It's just something you have to learn when you come to Go.

Similarly, in C, p[i] = x doesn't change the value of the pointer p.

Russ

chris dollin

unread,
Oct 14, 2010, 10:39:28 AM10/14/10
to r...@golang.org, Mathieu Lonjaret, golang-nuts
On 14 October 2010 15:34, Russ Cox <r...@golang.org> wrote:
> Similarly, in C, p[i] = x doesn't change the value of the pointer p.

USUALLY not. (And I can't think of an instance when it would be the
right thing to happen ...)

Chris

--
Chris "OOPS!" Dollin

Reply all
Reply to author
Forward
0 new messages