Historia de la pregunta: En Go, las cadenas (string) son un tipo básico y frecuentemente utilizado, activamente empleado para el intercambio de datos, registro, análisis, etc. La diferencia en Go es que las cadenas son inmutables, consisten en una secuencia inmutable de bytes y pueden contener datos en UTF-8.
Problema: Se confunde el trabajo con cadenas y segmentos de bytes ([]byte), cometiendo errores al modificar la cadena, al segmentar por runas y al intentar trabajar con caracteres multibyte (por ejemplo, cirílico, emoji).
Solución:
Una cadena es inmutable, no se pueden cambiar sus elementos directamente — intentar modificar s[0] es incorrecto. La cadena está codificada en UTF-8, es decir, un símbolo (runa) puede ocupar más de un byte. Trabajar con []byte es más barato, pero requiere control manual. La conversión de string <-> []byte siempre crea una copia.
Ejemplo de código:
s := "привет" fmt.Println(len(s)) // 12 bytes (cirílico: 2 bytes cada uno) fmt.Println(len([]rune(s))) // 6 runas, tantas letras fmt.Println(string([]byte{228, 189, 160, 229, 165, 189})) // caracteres chinos
Características clave:
1. ¿Se puede cambiar un símbolo individual de una cadena a través del índice (por ejemplo, s[1] = 'a')?
Respuesta: No. Las cadenas son inmutables, el compilador generará un error. Se debe crear un nuevo segmento []rune o []byte, modificarlo y luego convertirlo de nuevo a cadena.
2. ¿Por qué len(str) no siempre coincide con la cantidad de símbolos en la cadena?
Respuesta: len(str) es la cantidad de bytes, no de runas (símbolos). Para caracteres cirílicos o emoji, una cadena larga puede dar un valor inesperado. Para el número de símbolos, use []rune:
s := "мир 😀" fmt.Println(len(s)) // 7 fmt.Println(len([]rune(s))) // 5
3. ¿Se pasa la cadena por referencia o por valor a la función?
Respuesta: Por valor, pero físicamente se almacena un puntero a la memoria y la longitud. Después de la transmisión, dos variables "apuntan" al mismo texto, no se crea una copia automáticamente. La copia real de la memoria aparece al convertir a []byte o de []byte a string.
Un desarrollador tiene una cadena con símbolos rusos, toma los primeros 4 bytes y espera obtener la primera letra, pero solo obtiene la mitad del símbolo — se generan caracteres "corruptos".
Ventajas: Se hizo rápido y corto. Desventajas: Trabajo incorrecto con datos Unicode, cadenas "corruptas", pánico al intentar analizar tales cadenas en otros lugares.
Las cadenas se convierten en []rune para trabajar con los símbolos, después de las acciones necesarias, se reúne de nuevo la cadena a través de string(). El trabajo con []byte se realiza solo para la serialización de bajo nivel, teniendo en cuenta la codificación.
Ventajas: Manejo correcto de Unicode, fiabilidad de las funciones. Desventajas: Un poco más lento, requiere más memoria, pero es seguro para cualquier cadena.