El tipo rune en Go es un alias de int32.
Dado este tipo int32 subyacente, el tipo rune almacena un valor entero con signo de 32 bits.
Sin embargo, a diferencia de un tipo int32, el valor entero que se almacena en un tipo rune representa un solo carácter Unicode.
Unicode es un superconjunto de ASCII que representa los caracteres asignándole un número único a cada carácter. A este número único se le llama punto de código Unicode. Unicode busca representar todos los caracteres del mundo, incluidos los distintos alfabetos, números, símbolos e incluso emojis, como puntos de código Unicode.
En Go, el tipo rune representa un solo punto de código Unicode.
La siguiente tabla contiene caracteres Unicode de ejemplo junto con su punto de código Unicode y sus valores decimales:
| Carácter Unicode | Punto de código Unicode | Valor decimal |
|---|---|---|
| 0 | U+0030 |
48 |
| A | U+0041 |
65 |
| a | U+0061 |
97 |
| ¿ | U+00BF |
191 |
| π | U+03C0 |
960 |
| 🧠 | U+1F9E0 |
129504 |
UTF-8 es una codificación de caracteres de ancho variable que se usa para codificar cada punto de código Unicode como 1, 2, 3 o 4 bytes.
Como un punto de código Unicode se puede codificar en un máximo de 4 bytes, el tipo rune necesita poder almacenar hasta 4 bytes de datos.
Por eso el tipo rune es un alias de int32: un tipo int32 es capaz de almacenar hasta 4 bytes de datos.
Los archivos de código fuente de Go se codifican con UTF-8.
Las variables de tipo rune se declaran colocando un carácter entre comillas simples:
myRune := '¿'
Como rune es solo un alias de int32, imprimir el tipo de una rune da como resultado int32:
myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32
De manera similar, imprimir el valor de una rune da como resultado su valor entero (decimal):
myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191
Para imprimir el carácter Unicode que representa la rune, usa el verbo de formato %c:
myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿
Para imprimir el punto de código Unicode que representa la rune, usa el verbo de formato %U:
myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF
Los strings en Go se codifican con UTF-8, lo que significa que contienen caracteres Unicode. Los caracteres de un string se almacenan y codifican como 1, 2, 3 o 4 bytes, según el carácter Unicode que representen.
En Go, se usan slices para representar secuencias y se puede iterar sobre estos slices usando range.
Cuando iteramos sobre un string, Go convierte el string en una serie de runes, y cada una ocupa 4 bytes (recuerda, ¡el tipo rune es un alias de un int32!).
Aunque un string es solo un slice de bytes, la palabra clave range itera sobre las runes de un string, no sobre sus bytes.
En este ejemplo, la variable index representa el índice inicial de la secuencia de bytes de la rune actual, y la variable char representa la rune actual:
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
Como las runes se pueden almacenar en 1, 2, 3 o 4 bytes, la longitud de un string no siempre es igual al número de caracteres del string.
Usa la función integrada len para obtener la longitud de un string en bytes y la función utf8.RuneCountInString para obtener el número de runes de un string:
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
Se te ha encargado crear una biblioteca de registros que ayude a gestionar los registros de tu organización. Esta biblioteca permitirá a los usuarios identificar qué aplicación emitió un registro determinado, corregir registros corruptos y determinar si una línea de registro está dentro de cierto límite de caracteres.
Los registros provienen de múltiples aplicaciones, y cada una usa su propio formato de registro propietario. La aplicación que emite un registro debe identificarse antes de poder almacenarlo en un sistema de agregación de registros.
Implementa la función Application que recibe una línea de registro y devuelve la aplicación que emitió esa línea de registro.
Para identificar qué aplicación emitió una línea de registro dada, busca en la línea de registro un carácter específico, según lo indicado en la siguiente tabla:
| Aplicación | Carácter | Punto de código Unicode |
|---|---|---|
recommendation |
❗ | U+2757 |
search |
🔍 | U+1F50D |
weather |
☀ | U+2600 |
Si una línea de registro no contiene ninguno de los caracteres de la tabla anterior, devuelve default a quien hizo la llamada.
Si una línea de registro contiene más de un carácter de la tabla anterior, devuelve la aplicación correspondiente al primer carácter que aparezca en la línea de registro, de izquierda a derecha.
Application("❗ recommended search product 🔍")
// => recommendation
Debido a un error poco frecuente pero persistente en la infraestructura de registro, ciertos caracteres de los registros pueden corromperse. Después de dedicar tiempo a identificar los caracteres corruptos y su valor original, decides actualizar la biblioteca de registros para ayudar a corregir los registros corruptos.
Implementa la función Replace que recibe una línea de registro, un carácter corrupto y el valor original, y devuelve una línea de registro modificada en la que todas las apariciones del carácter corrupto se reemplazaron por el valor original.
log := "please replace '👎' with '👍'"
Replace(log, '👎', '👍')
// => please replace '👍' with '👍'"
Los sistemas encargados de mostrar los registros tienen un límite en la cantidad de caracteres que se pueden mostrar por línea de registro. Por eso, los usuarios piden que esta biblioteca incluya una función auxiliar que determine si una línea de registro está dentro de un límite de caracteres específico.
Implementa la función WithinLimit que recibe una línea de registro y un límite de caracteres, y devuelve si la línea de registro está dentro de ese límite de caracteres o no.
WithinLimit("hello❗", 6)
// => true
Regístrate en Exercism para aprender y dominar Go con 34 conceptos165 ejercicios y mentoría humana real, todo gratis.