El tipo rune en Go es un alias de int32.
Dado este tipo int32 subyacente, el tipo rune contiene un valor entero con signo de 32 bits.
Sin embargo, a diferencia de un tipo int32, el valor entero almacenado en un tipo rune representa un único carácter Unicode.
Unicode es un superconjunto de ASCII que representa caracteres asignando un número único a cada carácter. Ese número único se denomina punto de código Unicode. Unicode pretende representar todos los caracteres del mundo, incluidos distintos alfabetos, números, símbolos e incluso emoji, como puntos de código Unicode.
En Go, el tipo rune representa un único 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.
Dado que un punto de código Unicode puede codificarse como un máximo de 4 bytes, el tipo rune tiene que poder contener hasta 4 bytes de datos.
Por eso el tipo rune es un alias de int32, ya que un tipo int32 es capaz de contener 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 := '¿'
Dado que rune es solo un alias de int32, imprimir el tipo de un rune dará como resultado int32:
myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32
De forma similar, imprimir el valor de un rune dará su valor entero (decimal):
myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191
Para imprimir el carácter Unicode que representa el 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 el 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 los strings se almacenan y codifican como 1, 2, 3 o 4 bytes según el carácter Unicode que representen.
En Go, los slices se usan para representar secuencias y se puede iterar sobre ellos con range.
Cuando iteramos sobre un string, Go convierte el string en una serie de runes, cada uno de los cuales ocupa 4 bytes (recuerda, el tipo rune es un alias de int32).
Aunque un string no es más que un slice de bytes, la palabra clave range itera sobre los runes de un string, no sobre sus bytes.
En este ejemplo, la variable index representa el índice inicial de la secuencia de bytes del rune actual y la variable char representa el 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 los runes pueden almacenarse como 1, 2, 3 o 4 bytes, la longitud de un string no siempre tiene por qué coincidir con el 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 encomendado la tarea de crear una biblioteca de logs para ayudar a gestionar los logs de tu organización. Esta biblioteca permitirá a los usuarios identificar qué aplicación emitió un log determinado, corregir logs corruptos y determinar si una línea de log concreta está dentro de un cierto límite de caracteres.
Los logs provienen de múltiples aplicaciones, y cada una usa su propio formato de log propietario. La aplicación que emite un log debe identificarse antes de poder almacenarlo en un sistema de agregación de logs.
Implementa la función Application, que recibe una línea de log y devuelve la aplicación que emitió dicha línea de log.
Para identificar qué aplicación emitió una línea de log determinada, busca en la línea de log 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 log no contiene ninguno de los caracteres de la tabla anterior, devuelve default a quien la haya llamado.
Si una línea de log contiene más de un carácter de la tabla anterior, devuelve la aplicación correspondiente al primer carácter que se encuentre en la línea de log, de izquierda a derecha.
Application("❗ recommended search product 🔍")
// => recommendation
Debido a un bug poco frecuente pero persistente en la infraestructura de logs, ciertos caracteres de los logs pueden corromperse. Después de pasar un tiempo identificando los caracteres corruptos y su valor original, decides actualizar la biblioteca de logs para ayudar a corregir los logs corruptos.
Implementa la función Replace, que recibe una línea de log, un carácter corrupto y el valor original, y devuelve una línea de log modificada en la que todas las apariciones del carácter corrupto se han reemplazado por el valor original.
log := "please replace '👎' with '👍'"
Replace(log, '👎', '👍')
// => please replace '👍' with '👍'"
Los sistemas encargados de mostrar los logs tienen un límite en el número de caracteres que se pueden mostrar por línea de log. Por ello, los usuarios piden que esta biblioteca incluya una función auxiliar para determinar si una línea de log está dentro de un límite de caracteres específico o no.
Implementa la función WithinLimit, que recibe una línea de log y un límite de caracteres, y devuelve si la línea de log está dentro del 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.