bytes.Buffer în Go

Un buffer de octeți care crește singur: scrii în el cu Write/WriteString/WriteByte/WriteRune și citești cu String() sau Bytes().

Sintaxă
var buf bytes.Buffer
func (b *Buffer) Write(p []byte) (n int, err error)
func (b *Buffer) WriteString(s string) (n int, err error)
func (b *Buffer) WriteByte(c byte) error
func (b *Buffer) WriteRune(r rune) (n int, err error)
func (b *Buffer) String() string
func (b *Buffer) Bytes() []byte

Ce face bytes.Buffer

bytes.Buffer este o zonă de memorie în care poți și scrie, și citi. Scrierile se adaugă la sfârșit, iar citirile iau de la început partea încă necitită. Valoarea zero este gata de folosit: var buf bytes.Buffer. Mai poți crea unul cu bytes.NewBufferString("…") sau bytes.NewBuffer([]byte).

Scrii cu Write([]byte), WriteString(text), WriteByte(octet) sau WriteRune(caracter). String() returnează partea necitită ca text (copie), iar Bytes() ca slice care împarte memoria cu bufferul. *bytes.Buffer este atât io.Writer, cât și io.Reader.

Față de strings.Builder, care doar construiește un text, Buffer permite și citirea, revenirea (UnreadByte) și refolosirea memoriei cu Reset. Dacă doar construiești un text, alege Builder.

Parametri

Parametru Descriere
p / s / c / r Datele scrise: octeți, text, un octet sau un caracter.

Ce returnează

Metodele Write* returnează numărul de octeți scriși și o eroare (mereu nil; dacă memoria nu ajunge, programul se oprește cu panic). String și Bytes returnează partea necitită.

Exemple

Exemplul 1: Scriere în buffer

Primii 5 octeți sunt „Bună”: litera ă ocupă doi octeți (196 131).

package main

import (
	"bytes"
	"fmt"
)

func main() {
	var buf bytes.Buffer
	buf.WriteString("Bună, ")
	buf.Write([]byte("Ana"))
	buf.WriteByte('!')
	buf.WriteRune(' ')
	buf.WriteRune('☺')
	fmt.Println(buf.String())
	fmt.Println(buf.Len(), "octeți:", buf.Bytes()[:5])

	b2 := bytes.NewBufferString("Iași")
	fmt.Fprintf(b2, " - %d km", 400)
	fmt.Println(b2.String())
}

Rezultat

Bună, Ana! ☺
15 octeți: [66 117 110 196 131]
Iași - 400 km

Exemplul 2: Bytes() împarte memoria, String() copiază

package main

import (
	"bytes"
	"fmt"
)

func main() {
	buf := bytes.NewBufferString("cluj")
	s := buf.String()
	b := buf.Bytes()
	b[0] = 'C'
	fmt.Println(buf.String(), s)
}

Rezultat

Cluj cluj

Exemplul 3: Buffer ca destinație pentru o funcție care scrie

Într-un test, scrii într-un buffer în loc de ecran și verifici apoi ce a scris funcția.

package main

import (
	"bytes"
	"fmt"
	"io"
)

func salut(w io.Writer, nume string) {
	fmt.Fprintf(w, "Salut, %s!\n", nume)
}

func main() {
	var buf bytes.Buffer
	salut(&buf, "Maria")
	fmt.Println("corect?", buf.String() == "Salut, Maria!\n")
}

Rezultat

corect? true

Greșeli frecvente

  • Copiezi un Buffer prin valoare (b2 := buf) sau îl dai unei funcții fără pointer. Cele două copii împart memoria internă și se strică reciproc; folosește mereu *bytes.Buffer.
  • Păstrezi rezultatul lui Bytes() și apoi scrii din nou în buffer. Slice-ul poate arăta spre memorie veche sau poate fi suprascris; copiază-l dacă îl păstrezi.
  • Te aștepți ca String() să dea tot ce ai scris vreodată. Dă doar partea necitită; ce ai citit deja a dispărut din buffer.

Comenzi înrudite

  • bytes.Buffer.Read: Citește din buffer octeți (Read, ReadByte) sau caractere (ReadRune); UnreadByte și UnreadRune pun înapoi ultima citire.
  • bytes.Buffer.ReadString: Citește din buffer până la un caracter-delimitator (inclusiv), ca text (ReadString) sau octeți (ReadBytes).
  • bytes.Buffer.Len: Len dă octeții necitiți, Cap capacitatea, Grow rezervă loc, Available spațiul liber, iar AvailableBuffer un slice pentru scriere directă.
  • bytes.Buffer.Reset: Reset golește bufferul și păstrează memoria pentru refolosire; Truncate păstrează doar primii n octeți necitiți.
  • strings.Builder: Construiește eficient un text din multe bucăți: adaugi cu WriteString, WriteByte, WriteRune sau Write și obții rezultatul cu String().
  • fmt.Fprintln: Scrie valorile într-un io.Writer (fișier, buffer, răspuns HTTP) cu regulile lui Println, respectiv Print.