A Go-ban a rune típus az int32 álneve.
Mivel a mögöttes típusa int32, a rune típus egy előjeles 32 bites egész értéket tárol.
Az int32 típustól eltérően azonban a rune típusban tárolt egész érték egyetlen Unicode-karaktert jelöl.
A Unicode az ASCII bővített halmaza, amely minden karakterhez egyedi számot rendel. Ezt az egyedi számot Unicode-kódpontnak nevezzük. A Unicode célja, hogy a világ összes karakterét Unicode-kódpontként ábrázolja, beleértve a különféle ábécéket, számokat, szimbólumokat és még az emojikat is.
A Go-ban a rune típus egyetlen Unicode-kódpontot jelöl.
Az alábbi táblázat példa Unicode-karaktereket mutat a Unicode-kódpontjukkal és decimális értékükkel együtt:
| Unicode-karakter | Unicode-kódpont | Decimális érték |
|---|---|---|
| 0 | U+0030 |
48 |
| A | U+0041 |
65 |
| a | U+0061 |
97 |
| ¿ | U+00BF |
191 |
| π | U+03C0 |
960 |
| 🧠 | U+1F9E0 |
129504 |
A UTF-8 egy változó hosszúságú karakterkódolás, amely minden Unicode-kódpontot 1, 2, 3 vagy 4 bájtként kódol.
Mivel egy Unicode-kódpont legfeljebb 4 bájtként kódolható, a rune típusnak akár 4 bájt adat tárolására is képesnek kell lennie.
Ezért a rune típus az int32 álneve, hiszen az int32 típus képes akár 4 bájt adat tárolására is.
A Go forráskódfájljai UTF-8 kódolást használnak.
A rune típusú változókat úgy hozod létre, hogy egy karaktert aposztrófok közé teszel:
myRune := '¿'
Mivel a rune csupán az int32 álneve, egy rune típusát kiíratva int32-t kapsz:
myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32
Hasonlóképpen, egy rune értékét kiíratva megkapod annak egész (decimális) értékét:
myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191
A rune által képviselt Unicode-karakter kiíratásához a %c formázási igét használd:
myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
A rune által képviselt Unicode-kódpont kiíratásához a %U formázási igét használd:
myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF
A rune-t nemcsak úgy definiálhatod, hogy a karaktert aposztrófok közé teszed, hanem megadhatod a hexadecimális vagy decimális számát is:
myRune := rune(0xbf)
myRune = 191
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
A Go-ban a stringek UTF-8 kódolást használnak, ami azt jelenti, hogy Unicode-karaktereket tartalmaznak. A stringekben lévő karakterek 1, 2, 3 vagy 4 bájtként tárolódnak és kódolódnak attól függően, hogy milyen Unicode-karaktert képviselnek.
A Go-ban a szeleteket sorozatok ábrázolására használjuk, és ezeken a szeleteken a range segítségével iterálhatunk.
Amikor végigmegyünk egy stringen, a Go a stringet rune-ok sorozatává alakítja, amelyek mindegyike 4 bájt (ne feledd, a rune típus az int32 álneve!)
Bár egy string csupán bájtok szelete, a range kulcsszó egy string rune-jain megy végig, nem a bájtjain.
Ebben a példában az index változó az aktuális rune bájtsorozatának kezdőindexét, a char változó pedig az aktuális rune-t képviseli:
myString := "❗hello"
for index, char := range myString {
fmt.Printf("Index: %d\tCharacter: %c\t\tCode Point: %U\n", index, char, char)
}
// Output:
// Index: 0 Character: ❗ Code Point: U+2757
// Index: 3 Character: h Code Point: U+0068
// Index: 4 Character: e Code Point: U+0065
// Index: 5 Character: l Code Point: U+006C
// Index: 6 Character: l Code Point: U+006C
// Index: 7 Character: o Code Point: U+006F
Mivel a rune-ok 1, 2, 3 vagy 4 bájtként tárolhatók, egy string hossza nem mindig egyezik meg a benne lévő karakterek számával.
A beépített len függvénnyel egy string bájtban mért hosszát kapod meg, a utf8.RuneCountInString függvénnyel pedig a stringben lévő rune-ok számát:
import "unicode/utf8"
myString := "❗hello"
stringLength := len(myString)
numberOfRunes := utf8.RuneCountInString(myString)
fmt.Printf("myString - Length: %d - Runes: %d\n", stringLength, numberOfRunes)
// Output: myString - Length: 8 - Runes: 6
Egy rune-szelet típuskonvertálással stringgé alakítható:
myRuneSlice := []rune{'e', 'x', 'e', 'r', 'c', 'i', 's', 'm'}
myString := string(myRuneSlice)
fmt.Println(myString)
// Output: exercism
Hasonlóképpen egy string típuskonvertálással rune-szeletté alakítható. Ne feledd, formázási igék nélkül egy rune kiíratása annak egész (decimális) értékét adja:
myString := "exercism"
myRuneSlice := []rune(myString)
fmt.Println(myRuneSlice)
// Output: [101 120 101 114 99 105 115 109]