Saltar al contenido principal

Documentación de Introducción a Golang

¿Qué es Go (Golang)?

  • Lenguaje de programación concurrente y compilado.
  • Sintaxis similar a C.
  • Posee su propia plataforma de desarrollo.
  • Concurrente: maneja diagramas de flujo de procesos concurrentes.
  • Tipado estático.
  • Recolección de basura segura, optimizada para el rendimiento en función del hardware y sistema operativo.
  • Produce ejecutables que pueden ser servidores web o aplicaciones de escritorio.
  • Disponible en formato binario para Windows, Linux y Mac.

Características principales

  • Fácil de aprender y adaptado para el trabajo en equipo.
  • Modularización del desarrollo, similar a Django.
  • Código abierto, apoyado y compatible con Google.
  • Simultaneidad incorporada:
    • Procesos en paralelo mediante Goroutines y Canales, optimizados según los procesadores del hardware.
  • Biblioteca estándar: cubre tareas principales, con soporte para librerías y frameworks de terceros (por ejemplo, bases de datos).
  • Fuertemente tipado:
    • Obliga a definir y entender cada variable.
    • Si no defines el tipo, Go lo infiere.
    • Para convertir el tipo, debes hacer un cast explícito.
  • Ahorro de memoria en tiempo de ejecución:
    • Ideal para desarrollos de alto rendimiento y alta demanda (ej: Big Data).
    • Actualmente usado en aplicaciones web y APIs RESTful.
  • Lenguaje compilado:
    • Se realiza un build de la aplicación para su despliegue.
    • Incluye servidor incorporado.
  • No orientado a objetos:
    • Utiliza estructuras, funciones, métodos e interfaces para optimizar el rendimiento.
  • Manejo de errores:
    • Prefiere advertencias del compilador en lugar de excepciones para ahorrar recursos.

Recursos oficiales


Estructura básica

package nombre_del_modulo

// Paquete handler u otros paquetes según la aplicación

Primer programa en Go

package main

import (
"fmt"
)

func main() {
fmt.Println("Hola mundo desde Golang o Go")
}

  • Todo programa debe tener una función principal llamada main.
  • El archivo principal también debe llamarse main.go.
  • Debes utilizar al menos una funcionalidad importada.

Archivo go.mod

Para inicializar un módulo:

go mod init <nombre_proyecto>

Ejemplo:

module clase_1

go 1.23.0

  • Interpreta la app como un módulo.
  • El archivo go.mod se actualiza al agregar librerías.
  • Puedes ejecutar la app con:
go run .


Variables y Constantes

  • Comentarios: // comentario
  • Si declaras una variable y no la usas, obtendrás un error en tiempo de ejecución.
  • Constantes:
const MiConstante = "Valor de mi constante"

  • No es necesario declarar el tipo de una constante.
  • Si una variable o constante empieza con mayúscula, es pública y accesible desde otros módulos.
  • fmt.Printf permite usar comodines de formato:
fmt.Printf("El valor de MiConstante es %s", MiConstante)

  • Go soporta caracteres especiales como la ñ y las tildes.
package main

import "fmt"

const MiConstante = "Valor de mi constante ñandú"

func main() {
// Declaración por inferencia
var nombre string = "Cesar"
fmt.Println(nombre)

// Declaración rápida
nombre2 := "Juan"
fmt.Println(nombre2)

fmt.Printf("El valor de MiConstante es %s \\n", MiConstante)
}


