Go: Estructuras de datos
Golang: estructuras de datos fundamentales en Go. Aprende a usar arrays, slices, mapas y otras estructuras esenciales para desarrollar aplicaciones eficientes en Go.
Aprende Go GRATIS y certifícateLas estructuras de datos son componentes esenciales en cualquier lenguaje de programación, y Golang no es la excepción. Comprender cómo manejar y aplicar estas estructuras en Go permite desarrollar aplicaciones más eficientes y escalables. A continuación, se exploran las estructuras de datos más utilizadas en Golang, con ejemplos prácticos y actualizados.
Arrays
En Golang, un array es una colección de elementos del mismo tipo con una longitud fija. Los arrays se declaran especificando el tipo y la cantidad de elementos que contienen.
var numeros [5]int
En este ejemplo, numeros
es un array de enteros con una longitud de 5. También es posible inicializar un array con valores:
letras := [3]string{"a", "b", "c"}
Acceso y modificación de elementos
Los elementos de un array se acceden mediante índices, comenzando desde cero.
fmt.Println(letras[0]) // Imprime "a"
Para modificar un elemento:
letras[1] = "d"
fmt.Println(letras[1]) // Imprime "d"
Slices
Los slices son una vista flexible y dinámica de los arrays. A diferencia de los arrays, los slices pueden cambiar de tamaño. Se declaran sin especificar una longitud.
var numerosSlice []int
Creación y inicialización
Un slice puede crearse a partir de un array o usando la función integrada make
.
numerosArray := [5]int{1, 2, 3, 4, 5}
numerosSlice := numerosArray[1:4] // Slice desde el índice 1 hasta el 3
// Usando make
letrasSlice := make([]string, 3)
letrasSlice[0] = "x"
letrasSlice[1] = "y"
letrasSlice[2] = "z"
Añadir elementos
Para añadir elementos a un slice, se utiliza la función append
.
numerosSlice = append(numerosSlice, 6, 7)
fmt.Println(numerosSlice) // Imprime [2 3 4 6 7]
Capacidad y longitud
Los slices tienen una longitud y una capacidad. La longitud es el número de elementos en el slice, mientras que la capacidad es el número de elementos en el array subyacente a partir del punto inicial del slice.
fmt.Println(len(numerosSlice)) // Longitud del slice
fmt.Println(cap(numerosSlice)) // Capacidad del slice
Maps
Un map es una colección desordenada de pares clave-valor. Las claves deben ser de un tipo comparable, mientras que los valores pueden ser de cualquier tipo.
Creación y inicialización
Se utiliza la función make
para crear un map.
edad := make(map[string]int)
edad["Juan"] = 30
edad["Ana"] = 25
// Declaración con valores iniciales
paises := map[string]string{
"ES": "España",
"MX": "México",
}
Acceso y modificación
Para acceder a un valor:
fmt.Println(edad["Juan"]) // Imprime 30
Para modificar o añadir un valor:
edad["Juan"] = 31
Verificar existencia de una clave
Al acceder a una clave, es posible verificar si existe.
valor, existe := edad["Pedro"]
if existe {
fmt.Println("La edad de Pedro es", valor)
} else {
fmt.Println("Pedro no está en el map")
}
Eliminación de elementos
Para eliminar una clave y su valor asociado, se utiliza delete
.
delete(edad, "Ana")
Structs
Los structs son tipos de datos compuestos que agrupan campos. Son útiles para representar objetos o entidades con múltiples propiedades.
Definición y utilización
type Persona struct {
Nombre string
Edad int
}
func main() {
persona := Persona{
Nombre: "Luis",
Edad: 28,
}
fmt.Println(persona.Nombre) // Imprime "Luis"
}
Punteros a structs
Es posible utilizar punteros para referenciar structs.
func incrementarEdad(p *Persona) {
p.Edad++
}
func main() {
persona := Persona{"María", 22}
incrementarEdad(&persona)
fmt.Println(persona.Edad) // Imprime 23
}
Punteros
Los punteros almacenan la dirección de memoria de una variable. En Go, los punteros se utilizan para pasar referencias y modificar valores en funciones.
Declaración y uso
var numero int = 10
var punteroNumero *int = &numero
fmt.Println(*punteroNumero) // Imprime 10
*punteroNumero = 20
fmt.Println(numero) // Imprime 20
Interfaces
Las interfaces definen un conjunto de métodos que debe implementar un tipo. Permiten definir comportamientos comunes.
Definición y ejemplo
type Forma interface {
Area() float64
}
type Circulo struct {
Radio float64
}
func (c Circulo) Area() float64 {
return 3.1416 * c.Radio * c.Radio
}
func calcularArea(f Forma) {
fmt.Println("El área es:", f.Area())
}
func main() {
circulo := Circulo{Radio: 5}
calcularArea(circulo)
}
Canales
Los canales son una característica fundamental en Go para la comunicación entre goroutines. Permiten enviar y recibir valores.
Creación y uso
func enviarMensaje(c chan string) {
c <- "Hola desde la goroutine"
}
func main() {
mensaje := make(chan string)
go enviarMensaje(mensaje)
fmt.Println(<-mensaje) // Imprime "Hola desde la goroutine"
}
Conjuntos (Sets)
Aunque Go no tiene una estructura de datos de conjunto integrada, se pueden simular utilizando maps.
Implementación de un conjunto
conjunto := make(map[string]struct{})
conjunto["elemento1"] = struct{}{}
conjunto["elemento2"] = struct{}{}
if _, existe := conjunto["elemento1"]; existe {
fmt.Println("El elemento1 está en el conjunto")
}
Listas enlazadas
La biblioteca estándar de Go proporciona implementaciones para listas.
Uso de list.List
import (
"container/list"
)
func main() {
lista := list.New()
lista.PushBack(1)
lista.PushBack(2)
lista.PushBack(3)
for elemento := lista.Front(); elemento != nil; elemento = elemento.Next() {
fmt.Println(elemento.Value)
}
}
Pilas y colas
Las pilas y colas pueden implementarse utilizando slices o la biblioteca estándar.
Implementación de una pila usando slices
type Pila []int
func (p *Pila) Push(valor int) {
*p = append(*p, valor)
}
func (p *Pila) Pop() int {
indice := len(*p) - 1
valor := (*p)[indice]
*p = (*p)[:indice]
return valor
}
func main() {
var pila Pila
pila.Push(10)
pila.Push(20)
fmt.Println(pila.Pop()) // Imprime 20
}
Implementación de una cola usando slices
type Cola []int
func (c *Cola) Enqueue(valor int) {
*c = append(*c, valor)
}
func (c *Cola) Dequeue() int {
valor := (*c)[0]
*c = (*c)[1:]
return valor
}
func main() {
var cola Cola
cola.Enqueue(10)
cola.Enqueue(20)
fmt.Println(cola.Dequeue()) // Imprime 10
}
Árboles
Aunque Go no incluye árboles en su biblioteca estándar, es posible implementarlos.
Ejemplo de un árbol binario simple
type Nodo struct {
Valor int
Izq *Nodo
Der *Nodo
}
func (n *Nodo) Insertar(valor int) {
if valor <= n.Valor {
if n.Izq == nil {
n.Izq = &Nodo{Valor: valor}
} else {
n.Izq.Insertar(valor)
}
} else {
if n.Der == nil {
n.Der = &Nodo{Valor: valor}
} else {
n.Der.Insertar(valor)
}
}
}
func main() {
raiz := &Nodo{Valor: 50}
raiz.Insertar(30)
raiz.Insertar(70)
// ...continuar con la implementación
}
Lecciones de este módulo de Go
Lecciones de programación del módulo Estructuras de datos del curso de Go.
Ejercicios de programación en este módulo de Go
Evalúa tus conocimientos en Estructuras de datos con ejercicios de programación Estructuras de datos de tipo Test, Puzzle, Código y Proyecto con VSCode.