Ce face strings.Builder
Textele din Go nu pot fi modificate, deci s += "x" creează la fiecare pas un text nou și copiază tot ce era înainte. Într-o buclă cu mii de pași, asta devine lent. strings.Builder ține un buffer care crește și adaugă bucățile la final fără copieri inutile.
Nu trebuie inițializat: var sb strings.Builder este gata de folosit. Adaugi cu WriteString(text), WriteByte('\n') (un octet ASCII), WriteRune('ș') (un caracter Unicode) sau Write([]byte). La final, sb.String() returnează textul construit, fără să-l copieze.
*strings.Builder implementează io.Writer, deci poți scrie în el și cu fmt.Fprintf(&sb, ...). Metodele de scriere returnează o eroare doar pentru a respecta interfețele; eroarea este întotdeauna nil.
Parametri
| Parametru | Descriere |
|---|---|
s / c / r / p |
Bucata adăugată: text (string), octet (byte), caracter (rune) sau octeți ([]byte). |
Ce returnează
Metodele Write* returnează numărul de octeți adăugați și o eroare mereu nil (WriteByte doar eroarea). String() returnează textul construit.
Exemple
Exemplul 1: Construirea unui text pas cu pas
package main
import (
"fmt"
"strings"
)
func main() {
var sb strings.Builder
sb.WriteString("Orașe: ")
for i, oras := range []string{"Iași", "Cluj", "Brașov"} {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(oras)
}
sb.WriteByte('.')
sb.WriteByte('\n')
sb.WriteRune('✓')
sb.WriteRune('ș')
sb.Write([]byte(" gata"))
fmt.Println(sb.String())
}
Rezultat
Orașe: Iași, Cluj, Brașov.
✓ș gata
Exemplul 2: Fprintf direct în Builder
Dăm &sb (adresa), pentru că metodele lui Builder au receptor pointer.
package main
import (
"fmt"
"strings"
)
func main() {
var sb strings.Builder
fmt.Fprintf(&sb, "%-6s %4s\n", "Elev", "Nota")
note := map[string]int{"Ana": 10, "Ion": 8}
for _, nume := range []string{"Ana", "Ion"} {
fmt.Fprintf(&sb, "%-6s %4d\n", nume, note[nume])
}
fmt.Print(sb.String())
fmt.Println("lungime:", sb.Len(), "octeți")
}
Rezultat
Elev Nota
Ana 10
Ion 8
lungime: 36 octeți
Exemplul 3: Cât de lent este += față de Builder
Ambele variante dau același text. Diferența este numărul de copieri: cu += fiecare pas copiază tot textul de până atunci. Rezultatul afișat este doar lungimea, ca să fie același la fiecare rulare.
package main
import (
"fmt"
"strings"
)
func main() {
s := ""
for i := 0; i < 1000; i++ {
s += "ab" // creează 1000 de texte noi
}
var sb strings.Builder
for i := 0; i < 1000; i++ {
sb.WriteString("ab") // adaugă în același buffer
}
fmt.Println(len(s), sb.Len(), s == sb.String())
}
Rezultat
2000 2000 true
Greșeli frecvente
- Copiezi un Builder deja folosit (
b2 := sb) și scrii în copie. Programul se oprește cupanic: strings: illegal use of non-zero Builder copied by value. Transmite-l mereu prin pointer (*strings.Builder). - Scrii
fmt.Fprintf(sb, …)fără&: nu compilează, pentru că doar*strings.Builderesteio.Writer. - Folosești
WriteByte('ș'). ș nu încape într-un octet (nu compilează); pentru diacritice foloseșteWriteRunesauWriteString.
Comenzi înrudite
strings.Builder.Grow: Grow rezervă loc dinainte, Len dă octeții scriși, Cap capacitatea bufferului, iar Reset golește Builder-ul.strings.Join: Lipește textele dintr-un slice într-un singur text, cu un separator între ele.bytes.Buffer: Un buffer de octeți care crește singur: scrii în el cu Write/WriteString/WriteByte/WriteRune și citești cu String() sau Bytes().fmt.Fprintln: Scrie valorile într-un io.Writer (fișier, buffer, răspuns HTTP) cu regulile lui Println, respectiv Print.