En esta página
Variables y tipos de datos
El sistema de tipos de Go
Go es un lenguaje de tipado estático fuerte. Esto significa dos cosas: primero, cada variable tiene un tipo fijo que el compilador conoce en tiempo de compilación; segundo, las conversiones entre tipos nunca ocurren de forma implícita — siempre debes ser explícito. Esta combinación elimina toda una categoría de bugs que son comunes en JavaScript o Python.
Entender el sistema de tipos de Go es fundamental porque todo lo demás en el lenguaje se construye sobre él.
Declarando variables
Go ofrece varias formas de declarar variables, cada una con su contexto de uso ideal:
1. Declaración explícita con `var`
var nombre string = "Go"
var edad int = 13 // Go cumplió 13 años en 2022
var pi float64 = 3.14159
var activo bool = true2. Declaración con inferencia de tipo
Si proporcionas un valor inicial, Go puede inferir el tipo:
var nombre = "Go" // string inferido
var pi = 3.14159 // float64 inferido
var activo = true // bool inferido3. Declaración corta con `:=`
La forma más común dentro de funciones. Solo funciona dentro de funciones (no a nivel de paquete):
func main() {
nombre := "Gopher" // string
versión := 1.26 // float64
activo := true // bool
bytes := byte('A') // byte (uint8)
}4. Bloque `var` para múltiples variables
Cuando declaras varias variables relacionadas, un bloque var mejora la legibilidad:
var (
host string = "localhost"
puerto int = 8080
debug bool = false
timeout float64 = 30.0
)Tipos numéricos
Go tiene un conjunto específico de tipos numéricos. La elección correcta importa para rendimiento y semántica:
Enteros con signo
| Tipo | Tamaño | Rango |
|---|---|---|
int8 |
8 bits | -128 a 127 |
int16 |
16 bits | -32,768 a 32,767 |
int32 |
32 bits | -2,147,483,648 a 2,147,483,647 |
int64 |
64 bits | ±9.2 × 10¹⁸ |
int |
32 o 64 bits* | depende de la plataforma |
*int es 64 bits en sistemas de 64 bits (prácticamente todos los sistemas modernos). Es el tipo entero por defecto.
Enteros sin signo
var b uint8 = 255 // byte — alias de uint8
var s uint16 = 65535
var u uint32 = 4294967295
var g uint64 = 18446744073709551615
var n uint = 42 // sin signo, tamaño de plataformaPunto flotante
var f32 float32 = 3.14 // precisión simple (~7 dígitos decimales)
var f64 float64 = 3.14159265358979 // precisión doble (~15 dígitos)
// float64 es el tipo por defecto para literales flotantes
pi := 3.14159 // float64Números complejos
var c64 complex64 = 1 + 2i
var c128 complex128 = 3.14 + 2.71iEl tipo `string`
En Go, un string es una secuencia inmutable de bytes codificada en UTF-8. No puedes modificar un carácter de un string directamente — debes crear uno nuevo:
saludo := "¡Hola, Go!"
// Longitud en bytes (no en caracteres Unicode)
fmt.Println(len(saludo)) // puede ser > número de caracteres si hay UTF-8 multi-byte
// Concatenación
completo := saludo + " ¿Cómo estás?"
// String multilínea con backticks (raw string literal)
json := `{
"nombre": "Go",
"versión": 1.26
}`
// Interpolación (requiere fmt.Sprintf)
mensaje := fmt.Sprintf("Versión: %.2f", 1.26)`byte` y `rune`
Aquí está una distinción crucial en Go:
byte(alias deuint8): representa un byte individual. Útil para trabajar con datos binarios.rune(alias deint32): representa un punto de código Unicode. Un solo carácter comoñ,éo中puede ocupar múltiples bytes en UTF-8, pero es siempre un solo rune.
// Iterar sobre bytes
s := "hola"
for i := 0; i < len(s); i++ {
fmt.Printf("byte[%d] = %d\n", i, s[i])
}
// Iterar sobre runes (caracteres Unicode correctamente)
for i, r := range "¡Hola!" {
fmt.Printf("rune[%d] = %c (%d)\n", i, r, r)
}
// Convertir string a slice de runes para acceso por índice
runes := []rune("¡Hola!")
fmt.Println(len(runes)) // 6 (caracteres), no bytesEl tipo `bool`
activo := true
inactivo := false
// Operadores lógicos
resultado := activo && !inactivo // true
cualquiera := activo || inactivo // trueValores cero (zero values)
Esta es una de las características más elegantes de Go: toda variable declarada sin valor inicial recibe automáticamente su valor cero. No hay variables sin inicializar, no hay comportamiento indefinido:
var i int // 0
var f float64 // 0.0
var b bool // false
var s string // "" (cadena vacía)
var p *int // nil
var slice []int // nil
var m map[string]int // nilLos valores cero hacen que el código sea predecible. En otros lenguajes, leer una variable no inicializada puede dar resultados aleatorios o lanzar excepciones. En Go, siempre obtienes el valor cero definido por el tipo.
Constantes y `const`
Las constantes en Go se evalúan en tiempo de compilación y no ocupan memoria en tiempo de ejecución:
const Pi = 3.14159265358979323846
const Empresa = "Bemorex"
const MaxConexiones = 100
// Constantes tipadas
const Timeout time.Duration = 30 * time.Second
// Bloque de constantes
const (
KB = 1024
MB = 1024 * KB
GB = 1024 * MB
)`iota`: enumeraciones idiomáticas
iota es un identificador especial de Go que se usa dentro de bloques const. Empieza en 0 y se incrementa en 1 por cada constante en el bloque:
type Nivel int
const (
Principiante Nivel = iota // 0
Intermedio // 1
Avanzado // 2
Experto // 3
)
// Con expresiones
type ByteSize float64
const (
_ = iota // Ignorar el primer valor con _
KB ByteSize = 1 << (10 * iota) // 1024
MB // 1048576
GB // 1073741824
TB // 1099511627776
)Conversión de tipos explícita
En Go, nunca hay conversión implícita entre tipos numéricos. Debes ser explícito:
var i int = 42
var f float64 = float64(i) // int → float64
var u uint = uint(f) // float64 → uint
// De string a número
import "strconv"
n, err := strconv.Atoi("42") // string → int
if err != nil {
fmt.Println("Error de conversión")
}
f, err := strconv.ParseFloat("3.14", 64) // string → float64
// De número a string
s := strconv.Itoa(42) // int → string (más eficiente que fmt.Sprintf)
s2 := fmt.Sprintf("%.2f", 3.14) // float64 → string formateadoMúltiple asignación
Go permite asignar múltiples variables en una sola línea:
x, y := 10, 20
a, b := "hola", true
// Intercambiar valores sin variable temporal
x, y = y, x
fmt.Println(x, y) // 20 10La variable en blanco `_`
El guion bajo _ descarta valores. Es el "agujero negro" de Go:
// Ignorar el índice en un range
for _, valor := range []int{1, 2, 3} {
fmt.Println(valor)
}
// Ignorar un valor de retorno
resultado, _ := strconv.Atoi("42") // ignorar el error (no recomendado en producción)Con este conocimiento sólido del sistema de tipos, en la siguiente lección exploraremos cómo controlar el flujo de ejecución con if, switch y el único bucle de Go: for.
Inicia sesión para guardar tu progreso