Menu

Int a string, string a int y conversión de tipos en Golang

Cómo convertir entre tipos en Go: int a string y string a int con strconv, flotantes a enteros, conversiones numéricas con T(v), bytes y runes, la trampa de string(65) y el manejo de errores de conversión.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Go nunca convierte tipos de forma implícita. Conviertes entre tipos compatibles con T(v), y entre números y texto con el paquete strconv. Las dos conversiones más buscadas:

strconv.Itoa ("integer to ASCII") formatea un int como texto decimal. strconv.Atoi ("ASCII to integer") analiza texto y lo convierte en un int, y devuelve un error cuando el texto no es un número válido. Comprueba siempre ese error.

La conversión T(v)

La sintaxis de conversión de Go parece una llamada a una función con el nombre del tipo de destino. Funciona en tres situaciones:

  1. entre tipos numéricos (int, int64, float64, uint8, ...),
  2. entre string y []byte o []rune,
  3. entre tipos que comparten tipo subyacente (Celsius y float64).

Lee los resultados con atención:

  • int(3.9) es 3 e int(-3.9) es -3. La conversión trunca hacia cero; no redondea. Usa antes math.Round, math.Floor o math.Ceil para elegir el comportamiento. math.Round redondea la mitad alejándose de cero, así que -3.5 se convierte en -4.
  • uint8(300) es 44, porque solo sobreviven los 8 bits bajos (300 menos 256), e int8(200) es -56 por la misma razón. Ni error ni panic.
  • Celsius y float64 comparten tipo subyacente, así que se convierten libremente, pero solo de forma explícita.

Los valores están en variables a propósito. Con constantes, las mismas conversiones no compilan.

Las constantes se comprueban, las variables no

Convertir una constante que no cabe es un error de compilación. Convertir una variable con el mismo valor da la vuelta en silencio:

fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8

Convertir una constante no entera a un tipo entero también se rechaza, mientras que el mismo valor en una variable se trunca:

./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int

Si el valor flotante está fuera del rango del tipo entero de destino (por ejemplo int64(1e20)), el resultado depende de la implementación: amd64 y arm64, por ejemplo, dan respuestas distintas. Comprueba el rango antes de convertir valores no fiables.

Convertir números en strings

DesdeFunciónEjemploResultado
intstrconv.Itoa(n)strconv.Itoa(-7)"-7"
int64strconv.FormatInt(n, base)strconv.FormatInt(255, 16)"ff"
uint64strconv.FormatUint(n, base)strconv.FormatUint(5, 2)"101"
float64strconv.FormatFloat(f, fmt, prec, 64)strconv.FormatFloat(3.14159, 'f', 2, 64)"3.14"
boolstrconv.FormatBool(b)strconv.FormatBool(true)"true"
cualquier cosafmt.Sprint(v)fmt.Sprint(3.5)"3.5"
cualquier cosa, con formatofmt.Sprintf(format, v)fmt.Sprintf("%05d", 42)"00042"

FormatFloat recibe un byte de formato ('f' para notación fija, 'e' para exponente, 'g' para la más corta de las dos), una precisión (-1 significa "los menos dígitos que permiten recuperar el valor exacto") y el tamaño en bits del float original (64 o 32).

strconv es más rápido que fmt.Sprint, que mete el valor en una interfaz y pasa por la ruta de formato general de fmt. En un bucle caliente esa diferencia se nota; para conversiones ocasionales, elige lo que se lea mejor.

Convertir strings en números

AFunciónDevuelve
intstrconv.Atoi(s)int, error
cualquier entero con signostrconv.ParseInt(s, base, bitSize)int64, error
cualquier entero sin signostrconv.ParseUint(s, base, bitSize)uint64, error
floatstrconv.ParseFloat(s, bitSize)float64, error
boolstrconv.ParseBool(s)bool, error

ParseInt siempre devuelve un int64. El argumento bitSize (0, 8, 16, 32, 64) fija el rango que acepta, así que el resultado cabe con seguridad cuando lo conviertes a un tipo más pequeño. base 0 significa "deducirla del prefijo", así que 0x1f, 0o17, 0b101 y 1_000 se analizan todos.

