Il tipo rune in Go è un alias di int32.
Dato questo tipo sottostante int32, il tipo rune contiene un valore intero con segno a 32 bit.
Tuttavia, a differenza di un tipo int32, il valore intero memorizzato in un tipo rune rappresenta un singolo carattere Unicode.
Unicode è un superset dell'ASCII che rappresenta i caratteri assegnando a ogni carattere un numero univoco. Questo numero univoco si chiama punto di codice Unicode. L'obiettivo di Unicode è rappresentare tutti i caratteri del mondo, inclusi i vari alfabeti, i numeri, i simboli e persino le emoji, come punti di codice Unicode.
In Go, il tipo rune rappresenta un singolo punto di codice Unicode.
La tabella seguente contiene alcuni caratteri Unicode di esempio con il loro punto di codice Unicode e il loro valore decimale:
| Carattere Unicode | Punto di codice Unicode | Valore decimale |
|---|---|---|
| 0 | U+0030 |
48 |
| A | U+0041 |
65 |
| a | U+0061 |
97 |
| ¿ | U+00BF |
191 |
| π | U+03C0 |
960 |
| 🧠 | U+1F9E0 |
129504 |
UTF-8 è una codifica di caratteri a lunghezza variabile che viene usata per codificare ogni punto di codice Unicode in 1, 2, 3 o 4 byte.
Dato che un punto di codice Unicode può essere codificato in un massimo di 4 byte, il tipo rune deve essere in grado di contenere fino a 4 byte di dati.
Ecco perché il tipo rune è un alias di int32: un tipo int32 è capace di contenere fino a 4 byte di dati.
I file di codice sorgente Go sono codificati usando UTF-8.
Le variabili di tipo rune si dichiarano inserendo un carattere tra apici singoli:
myRune := '¿'
Dato che rune è solo un alias di int32, stampare il tipo di un rune darà int32:
myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32
Allo stesso modo, stampare il valore di un rune ne darà il valore intero (decimale):
myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191
Per stampare il carattere Unicode rappresentato dal rune, usa il verbo di formattazione %c:
myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
Per stampare il punto di codice Unicode rappresentato dal rune, usa il verbo di formattazione %U:
myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF
Le stringhe in Go sono codificate usando UTF-8, il che significa che contengono caratteri Unicode. I caratteri all'interno delle stringhe sono memorizzati e codificati in 1, 2, 3 o 4 byte, a seconda del carattere Unicode che rappresentano.
In Go, gli slice sono usati per rappresentare le sequenze e su questi slice si può iterare usando range.
Quando iteriamo su una stringa, Go la converte in una serie di rune, ognuno dei quali è di 4 byte (ricorda, il tipo rune è un alias di un int32!)
Anche se una stringa è solo uno slice di byte, la parola chiave range itera sui rune di una stringa, non sui suoi byte.
In questo esempio, la variabile index rappresenta l'indice iniziale della sequenza di byte del rune corrente e la variabile char rappresenta il rune corrente:
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
Dato che i rune possono essere memorizzati in 1, 2, 3 o 4 byte, la lunghezza di una stringa non sempre coincide con il numero di caratteri della stringa.
Usa la funzione incorporata len per ottenere la lunghezza di una stringa in byte e la funzione utf8.RuneCountInString per ottenere il numero di rune in una stringa:
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
Hai il compito di creare una libreria di log che ti aiuti a gestire i log della tua organizzazione. Questa libreria permetterà agli utenti di identificare quale applicazione ha emesso un determinato log, di correggere i log danneggiati e di determinare se una determinata riga di log rientra in un certo limite di caratteri.
I log provengono da più applicazioni, ognuna delle quali usa il proprio formato di log proprietario. L'applicazione che emette un log deve essere identificata prima che il log possa essere memorizzato in un sistema di aggregazione dei log.
Implementa la funzione Application che prende una riga di log e restituisce l'applicazione che ha emesso quella riga.
Per identificare quale applicazione ha emesso una determinata riga di log, cerca nella riga un carattere specifico, come indicato nella tabella seguente:
| Applicazione | Carattere | Punto di codice Unicode |
|---|---|---|
recommendation |
❗ | U+2757 |
search |
🔍 | U+1F50D |
weather |
☀ | U+2600 |
Se una riga di log non contiene nessuno dei caratteri della tabella qui sopra, restituisci default al chiamante.
Se una riga di log contiene più di un carattere della tabella qui sopra, restituisci l'applicazione corrispondente al primo carattere trovato nella riga, procedendo da sinistra a destra.
Application("❗ recommended search product 🔍")
// => recommendation
A causa di un bug raro ma persistente nell'infrastruttura di logging, alcuni caratteri nei log possono danneggiarsi. Dopo aver dedicato del tempo a identificare i caratteri danneggiati e il loro valore originale, decidi di aggiornare la libreria di log per aiutare a correggere i log danneggiati.
Implementa la funzione Replace che prende una riga di log, un carattere danneggiato e il valore originale e restituisce una riga di log modificata in cui tutte le occorrenze del carattere danneggiato sono state sostituite con il valore originale.
log := "please replace '👎' with '👍'"
Replace(log, '👎', '👍')
// => please replace '👍' with '👍'"
I sistemi responsabili della visualizzazione dei log hanno un limite al numero di caratteri che possono essere visualizzati per riga di log. Per questo motivo, gli utenti chiedono che questa libreria includa una funzione ausiliaria per determinare se una riga di log rientra o meno in un limite di caratteri specifico.
Implementa la funzione WithinLimit che prende una riga di log e un limite di caratteri e restituisce se la riga di log rientra o meno nel limite di caratteri.
WithinLimit("hello❗", 6)
// => true
Iscriviti a Exercism per imparare e padroneggiare Go con 34 concetti165 esercizi e il mentoring di persone reali, tutto gratis.