├── .gitignore ├── LICENSE ├── README.md ├── bytes.go ├── go.mod ├── go.sum ├── slice.go └── slice_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Golang Plus 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of bytes nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bytes [![GoSearch](http://go-search.org/badge?id=github.com%2Fgolangplus%2Fbytes)](http://go-search.org/view?id=github.com%2Fgolangplus%2Fbytes) 2 | Plus to the standard `bytes` package. 3 | 4 | ## Featured 5 | ```go 6 | // ByteSlice is a wrapper type for []byte. 7 | // Its pointer form, *ByteSlice, implements io.Reader, io.Writer, io.ByteReader, 8 | // io.ByteWriter, io.Closer, io.ReaderFrom, io.WriterTo and io.RuneReader 9 | // interfaces. 10 | // 11 | // Benchmark shows *ByteSlice is a better alternative for bytes.Buffer for writings and consumes less resource. 12 | type ByteSlice []byte 13 | ``` 14 | ([blog about ByteSlice](http://daviddengcn.blogspot.com/2015/07/a-light-and-fast-type-for-serializing.html)) 15 | 16 | ## LICENSE 17 | BSD license 18 | -------------------------------------------------------------------------------- /bytes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Golang Plus Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package bytesp is a plus to the standard "bytes" package. 7 | */ 8 | package bytesp 9 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golangplus/bytes 2 | 3 | go 1.14 4 | 5 | require github.com/golangplus/testing v1.0.0 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= 2 | github.com/golangplus/fmt v1.0.0 h1:FnUKtw86lXIPfBMc3FimNF3+ABcV+aH5F17OOitTN+E= 3 | github.com/golangplus/fmt v1.0.0/go.mod h1:zpM0OfbMCjPtd2qkTD/jX2MgiFCqklhSUFyDW44gVQE= 4 | github.com/golangplus/testing v1.0.0 h1:+ZeeiKZENNOMkTTELoSySazi+XaEhVO0mb+eanrSEUQ= 5 | github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA= 6 | -------------------------------------------------------------------------------- /slice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Golang Plus Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bytesp 6 | 7 | import ( 8 | "errors" 9 | "io" 10 | "strconv" 11 | "unicode/utf8" 12 | ) 13 | 14 | // Slice is a wrapper type for []byte. 15 | // Its pointer form, *Slice, implements io.Reader, io.Writer, io.ByteReader, 16 | // io.ByteWriter, io.Closer, io.ReaderFrom, io.WriterTo and io.RuneReader 17 | // interfaces. 18 | // 19 | // Benchmark shows *Slice is a better alternative for bytes.Buffer for writings and consumes less resource. 20 | type Slice []byte 21 | 22 | var ( 23 | // Make sure *Slice implement the interfaces. 24 | _ io.Reader = (*Slice)(nil) 25 | _ io.Writer = (*Slice)(nil) 26 | _ io.ByteReader = (*Slice)(nil) 27 | _ io.ByteWriter = (*Slice)(nil) 28 | _ io.Closer = (*Slice)(nil) 29 | _ io.ReaderFrom = (*Slice)(nil) 30 | _ io.WriterTo = (*Slice)(nil) 31 | _ io.RuneReader = (*Slice)(nil) 32 | ) 33 | 34 | // NewPSlice returns a *Slice with intialized contents. 35 | func NewPSlice(bytes []byte) *Slice { 36 | return (*Slice)(&bytes) 37 | } 38 | 39 | // Read implements the io.Reader interface. 40 | // After some bytes are read, the slice shrinks. 41 | func (s *Slice) Read(p []byte) (n int, err error) { 42 | if len(p) == 0 { 43 | return 0, nil 44 | } 45 | 46 | if len(*s) == 0 { 47 | return 0, io.EOF 48 | } 49 | n = copy(p, *s) 50 | 51 | if n == len(*s) { 52 | *s = nil 53 | } else { 54 | *s = (*s)[n:] 55 | } 56 | 57 | return n, nil 58 | } 59 | 60 | // Reset sets the length of the slice to 0. 61 | func (s *Slice) Reset() { 62 | *s = (*s)[:0] 63 | } 64 | 65 | // Skip skips n bytes. 66 | func (s *Slice) Skip(n int64) (int64, error) { 67 | if n == 0 { 68 | return 0, nil 69 | } 70 | 71 | if len(*s) == 0 { 72 | return 0, io.EOF 73 | } 74 | if n >= int64(len(*s)) { 75 | n = int64(len(*s)) 76 | *s = nil 77 | } else { 78 | *s = (*s)[int(n):] 79 | } 80 | return n, nil 81 | } 82 | 83 | // Write implements the io.Writer interface. 84 | // Bytes are appended to the tail of the slice. 85 | func (s *Slice) Write(p []byte) (n int, err error) { 86 | *s = append(*s, p...) 87 | return len(p), nil 88 | } 89 | 90 | // ReadByte implements the io.ByteReader interface. 91 | func (s *Slice) ReadByte() (c byte, err error) { 92 | if len(*s) < 1 { 93 | return 0, io.EOF 94 | } 95 | 96 | c = (*s)[0] 97 | if len(*s) > 1 { 98 | *s = (*s)[1:] 99 | } else { 100 | *s = nil 101 | } 102 | return c, nil 103 | } 104 | 105 | // WriteByte implements the io.ByteWriter interface. 106 | func (s *Slice) WriteByte(c byte) error { 107 | *s = append(*s, c) 108 | return nil 109 | } 110 | 111 | // Close implements the io.Closer interface. 112 | // It does nothing. 113 | func (s Slice) Close() error { 114 | return nil 115 | } 116 | 117 | // ReadFrom implements the io.ReaderFrom interface. 118 | func (s *Slice) ReadFrom(r io.Reader) (n int64, err error) { 119 | const buf_SIZE = 32 * 1024 120 | buf := make([]byte, buf_SIZE) 121 | for { 122 | nRead, err := r.Read(buf) 123 | if nRead == 0 { 124 | if err != io.EOF { 125 | return n, err 126 | } 127 | break 128 | } 129 | n += int64(nRead) 130 | *s = append(*s, buf[:nRead]...) 131 | if err == io.EOF { 132 | break 133 | } 134 | 135 | if err != nil { 136 | return n, err 137 | } 138 | } 139 | 140 | return n, nil 141 | } 142 | 143 | // WriteTo implements the io.WriterTo interface. 144 | func (s Slice) WriteTo(w io.Writer) (n int64, err error) { 145 | nWrite, err := w.Write(s) 146 | return int64(nWrite), err 147 | } 148 | 149 | // ReadRune implements the io.RuneReader interface. 150 | func (s *Slice) ReadRune() (r rune, size int, err error) { 151 | if !utf8.FullRune(*s) { 152 | return utf8.RuneError, 0, io.ErrUnexpectedEOF 153 | } 154 | r, size = utf8.DecodeRune(*s) 155 | *s = (*s)[size:] 156 | 157 | return r, size, err 158 | } 159 | 160 | // error for a invalid rune 161 | var ErrInvalidRune = errors.New("Slice: invalid rune") 162 | 163 | var emptySlices = [...][]byte{ 164 | nil, 165 | {0}, 166 | {0, 0}, 167 | {0, 0, 0}, 168 | {0, 0, 0, 0}, 169 | } 170 | 171 | // WriteRune writes a single Unicode code point, returning the number of bytes 172 | // written and any error. 173 | func (s *Slice) WriteRune(r rune) (size int, err error) { 174 | if r < utf8.RuneSelf { 175 | *s = append(*s, byte(r)) 176 | return 1, nil 177 | } 178 | 179 | l := utf8.RuneLen(r) 180 | if l < 0 { 181 | return 0, ErrInvalidRune 182 | } 183 | 184 | *s = append(*s, emptySlices[l]...) 185 | utf8.EncodeRune((*s)[len(*s)-l:], r) 186 | return l, nil 187 | } 188 | 189 | // WriteString appends the contents of str to the slice, growing the slice as 190 | // needed. The return value n is the length of str; err is always nil. 191 | func (s *Slice) WriteString(str string) (size int, err error) { 192 | *s = append(*s, str...) 193 | return len(str), nil 194 | } 195 | 196 | // WriteItoa converts i into text of the specified base and write to s. 197 | func (s *Slice) WriteItoa(i int64, base int) (size int, err error) { 198 | l := len(*s) 199 | *s = strconv.AppendInt([]byte(*s), i, base) 200 | return len(*s) - l, nil 201 | } 202 | -------------------------------------------------------------------------------- /slice_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Golang Plus Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bytesp 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "fmt" 11 | "io" 12 | "testing" 13 | "unicode/utf8" 14 | 15 | "github.com/golangplus/testing/assert" 16 | ) 17 | 18 | func ExampleSlice() { 19 | var b Slice 20 | b.WriteByte(65) 21 | b.WriteString("bc") 22 | 23 | fmt.Println(b) 24 | fmt.Println(string(b)) 25 | // OUTPUT: 26 | // [65 98 99] 27 | // Abc 28 | } 29 | 30 | func TestSlice(t *testing.T) { 31 | var bs Slice 32 | assert.Equal(t, "len(bs)", len(bs), 0) 33 | assert.StringEqual(t, "bs", bs, "[]") 34 | 35 | n, err := bs.Skip(1) 36 | assert.Equal(t, "err", err, io.EOF) 37 | assert.Equal(t, "n", n, int64(0)) 38 | 39 | c, err := bs.ReadByte() 40 | assert.Equal(t, "err", err, io.EOF) 41 | 42 | bs.Write([]byte{1}) 43 | c, err = bs.ReadByte() 44 | assert.NoError(t, err) 45 | assert.Equal(t, "c", c, byte(1)) 46 | assert.Equal(t, "len(bs)", len(bs), 0) 47 | 48 | bs.Write([]byte{1, 2, 3}) 49 | n, err = bs.Skip(4) 50 | assert.NoError(t, err) 51 | assert.Equal(t, "n", n, int64(3)) 52 | 53 | bs.Write([]byte{1, 2, 3}) 54 | assert.Equal(t, "len(bs)", len(bs), 3) 55 | assert.StringEqual(t, "bs", bs, "[1 2 3]") 56 | 57 | cnt, err := bs.Read(nil) 58 | assert.NoError(t, err) 59 | assert.Equal(t, "cnt", cnt, 0) 60 | assert.Equal(t, "len(bs)", len(bs), 3) 61 | assert.Equal(t, "bs", bs, Slice([]byte{1, 2, 3})) 62 | 63 | n, err = bs.Skip(0) 64 | assert.NoError(t, err) 65 | assert.Equal(t, "n", n, int64(0)) 66 | assert.Equal(t, "len(bs)", len(bs), 3) 67 | assert.Equal(t, "bs", bs, Slice([]byte{1, 2, 3})) 68 | 69 | p := make([]byte, 2) 70 | bs.Read(p) 71 | assert.Equal(t, "len(bs)", len(bs), 1) 72 | assert.StringEqual(t, "bs", bs, "[3]") 73 | assert.StringEqual(t, "p", p, "[1 2]") 74 | 75 | bs.Read(make([]byte, 1)) 76 | assert.Equal(t, "len(bs)", len(bs), 0) 77 | assert.StringEqual(t, "bs", bs, "[]") 78 | 79 | bs.Write([]byte{4, 5}) 80 | assert.Equal(t, "len(bs)", len(bs), 2) 81 | assert.StringEqual(t, "bs", bs, "[4 5]") 82 | 83 | bs.WriteByte(6) 84 | 85 | c, err = bs.ReadByte() 86 | assert.NoError(t, err) 87 | assert.Equal(t, "c", c, byte(4)) 88 | assert.StringEqual(t, "bs", bs, "[5 6]") 89 | 90 | bs.WriteRune('A') 91 | assert.Equal(t, "len(bs)", len(bs), 3) 92 | assert.StringEqual(t, "bs", bs, "[5 6 65]") 93 | bs.WriteRune('中') 94 | assert.Equal(t, "len(bs)", len(bs), 6) 95 | assert.StringEqual(t, "bs", bs, "[5 6 65 228 184 173]") 96 | 97 | bs.WriteString("世界") 98 | assert.Equal(t, "len(bs)", len(bs), 12) 99 | assert.StringEqual(t, "bs", bs, "[5 6 65 228 184 173 228 184 150 231 149 140]") 100 | 101 | bs.Skip(1) 102 | assert.StringEqual(t, "bs", bs, "[6 65 228 184 173 228 184 150 231 149 140]") 103 | 104 | bs.Close() 105 | 106 | bs.Reset() 107 | fmt.Fprint(&bs, "ABC") 108 | assert.StringEqual(t, "bs", bs, "[65 66 67]") 109 | 110 | data := make([]byte, 35*1024) 111 | io.ReadFull(rand.Reader, data) 112 | bs = nil 113 | n, err = bs.ReadFrom(bytes.NewReader(data)) 114 | assert.NoError(t, err) 115 | assert.Equal(t, "n", n, int64(len(data))) 116 | assert.Equal(t, "bs == data", bytes.Equal(bs, data), true) 117 | 118 | bs = nil 119 | n, err = Slice(data).WriteTo(&bs) 120 | assert.NoError(t, err) 121 | assert.Equal(t, "n", n, int64(len(data))) 122 | assert.Equal(t, "bs == data", bytes.Equal(bs, data), true) 123 | 124 | bs = []byte("A中文") 125 | r, size, err := bs.ReadRune() 126 | assert.NoError(t, err) 127 | assert.Equal(t, "size", size, 1) 128 | assert.Equal(t, "r", r, 'A') 129 | r, size, err = bs.ReadRune() 130 | assert.NoError(t, err) 131 | assert.Equal(t, "size", size, len([]byte("中"))) 132 | assert.Equal(t, "r", r, '中') 133 | r, size, err = bs.ReadRune() 134 | assert.NoError(t, err) 135 | assert.Equal(t, "size", size, len([]byte("文"))) 136 | assert.Equal(t, "r", r, '文') 137 | } 138 | 139 | func TestSlice_Bug_Read(t *testing.T) { 140 | var s Slice 141 | n, err := s.Read(make([]byte, 1)) 142 | t.Logf("n: %d, err: %v", n, err) 143 | assert.Equal(t, "n", 0, 0) 144 | assert.Equal(t, "err", err, io.EOF) 145 | } 146 | 147 | type readerReturningEOFLastRead int 148 | 149 | func (r *readerReturningEOFLastRead) Read(p []byte) (n int, err error) { 150 | if len(p) == 0 { 151 | return 0, nil 152 | } 153 | n = int(*r) 154 | if len(p) < n { 155 | n = len(p) 156 | } 157 | for i := 0; i < n; i++ { 158 | p[i] = 1 159 | } 160 | *r -= readerReturningEOFLastRead(n) 161 | if *r == 0 { 162 | return n, io.EOF 163 | } 164 | return n, nil 165 | } 166 | 167 | func TestSlice_ReadFrom(t *testing.T) { 168 | src := make([]byte, 63*1024) 169 | for i := range src { 170 | src[i] = byte(i) 171 | } 172 | b := bytes.NewBuffer(src) 173 | var s Slice 174 | n, err := s.ReadFrom(b) 175 | assert.Equal(t, "n", n, int64(len(src))) 176 | assert.NoError(t, err) 177 | assert.Equal(t, "s", s, Slice(src)) 178 | } 179 | 180 | type readerReturningEOFAfterLastRead int 181 | 182 | func (r *readerReturningEOFAfterLastRead) Read(p []byte) (n int, err error) { 183 | if len(p) == 0 { 184 | return 0, nil 185 | } 186 | n = int(*r) 187 | if len(p) < n { 188 | n = len(p) 189 | } 190 | for i := 0; i < n; i++ { 191 | p[i] = 2 192 | } 193 | *r -= readerReturningEOFAfterLastRead(n) 194 | if n == 0 { 195 | return n, io.EOF 196 | } 197 | return n, nil 198 | } 199 | 200 | func TestSlice_ReadFromEOF(t *testing.T) { 201 | r1 := readerReturningEOFLastRead(1) 202 | var s Slice 203 | n, err := s.ReadFrom(&r1) 204 | assert.Equal(t, "n", n, int64(1)) 205 | assert.NoError(t, err) 206 | assert.Equal(t, "s", s, Slice([]byte{1})) 207 | 208 | r2 := readerReturningEOFAfterLastRead(1) 209 | s = nil 210 | n, err = s.ReadFrom(&r2) 211 | assert.Equal(t, "n", n, int64(1)) 212 | assert.NoError(t, err) 213 | assert.Equal(t, "s", s, Slice([]byte{2})) 214 | } 215 | 216 | type readerErrUnexpectedEOF int 217 | 218 | func (r *readerErrUnexpectedEOF) Read(p []byte) (n int, err error) { 219 | if len(p) == 0 { 220 | return 0, nil 221 | } 222 | n = int(*r) 223 | if len(p) < n { 224 | n = len(p) 225 | } 226 | for i := 0; i < n; i++ { 227 | p[i] = 3 228 | } 229 | *r -= readerErrUnexpectedEOF(n) 230 | if *r == 0 { 231 | return n, io.ErrUnexpectedEOF 232 | } 233 | return n, nil 234 | } 235 | 236 | func TestSlice_ReadFromFailed(t *testing.T) { 237 | r0 := readerErrUnexpectedEOF(0) 238 | var s Slice 239 | n, err := s.ReadFrom(&r0) 240 | assert.Equal(t, "n", n, int64(0)) 241 | assert.Equal(t, "err", err, io.ErrUnexpectedEOF) 242 | assert.Equal(t, "s", s, Slice(nil)) 243 | 244 | r1 := readerErrUnexpectedEOF(1) 245 | s = nil 246 | n, err = s.ReadFrom(&r1) 247 | assert.Equal(t, "n", n, int64(1)) 248 | assert.Equal(t, "err", err, io.ErrUnexpectedEOF) 249 | assert.Equal(t, "s", s, Slice([]byte{3})) 250 | } 251 | 252 | func TestSlice_Bug_ReadRune(t *testing.T) { 253 | s := Slice{65, 0xff, 66} 254 | r, sz, err := s.ReadRune() 255 | assert.Equal(t, "r", r, 'A') 256 | assert.Equal(t, "sz", sz, 1) 257 | assert.Equal(t, "err", err, nil) 258 | r, sz, err = s.ReadRune() 259 | assert.Equal(t, "r", r, utf8.RuneError) 260 | assert.Equal(t, "sz", sz, 1) 261 | assert.Equal(t, "err", err, nil) 262 | 263 | r, sz, err = s.ReadRune() 264 | assert.Equal(t, "r", r, 'B') 265 | assert.Equal(t, "sz", sz, 1) 266 | assert.Equal(t, "err", err, nil) 267 | } 268 | 269 | func TestSlice_WriteItoa(t *testing.T) { 270 | var s Slice 271 | s.WriteItoa(1234, 10) 272 | s.WriteItoa(255, 16) 273 | 274 | assert.Equal(t, "s", string(s), "1234ff") 275 | } 276 | 277 | func TestSLice_NewPSlice(t *testing.T) { 278 | s := NewPSlice([]byte{1, 2, 3}) 279 | assert.Equal(t, "*s", []byte(*s), []byte{1, 2, 3}) 280 | } 281 | 282 | func TestSlice_ReadRune_UnfullRune(t *testing.T) { 283 | var s Slice = []byte("\xF0\xA4\xAD") 284 | _, _, err := s.ReadRune() 285 | assert.Equal(t, "err", err, io.ErrUnexpectedEOF) 286 | } 287 | 288 | func TestSlice_WriteRune_InvalidRune(t *testing.T) { 289 | var s Slice 290 | _, err := s.WriteRune(utf8.MaxRune + 1) 291 | assert.Equal(t, "err", err, ErrInvalidRune) 292 | } 293 | 294 | func BenchmarkSliceRead1k(b *testing.B) { 295 | var data [1000]byte 296 | for i := 0; i < b.N; i++ { 297 | b := Slice(data[:]) 298 | for { 299 | if _, err := b.ReadByte(); err != nil { 300 | break 301 | } 302 | } 303 | } 304 | } 305 | 306 | func BenchmarkBytesBufferRead1k(b *testing.B) { 307 | var data [1000]byte 308 | for i := 0; i < b.N; i++ { 309 | b := bytes.NewBuffer(data[:]) 310 | for { 311 | if _, err := b.ReadByte(); err != nil { 312 | break 313 | } 314 | } 315 | } 316 | } 317 | 318 | func BenchmarkBytesReader1k(b *testing.B) { 319 | var data [1000]byte 320 | for i := 0; i < b.N; i++ { 321 | b := bytes.NewReader(data[:]) 322 | for { 323 | if _, err := b.ReadByte(); err != nil { 324 | break 325 | } 326 | } 327 | } 328 | } 329 | 330 | func BenchmarkSliceRead10(b *testing.B) { 331 | var data [10]byte 332 | for i := 0; i < b.N; i++ { 333 | b := Slice(data[:]) 334 | for { 335 | if _, err := b.ReadByte(); err != nil { 336 | break 337 | } 338 | } 339 | } 340 | } 341 | 342 | func BenchmarkBytesBufferRead10(b *testing.B) { 343 | var data [10]byte 344 | for i := 0; i < b.N; i++ { 345 | b := bytes.NewBuffer(data[:]) 346 | for { 347 | if _, err := b.ReadByte(); err != nil { 348 | break 349 | } 350 | } 351 | } 352 | } 353 | 354 | func BenchmarkReader10(b *testing.B) { 355 | var data [10]byte 356 | for i := 0; i < b.N; i++ { 357 | r := bytes.NewReader(data[:]) 358 | for { 359 | if _, err := r.ReadByte(); err != nil { 360 | if err != io.EOF { 361 | b.Fatalf("r.ReadByte failed: %v", err) 362 | } 363 | break 364 | } 365 | } 366 | } 367 | } 368 | 369 | func BenchmarkSliceWrite10(b *testing.B) { 370 | var data [10]byte 371 | for i := 0; i < b.N; i++ { 372 | b := Slice(data[:0]) 373 | for range data { 374 | b.WriteByte(0) 375 | } 376 | } 377 | } 378 | 379 | func BenchmarkBytesBufferWrite10_New(b *testing.B) { 380 | var data [10]byte 381 | for i := 0; i < b.N; i++ { 382 | b := bytes.NewBuffer(data[:0]) 383 | for range data { 384 | b.WriteByte(0) 385 | } 386 | } 387 | } 388 | 389 | func BenchmarkBytesBufferWrite10_Def(b *testing.B) { 390 | var data [10]byte 391 | for i := 0; i < b.N; i++ { 392 | var b bytes.Buffer 393 | for range data { 394 | b.WriteByte(0) 395 | } 396 | } 397 | } 398 | 399 | func BenchmarkSliceWrite1k(b *testing.B) { 400 | var data [1000]byte 401 | for i := 0; i < b.N; i++ { 402 | b := Slice(data[:0]) 403 | for range data { 404 | b.WriteByte(0) 405 | } 406 | } 407 | } 408 | 409 | func BenchmarkBytesBufferWrite1k(b *testing.B) { 410 | var data [1000]byte 411 | for i := 0; i < b.N; i++ { 412 | b := bytes.NewBuffer(data[:0]) 413 | for range data { 414 | b.WriteByte(0) 415 | } 416 | } 417 | } 418 | --------------------------------------------------------------------------------