Tipos de Datos en Go

  • String: textos.
  • Texto largo: usa comillas invertidas ```.
  • Booleanos: true, false.
  • Flotantes:
    • float32
    • float64
  • Enteros:
    • int8, int16, int32, int64
    • uint8, uint16, uint32, uint64 (sin signo)
func main() {
var string1 string = "texto"
fmt.Println(string1)

textoGrande := `Este es un texto muy
grande que se puede escribir
en varias líneas usando comillas mágicas.`
fmt.Println(textoGrande)

var estado bool = true
fmt.Println(estado)

var flotante32 float32 = 32.33
fmt.Println(flotante32)

var flotante64 float64 = 32.33
fmt.Println(flotante64)

var entero int = 1234
fmt.Println(entero)

var entero8 int8 = 123
var entero16 int16 = 123
var entero32 int32 = 123
var entero64 int64 = 123
var enterounit8 uint8 = 123
var enterounit16 uint16 = 123
var enterounit32 uint32 = 123
var enterounit64 uint64 = 123

fmt.Println(entero8, entero16, entero32, entero64)
fmt.Println(enterounit8, enterounit16, enterounit32, enterounit64)
}


Reflect y TypeOf

  • El paquete reflect permite obtener el tipo de una variable en tiempo de ejecución.
package main

import (
"fmt"
"reflect"
)

func main() {
string1 := true
fmt.Println(reflect.TypeOf(string1)) // bool
}


Punteros en Go

  • Los punteros permiten acceder directamente al valor de la dirección de memoria de una variable.
package main

import "fmt"

func main() {
var estado bool = true
color := "rojo"

fmt.Println(color, &color) // Muestra valor y dirección de memoria
fmt.Println(estado, &estado)

calor := &color
fmt.Println(calor, *calor) // Muestra la dirección y el valor almacenado
}

Condicionales y operadores

Comparacion entre un valor u otro.

  • Operadores de comparación
    • Igual a
    • Distinto de
    • menor que
    • menor igual
    • mayor
    • mayor igual
  • A diferencia de C, no se usan parentesis en las condiciones en los ifs.
  • Condicionales:
    • if
    • else
    • if else
  • Operadores Logicos:
    • && (and)
    • || (or)
    • ! (not)
  • Declaración de variables en tiempo de ejecucion
    	if variable := 2; variable == 1 {
    fmt.Println(variable)
    }

    // Da ERROR
    fmt.Println(variable)
  • Nota: Golang no usa excepciones
    • Por lo tanto golang te obliga a validar los errores con el valor nil
      _, error := some()

      if error != nil {
      // Haz algo
      }

Ciclos

Estructura que permite ejecutar n cantidad de veces una funcionalidad n veces de acuerdo a una condición.

  • for
    for i := 0; i < 10; i++ {
    // Haz algo
    }
  • while (pero con for 🙂)
    for i < 11 {
    fmt.Println(i)
    i++
    }
  • break
    • Corta el ciclo si se cumple una condición
      for i2 := 1; i2 < 11; i2++ {
      fmt.Println(i2)

      if i2 == 3 {
      break
      }
      }
  • continue
    • Salta a la siguiente iteración
      for i2 := 1; i2 < 11; i2++ {
      if i2 == 3 {
      continue
      }

      fmt.Println(i2)
      }

Arreglos o slices

Estructura de datos, permite almacenar mas de un valor

  • Array: Decir el largo o capacidad de valores que va a tener
    • var paises [4]string arreglo de tipo string con 4 valores
  • Slices: Es dinamico, se puede ir modificando la cantidad de datos
  • len largo del arreglo
    • len(paises)
  • Si agrego mas elementos de los que tiene asignado el array, genera un warning o error
    	var paises [4]string
    paises[0] = "argentina"
    paises[1] = "bolivia"
    paises[2] = "venezuela"
    paises[3] = "Perú"
    paises[4] = "España"
  • Los slices se crean de la siguiente forma
    var paises2 = make([]string, 5)
    • Con la palabra reservada make
    • el tipo
    • el tamaño
    • Se recomienda usar un largo predeterminado pero el slice es dinamico
  • Agregar elemento al final del slice
    • append
      paises2 = append(paises2, "Noruega")
      • Esto no es posible en un array
  • Eliminar elemento de un slice en la posición 5 del array
    	paises2 = append(paises[:5], paises2[5+1:]...)
  • Código final
func main() {
// arreglo (array)
var paises [5]string
paises[0] = "argentina"
paises[1] = "bolivia"
paises[2] = "venezuela"
paises[3] = "Perú"
paises[4] = "España"
fmt.Println(paises)
fmt.Println(paises[0])
fmt.Println(paises[2])
fmt.Println("El largo del arreglo es: ", len(paises))

// Muestra el tipo y tamaño del array
fmt.Println(reflect.TypeOf(paises))
// Output: [5]string

// Slices
var paises2 = make([]string, 5)

paises2[0] = "argentina"
paises2[1] = "bolivia"
paises2[2] = "venezuela"
paises2[3] = "Perú"
paises2[4] = "España"

fmt.Println(paises2)

fmt.Println(reflect.TypeOf(paises2))
// Output: []string
// No muestra el tamaño de la estructura al ser dinamico.

// Agregar un elemento al slice
paises2 = append(paises2, "Noruega")

fmt.Println(paises2)
// [argentina bolivia venezuela Perú España Noruega]

// eliminar elem,ento de un slice
paises2 = append(paises[:5], paises2[5+1:]...)
// [argentina bolivia venezuela Perú España]

fmt.Println(paises2)
}

Mapas

Estructuras de datos de tipo clave-valor.

  • paises := make(map[string]int)
    • Clave string
    • Valor int
  • Agregar valores al map
    paises["argentina"] = 400000
    paises["españa"] = 300000
    paises["brasil"] = 500000
  • Otra sintaxis para definir maps
paises2 := map[int]string{
1: "Argentina",
2: "Chile",
}
  • Checkear si existe la propiedad en el map

    pais, existe := paises2[11]
  • Elimino un elemento del map

    • delete(paises2, 1)
      • le paso el map y el index del elemento a borrar
  • Recorrer un map con un for

    for id, valor := range paises2 {
    fmt.Printf("ID: %v | Nombre: %v \n", id, valor)
    }
  • Codigo final

func main() {
paises := make(map[string]int)
paises["argentina"] = 400000
paises["españa"] = 300000
paises["brasil"] = 500000

fmt.Println(paises)
// map[argentina:400000 brasil:500000 españa:300000]

fmt.Println(reflect.TypeOf(paises))
// map[string]int

// Otra sintaxis de maps
paises2 := map[int]string{
1: "Argentina",
2: "Chile",
}

fmt.Println(paises2)
// map[1:Argentina 2:Chile]

fmt.Println(reflect.TypeOf(paises2))
// map[int]string

fmt.Println(paises2[1])
// Argentina

// Veamos si existe algun valor en el map
pais, existe := paises2[2]

fmt.Println(pais)
fmt.Println(existe)
//Chile
// true

// Eliminar un elemento
delete(paises2, 1)

fmt.Println(paises2)

for id, valor := range paises2 {
fmt.Printf("ID: %v | Nombre: %v \n", id, valor)
}

resp := map[string]string{
"estado": "ok",
"mensaje": "Cualquier mensaje",
}

fmt.Println(resp)
}