Ce face unicode/utf8.RuneCountInString
În Go, un string este o secvență de octeți în codarea UTF-8. len(s) returnează numărul de octeți, nu de caractere. Literele englezești ocupă câte un octet, dar ă, â, î, ș, ț ocupă câte 2, € ocupă 3, iar emoji 4. Așa că len("Iași") este 5, deși cuvântul are 4 litere.
utf8.RuneCountInString(s) numără caracterele (în Go se numesc rune, adică puncte de cod Unicode). utf8.RuneCount(p) face același lucru pentru un []byte. Octeții invalizi sunt numărați fiecare ca un caracter.
Același lucru contează la indexare: s[0] este un octet (byte), nu o literă. Pentru caractere parcurge cu for i, r := range s (unde i este poziția în octeți, iar r caracterul) sau transformă în []rune(s), unde fiecare element este un caracter.
Parametri
| Parametru | Descriere |
|---|---|
s / p |
Textul (string) sau octeții ([]byte). |
Ce returnează
Numărul de caractere (int).
Exemple
Exemplul 1: len() numără octeți, RuneCountInString numără caractere
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
for _, s := range []string{"Cluj", "Iași", "Târgu Mureș", "10€", "țânțăroi"} {
fmt.Printf("%-12s len = %2d caractere = %2d\n", s, len(s), utf8.RuneCountInString(s))
}
fmt.Println(utf8.RuneCount([]byte("Brașov")))
fmt.Println(len([]rune("Brașov")))
}
Rezultat
Cluj len = 4 caractere = 4
Iași len = 5 caractere = 4
Târgu Mureș len = 13 caractere = 11
10€ len = 5 caractere = 3
țânțăroi len = 12 caractere = 8
6
6
Exemplul 2: Octeți față de caractere la parcurgere
s[i] dă octeți: ș apare ca doi octeți (200 153). for range dă caracterele și poziția lor în octeți: după ș, poziția sare de la 2 la 4.
package main
import "fmt"
func main() {
s := "Iași"
for i := 0; i < len(s); i++ {
fmt.Print(s[i], " ")
}
fmt.Println()
for i, r := range s {
fmt.Printf("poziția %d: %c\n", i, r)
}
litere := []rune(s)
fmt.Println("a treia literă:", string(litere[2]), "| s[2] este octetul", s[2])
}
Rezultat
73 97 200 153 105
poziția 0: I
poziția 1: a
poziția 2: ș
poziția 4: i
a treia literă: ș | s[2] este octetul 200
Exemplul 3: Scurtarea unui text la un număr de caractere
Tăierea cu s[:n] lucrează pe octeți și poate rupe o literă în două. Varianta corectă numără caracterele.
package main
import (
"fmt"
"unicode/utf8"
)
func scurteaza(s string, max int) string {
if utf8.RuneCountInString(s) <= max {
return s
}
return string([]rune(s)[:max]) + "…"
}
func main() {
titlu := "Știri din Iași și Brașov"
fmt.Printf("%q\n", titlu[:3])
fmt.Println(scurteaza(titlu, 9))
fmt.Println(scurteaza("Cluj", 9))
}
Rezultat
"Șt"
Știri din…
Cluj
Greșeli frecvente
- Folosești
len(s)ca număr de litere (de exemplu „parola trebuie să aibă minim 8 caractere”). „țânțăroi” are 8 litere, dar 12 octeți; foloseșteutf8.RuneCountInString. - Tai textul cu
s[:n]și obții o literă ruptă (afișată ca �). Taie după[]rune(s)sau verifică granițele cuutf8.RuneStart. - Crezi că un
runeeste mereu o literă „văzută”. Unele litere pot fi scrise din două puncte de cod (literă + semn diacritic combinat); pentru texte venite din surse diferite, normalizează-le cugolang.org/x/text/unicode/norm.
Comenzi înrudite
unicode/utf8.DecodeRuneInString: Citește primul (sau ultimul) caracter UTF-8 dintr-un text sau []byte și spune câți octeți ocupă.unicode/utf8.EncodeRune: EncodeRune scrie un caracter în UTF-8 într-un []byte, AppendRune îl adaugă la final, iar RuneLen spune câți octeți ocupă.unicode/utf8.ValidString: Verifică dacă un text sau un []byte este UTF-8 valid și dacă o valoare rune este un caracter Unicode valid.strings.Index: Returnează poziția (în octeți) a primei sau ultimei apariții a unui text, octet sau caracter; -1 dacă nu există.strings.Count: Numără de câte ori apare un text în alt text, fără suprapuneri.