Ο τύπος rune στη Go είναι alias για τον int32.
Δεδομένου αυτού του υποκείμενου τύπου int32, ο τύπος rune περιέχει μια ακέραια τιμή με πρόσημο 32 bit.
Ωστόσο, σε αντίθεση με τον τύπο int32, η ακέραια τιμή που αποθηκεύεται σε έναν τύπο rune αντιπροσωπεύει έναν μεμονωμένο χαρακτήρα Unicode.
Το Unicode είναι ένα υπερσύνολο του ASCII που αναπαριστά χαρακτήρες αντιστοιχίζοντας έναν μοναδικό αριθμό σε κάθε χαρακτήρα. Αυτός ο μοναδικός αριθμός ονομάζεται σημείο κώδικα Unicode. Το Unicode στοχεύει να αναπαραστήσει όλους τους χαρακτήρες του κόσμου, συμπεριλαμβανομένων διαφόρων αλφαβήτων, αριθμών, συμβόλων και ακόμη και emoji, ως σημεία κώδικα Unicode.
Στη Go, ο τύπος rune αντιπροσωπεύει ένα μεμονωμένο σημείο κώδικα Unicode.
Ο παρακάτω πίνακας περιέχει παραδείγματα χαρακτήρων Unicode μαζί με το σημείο κώδικα Unicode και τη δεκαδική τιμή τους:
| Χαρακτήρας Unicode | Σημείο κώδικα Unicode | Δεκαδική τιμή |
|---|---|---|
| 0 | U+0030 |
48 |
| A | U+0041 |
65 |
| a | U+0061 |
97 |
| ¿ | U+00BF |
191 |
| π | U+03C0 |
960 |
| 🧠 | U+1F9E0 |
129504 |
Το UTF-8 είναι μια κωδικοποίηση χαρακτήρων μεταβλητού πλάτους που χρησιμοποιείται για να κωδικοποιεί κάθε σημείο κώδικα Unicode σε 1, 2, 3 ή 4 byte.
Εφόσον ένα σημείο κώδικα Unicode μπορεί να κωδικοποιηθεί σε το πολύ 4 byte, ο τύπος rune πρέπει να μπορεί να χωρέσει έως 4 byte δεδομένων.
Γι' αυτό ο τύπος rune είναι alias για τον int32, καθώς ο τύπος int32 μπορεί να χωρέσει έως 4 byte δεδομένων.
Τα αρχεία πηγαίου κώδικα της Go κωδικοποιούνται με UTF-8.
Οι μεταβλητές τύπου rune δηλώνονται τοποθετώντας έναν χαρακτήρα μέσα σε απλά εισαγωγικά:
myRune := '¿'
Εφόσον το rune είναι απλώς alias για τον int32, η εκτύπωση του τύπου ενός rune θα δώσει int32:
myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32
Παρομοίως, η εκτύπωση της τιμής ενός rune θα δώσει την ακέραια (δεκαδική) τιμή του:
myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191
Για να εκτυπώσεις τον χαρακτήρα Unicode που αντιπροσωπεύει το rune, χρησιμοποίησε το ρήμα μορφοποίησης %c:
myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
Για να εκτυπώσεις το σημείο κώδικα Unicode που αντιπροσωπεύει το rune, χρησιμοποίησε το ρήμα μορφοποίησης %U:
myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF
Εκτός από το να ορίσεις ένα rune περικλείοντάς το σε απλά εισαγωγικά, μπορείς επίσης να καθορίσεις τον δεκαεξαδικό ή τον δεκαδικό αριθμό:
myRune := rune(0xbf)
myRune = 191
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
Οι συμβολοσειρές στη Go κωδικοποιούνται με UTF-8, που σημαίνει ότι περιέχουν χαρακτήρες Unicode. Οι χαρακτήρες στις συμβολοσειρές αποθηκεύονται και κωδικοποιούνται ως 1, 2, 3 ή 4 byte, ανάλογα με τον χαρακτήρα Unicode που αντιπροσωπεύουν.
Στη Go, τα slices χρησιμοποιούνται για την αναπαράσταση ακολουθιών και μπορείς να τα διατρέξεις με το range.
Όταν διατρέχουμε μια συμβολοσειρά, η Go τη μετατρέπει σε μια σειρά από rune, καθένα από τα οποία είναι 4 byte (θυμήσου, ο τύπος rune είναι alias για τον int32!)
Παρόλο που μια συμβολοσειρά είναι απλώς ένα slice από byte, η λέξη-κλειδί range διατρέχει τα rune της συμβολοσειράς, όχι τα byte της.
Σε αυτό το παράδειγμα, η μεταβλητή index αντιπροσωπεύει τη θέση έναρξης της ακολουθίας byte του τρέχοντος rune και η μεταβλητή char αντιπροσωπεύει το τρέχον rune:
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
Εφόσον τα rune μπορούν να αποθηκευτούν ως 1, 2, 3 ή 4 byte, το μήκος μιας συμβολοσειράς μπορεί να μην ισούται πάντα με τον αριθμό των χαρακτήρων της.
Χρησιμοποίησε την ενσωματωμένη συνάρτηση len για να πάρεις το μήκος μιας συμβολοσειράς σε byte και τη συνάρτηση utf8.RuneCountInString για να πάρεις τον αριθμό των rune σε μια συμβολοσειρά:
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
Ένα slice από rune μπορεί να μετατραπεί με μετατροπή τύπου σε συμβολοσειρά:
myRuneSlice := []rune{'e', 'x', 'e', 'r', 'c', 'i', 's', 'm'}
myString := string(myRuneSlice)
fmt.Println(myString)
// Output: exercism
Παρομοίως, μια συμβολοσειρά μπορεί να μετατραπεί με μετατροπή τύπου σε slice από rune. Θυμήσου, χωρίς ρήματα μορφοποίησης, η εκτύπωση ενός rune δίνει την ακέραια (δεκαδική) τιμή του:
myString := "exercism"
myRuneSlice := []rune(myString)
fmt.Println(myRuneSlice)
// Output: [101 120 101 114 99 105 115 109]