Cosas que muestra la salida:

  • " 42" falla. Atoi acepta un signo opcional y dígitos, nada más. La entrada de bufio suele terminar en \n, así que recórtala.
  • "4.2" no es válido para Atoi. Usa ParseFloat para decimales.
  • Ante un error de fuera de rango, ParseInt devuelve el mayor valor que cabe (127 para int8) junto con el error. No uses el valor cuando el error no sea nil.
  • Los errores son valores *strconv.NumError que envuelven strconv.ErrSyntax o strconv.ErrRange, así que errors.Is puede distinguirlos.

ParseBool acepta 1, t, T, TRUE, true, True y las formas equivalentes para false. "yes" y "on" son errores.

La trampa de string(65)

Convertir un entero a string no produce dígitos. Produce el carácter con ese code point Unicode:

n := 65
s := string(n) // "A", not "65"

El compilador lo acepta, pero go vet lo informa:

./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits

Si de verdad quieres el carácter, dilo con un rune: string(rune(n)). Si quieres el número como texto, usa strconv.Itoa(n). Convertir un rune o un byte a string es correcto y habitual:

Strings, bytes y runes

string, []byte y []rune se convierten entre sí con T(v). Cada conversión copia los datos, porque los strings son inmutables y los slices no:

Convierte a []rune cuando necesites indexar o modificar por carácter; convierte a []byte para I/O, hashing y ediciones a nivel de byte. La página de runes y bytes explica UTF-8 en detalle.

Conversión frente a aserción de tipo

Una conversión cambia un valor de un tipo concreto a otro. Sacar el valor concreto de una interfaz (any, error, io.Reader) es una operación distinta, la aserción de tipo:

var v any = 42

n := v.(int)       // type assertion: v holds an int, give it to me
f := float64(n)    // conversion: int to float64
// f := float64(v) // compile error: cannot convert v (variable of interface type any)
//                  // to type float64: need type assertion

Primero la aserción, luego la conversión. La forma comma-ok n, ok := v.(int) evita un panic cuando el tipo es incorrecto.

Referencia rápida

TareaCódigo
int a stringstrconv.Itoa(n)
int64 a stringstrconv.FormatInt(n, 10)
string a intn, err := strconv.Atoi(s)
string a int64n, err := strconv.ParseInt(s, 10, 64)
string a float64f, err := strconv.ParseFloat(s, 64)
float64 a stringstrconv.FormatFloat(f, 'f', -1, 64)
float64 a intint(f) (trunca) o int(math.Round(f))
int a float64float64(n)
string a []byte[]byte(s)
[]byte a stringstring(b)
rune a stringstring(r)
bool a stringstrconv.FormatBool(b)
cualquier valor a stringfmt.Sprint(v)

Preguntas frecuentes

¿Cómo convierto un int en un string en Go?

Usa strconv.Itoa(n): strconv.Itoa(42) devuelve "42". Para un int64 usa strconv.FormatInt(n, 10). fmt.Sprint(n) también funciona con cualquier tipo, pero es más lento. No escribas string(n): eso trata n como un code point Unicode, así que string(65) es "A".

¿Cómo convierto un string en un int en Go?

Usa strconv.Atoi, que devuelve el número y un error:

n, err := strconv.Atoi("42")
if err != nil {
	// not a valid integer
}

Para un tamaño o una base concretos, usa strconv.ParseInt(s, 10, 64), que devuelve un int64. Atoi no recorta espacios, así que " 42" da error; llama antes a strings.TrimSpace.

¿Cómo hago un cast en Go?

Go lo llama conversión, y la sintaxis es T(v): float64(n), int(f), []byte(s). Funciona entre tipos numéricos, entre strings y slices de bytes o de runes, y entre tipos con el mismo tipo subyacente. No analiza texto: convertir "42" en 42 necesita strconv. Sacar un tipo concreto de una interfaz es una aserción de tipo, v.(T), no una conversión.

¿Cómo convierto un float en un int en Go?

int(f) trunca hacia cero: int(3.9) es 3 e int(-3.9) es -3. Para redondear, usa int(math.Round(f)). Si el float está fuera del rango del tipo entero, el resultado depende de la implementación, así que comprueba antes el rango cuando el valor venga de la entrada.

¿Por qué string(65) devuelve "A" en Go?

Convertir un entero a string lo interpreta como un code point Unicode, y 65 es el code point de A. go vet lo marca: conversion from int to string yields a string of one rune, not a string of digits. Usa strconv.Itoa(65) para obtener "65".

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR