ProgramaciónDesarrollador Go

¿Cuáles son las características del trabajo con cadenas (string) en Go que deben conocerse para evitar errores inesperados al programar?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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:

  • La cadena es inmutable, no se puede cambiar por índice.
  • La cadena está codificada en UTF-8, no siempre 1 símbolo = 1 byte.
  • La conversión de string <-> []byte crea una copia.

Preguntas capciosas.

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.

Errores comunes y anti-patrones

  • Intentar modificar la cadena directamente a través de la indexación.
  • Comparar la longitud de la cadena a través de len — errores con Unicode.
  • Utilizar []byte para la serialización, pero olvidar la codificación.
  • Olvidar que string y []byte son objetos diferentes en memoria.

Ejemplo de la vida real

Caso negativo

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.

Caso positivo

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.