Lenguaje de programación Go

5 de diciembre de 2024

Lang: cs en de es

Hace poco probé el lenguaje de programación Go. Y utilicé ChatGPT para generar algunos ejemplos de muestra. Subí estos ejemplos a github y preparé una descripción sobre cómo probar los ejemplos. Según la guía de este artículo, también puedes probar el lenguaje de programación Go.

En el cambiante mundo de la tecnología, la simplicidad, la velocidad y la escalabilidad importan más que nunca, el lenguaje de programación Go se ha vuelto muy popular. Go (o Golang) fue diseñado por Google. El lenguaje Go combina un enfoque moderno de la programación con un mínimo de complejidad innecesaria. innecesaria. Con características como una programación paralela sencilla, una gestión de memoria robusta y una sintaxis minimalista, ha sido especialmente popular en el desarrollo de aplicaciones web, microservicios y soluciones en la nube.

Características básicas de Go

  • Simplicidad y claridad

    Go hace hincapié en una sintaxis simple y fácil de entender, lo que facilita la lectura y escritura de código. Contiene un mínimo cantidad de palabras clave, lo que reduce la complejidad de learning.

  • Lenguaje estáticamente tipado

    Go está tipado estáticamente, lo que significa que los tipos de las variables se conocen en tiempo de compilación, lo que ayuda a en la detección de errores.

  • Compilación rápida

    Go está diseñado para compilar código muy rápidamente, lo que hace que el desarrollo y el despliegue sean más rápidos.

  • Soporte integrado para paralelismo

    Go tiene soporte nativo para gorutins y canales, que facilitan la implementación de paralelismo y competencia en la paralela y competitiva. Los gorutins son unidades de hilos ligeros que pueden ejecutarse de forma concurrente.

  • Gestión automática de memoria (Garbage Collection).

    Go cuenta con un recolector de basura integrado que gestiona automáticamente la memoria y libera los objetos no utilizados.

  • Sistema de paquetes sencillo

    Go cuenta con un sistema de gestión de paquetes minimalista que facilita la importación y organización de bibliotecas.

  • Fuerte biblioteca estándar

    Go incluye una sólida biblioteca estándar que proporciona funciones para trabajar con redes, archivos, cifrado, servidores web, y otras tareas comunes.

  • Portabilidad entre plataformas

    Go facilita la compilación de aplicaciones en diferentes plataformas (Linux, macOS, Windows) gracias al soporte para compilación cruzada.

  • Fuerte cadena de herramientas

    Go ofrece herramientas integradas para el formateo de código (gofmt), análisis estático, pruebas y benchmarking.

  • Sin excepciones

    Go no utiliza excepciones tradicionales para la gestión de errores. En su lugar, utiliza valores de retorno y el modismo de "manejo de errores", que conduce a la gestión explícita de errores.

  • Seguridad en la ejecución paralela

    Go minimiza el riesgo de race condition a través de construcciones como los canales que permiten compartir datos de forma segura entre gorutinas.

  • Minimalismo por diseño

    Go eliminó algunas características comunes en otros lenguajes (por ejemplo, herencia, genéricos - éstos sólo se añadieron en Go 1.18, pero aún de forma minimalista).

Go es ideal para desarrollar servidores web, arquitecturas de microservicios, aplicaciones de red y otros modernos sistemas distribuidos.

Instalación

En una distribución Linux normal, instalar Go es sencillo a través del peg system.

En la distribución Linux Magei, este comando instala Go:

urpmi golang

Para Windows y Mac, puede descargar el instalador del lenguaje Go de Internet.

Hola palabra

El ejemplo básico es la impresión de texto.
El siguiente código en Go imprimirá el texto "¡Hola, mundo!" en la consola. Utiliza el paquete fmt para dar salida al texto y fmt.Println para mostrar el mensaje. La función main es el punto de entrada del programa, que ejecuta automáticamente cuando se ejecuta el programa.

paquete main

import "fmt"

func main() {
    fmt.Println("¡Hola, mundo!")
}

Para compilar el programa, utiliza go build.go o go build hello.go. y luego ejecuta el binario creado ./hola.

O introduzca un comando que compile y ejecute a la vez go run . o go run hello.go.

programación-lenguaje-go-ejemplos

Servidor web

Este código ejecuta un servidor web simple en el puerto 8080. Cada petición entrante a la ruta raíz (/) es manejada por la función handler, que responde con un mensaje que contiene la ruta URL solicitada. El servidor utiliza http.HandleFunc para asignar esta función y se activa mediante http.ListenAndServe. Si el servidor no se inicia, el programa imprime un error y sale.

paquete principal

import (
	"fmt"
	"log"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hola, ha solicitado: %s\n", r.URL.Path)
}

func main() {
	http.HandleFunc("/", handler)

	fmt.Println("Iniciando servidor en el puerto 8080")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}


Paralelismo - hilos

Este código muestra cómo ejecutar tareas en paralelo en Go usando gorutin y cómo sincronizar su finalización usando sync.WaitGroup.

package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

// Simular una tarea de larga ejecución
func longRunningTask(id int, wg *sync.WaitGroup) {
	difiere wg.Done()

	// Simular un tiempo de proceso aleatorio entre 1-3 segundos
	duration := time.Duration(rand.Intn(3)+1) * time.Second
	fmt.Printf("Tarea %d iniciada, tardará %v\n", id, duración)

	time.Sleep(duration) // Simular el procesamiento
	fmt.Printf("Tarea %d finalizada", id)
}

func main() {
	rand.Semilla(tiempo.Ahora().UnixNano())

	// Grupo de sincronización para esperar a que se complete todo gorutin
	var wg sync.WaitGroup

	// Número de tareas paralelas
	numTasks := 5

	// Ejecutar tareas en paralelo usando gorutin
	for i := 1; i <= numTasks; i++ {
		wg.Añadir(1)
		go longRunningTask(i, &wg)
	}

	// Esperar a que se completen todas las tareas
	wg.Wait()

	fmt.Println("Todas las tareas completadas")
}

API REST

Qué es la API rest?
REST API (Representational State Transfer Application Programming Interface) es un estilo arquitectónico para el diseño de aplicaciones de red, que utiliza métodos HTTP estándar como GET, POST, PUT, DELETE para comunicarse entre el cliente y el servidor. API REST Permite a los clientes acceder a datos y operaciones en el servidor a través de un localizador uniforme de recursos (URL) y separa la lógica del cliente de la del servidor. La API funciona basándose en principios como el stateless (cada petición es independiente) y utiliza formatos como JSON o XML para intercambiar datos, lo que garantiza una fácil integración entre distintos sistemas.

Si estás utilizando el lenguaje de programación PHP, entonces una excelente opción para hacerlo funcionar. Plataforma API de REST API, que es una librería construida para Symfony y construida sobre Doctrine.

Aquí tienes un ejemplo de código en Go que implementa la API REST. El siguiente código implementa la API RESTful en Go para gestionar elementos. Utiliza el paquete gorilla/mux para enrutar las peticiones HTTP. La aplicación permite realizar operaciones CRUD (crear, leer, actualizar y eliminar) sobre ítems que se almacenan en memoria en memoryStore. Cada ítem tiene un único ID, nombre y valor. El código implementa varios endpoints para recuperar todos los ítems (/items), recuperar elementos individuales por ID (/items/{id}), crear un nuevo elemento, actualizar un elemento existente y eliminar un elemento. Utiliza el bloqueo de sincronización sync.Mutex para proporcionar un acceso seguro a los datos.

paquete main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"sync"

	"github.com/gorilla/mux"
)

// ir a get -u github.com/gorilla/mux
type Artículo struct {
	ID int `json: "id"`
	Nombre string `json: "nombre"`
	Valor string `json: "valor"`
}

var (
	memoryStore = make(mapa[int]Item)
	idContador = 1
	mu sync.Mutex
)

func getItems(w http.ResponseWriter, r *http.Request) {
	mu.Bloquear()
	aplazar mu.Unlock()

	var items []Item
	for _, item := rango memoryStore {
		items = append(items, item)
	}
	json.NewEncoder(w).Encode(items)
}

func getItem(w http.ResponseWriter, r *http.Request) {
	mu.Bloquear()
	aplazar mu.Unlock()

	params := mux.Vars(r)
	id, _ := strconv.Atoi(params["id"])

	item, exists := memoryStore[id]
	if !existe {
		http.Error(w, "Item not found", http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(item)
}

func createItem(w http.ResponseWriter, r *http.Request) {
	mu.Bloquear()
	aplazar mu.Unlock()

	var item Artículo
	_ = json.NewDecoder(r.Body).Decode(&item)
	item.ID = idContador
	idContador++
	memoryStore[item.ID] = item
	json.NewEncoder(w).Encode(item)
}

func updateItem(w http.ResponseWriter, r *http.Request) {
	mu.Bloquear()
	aplazar mu.Unlock()

	params := mux.Vars(r)
	id, _ := strconv.Atoi(params["id"])

	_, existe := memoryStore[id]
	if !existe {
		http.Error(w, "Item not found", http.StatusNotFound)
		return
	}

	var updatedItem Item
	_ = json.NewDecoder(r.Body).Decode(&updatedItem)
	updatedItem.ID = id
	memoryStore[id] = updatedItem
	json.NewEncoder(w).Encode(updatedItem)
}

func deleteItem(w http.ResponseWriter, r *http.Request) {
	mu.Bloquear()
	aplazar mu.Unlock()

	params := mux.Vars(r)
	id, _ := strconv.Atoi(params["id"])

	_, existe := memoryStore[id]
	if !existe {
		http.Error(w, "Item not found", http.StatusNotFound)
		return
	}
	delete(memoryStore, id)
	w.WriteHeader(http.StatusNoContent)
}

func main() {
	router := mux.NuevoRouter()

	// Endpoints para la API REST
	router.HandleFunc("/items", getItems).Methods("GET")
	router.HandleFunc("/items/{id}", getItem).Methods("GET")
	router.HandleFunc("/items", createItem).Methods("POST")
	router.HandleFunc("/items/{id}", updateItem).Methods("PUT")
	router.HandleFunc("/items/{id}", deleteItem).Methods("DELETE")

	fmt.Println("Servidor ejecutándose en el puerto 8080")
	log.Fatal(http.ListenAndServe(":8080", enrutador))
}

Después de ejecutar esta aplicación, un servidor web disponible en el puerto 8080 se ejecutará en su ordenador. Así que puedes escribir la URL http://localhost:8080/ en tu navegador web.
Para otros usos en los que necesites enviar peticiones HTTP con datos, puedes utilizar, por ejemplo, la herramienta de consola .curl.

Crear un nuevo elemento:

curl -X POST http://localhost:8080/items -H "Content-Type: application/json" -d '{"nombre": "Artículo1", "valor": "Valor1"}'

Listar todos los ítems:
curl http://localhost:8080/items

Mostrar el elemento con ID 1:
curl http://localhost:8080/items/1

Actualizar el identificador del elemento 1:
curl -X PUT http://localhost:8080/items/1 -H "Content-Type: application/json" -d '{"name": "UpdatedItem1", "value": "UpdatedValue1"}'

Deltete el ID del elemento 1:
curl -X DELETE http://localhost:8080/items/1

Aplicaciones de la interfaz de usuario

En el lenguaje Go también es posible realizar aplicaciones con interfaz gráfica de usuario.
lenguaje-de-programación-go-gui

He aquí una pequeña muestra de la aplicación gráfica. El siguiente código crea una sencilla aplicación gráfica en Go utilizando la librería Qt. La aplicación crea una ventana principal con con el título "Go Qt Example" y un tamaño mínimo de 400x300 píxeles. Dentro de la ventana hay un botón "Click Me!" que cuando se pulsa, muestra un mensaje informativo con el texto "¡Botón pulsado!". La aplicación utiliza un layout para colocar el botón y establece este diseño en el widget central. A continuación se muestra la ventana principal y la aplicación se lanza y espera la interacción del usuario.

paquete main

import (
	"wasp"

	"github.com/therecipe/qt/widgets"
)

func main() {
	// Crea una nueva aplicación Qt
	app := widgets.NewQApplication(len(os.Args), os.Args)

	// Crea la ventana principal
	window := widgets.NewQMainWindow(nil, 0)
	window.SetWindowTitle("Ejemplo Go Qt")
	window.SetMinimumSize2(400, 300)

	// Crea un widget central y un layout
	centralWidget := widgets.NewQWidget(nil, 0)
	layout := widgets.NewQVBoxLayout()

	// Crear botón
	button := widgets.NewQPushButton2("Click Me!", nil)
	button.ConnectClicked(func(bool) {
		widgets.QMessageBox_Information(nil, "Message", "¡Botón pulsado!", widgets.QMessageBox__Ok, widgets.QMessageBox__Ok)
	})

	// Añadir un botón al layout
	layout.AddWidget(button, 0, 0)

	// Establecer el layout al widget central
	centralWidget.SetLayout(layout)

	// Establece el widget central en la ventana principal
	window.SetCentralWidget(centralWidget)

	// Mostrar la ventana
	window.Show()

	// Lanzar la aplicación
	app.Ejec()
}

Qué es un archivo go.mod

Un fichero go.mod es un fichero del lenguaje Go que define un módulo y sus dependencias. Un módulo es una colección de paquetes que están versionados y pueden ser utilizados en otros proyectos. El archivo go.mod especifica el nombre del módulo, la versión Go y cualquier otra dependencia que el módulo necesite.

Ejemplos de contenido:

module github.com/username/project

go 1.20

require (
    github.com/some/dependencia v1.2.3
    golang.org/x/tools v0.1.5
)

Códigos fuente

Todos los códigos fuente de los ejemplos en el lenguaje de programación Go están disponibles en github. Sólo tienes que clonar el repositorio y podrás probar las aplicaciones.

Video tutorial

Vídeo y descripciones verbales para ejemplos de aplicación de Go

Manejo de errores

Go no utiliza excepciones tradicionales para el manejo de errores. En su lugar, utiliza valores de retorno y el modismo de "manejo de errores". Qué significa esto?

El lenguaje Go (Golang) adopta un enfoque diferente al manejo de errores que muchos otros lenguajes de programación. En diferencia de lenguajes como Java, Python o C#, que utilizan excepciones, Go utiliza valores de retorno.

Qué significa específicamente:

  1. Sin excepciones:

    Go no tiene un mecanismo para levantar y atrapar excepciones (por ejemplo, bloques try-catch). En su lugar las funciones en Go típicamente devuelven dos valores:

    • El resultado principal de la función.
    • Un error como valor de tipo error.
  2. Enfoque de "gestión de errores" idiomático:

    Los errores se manejan explícitamente, por ejemplo:

    
    package main
    
    import (
        "fmt"
        "wasp"
    )
    
    func main() {
        file, err := os.Open("ejemplo.txt")
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        defer archivo.Cerrar()
    
        fmt.Println("Archivo abierto con éxito")
    }
    
                

    En este ejemplo:

    • os.Open devuelve dos valores: el fichero abierto (*os.File) y un error (error) si el archivo no consigue abrirse.
    • El código comprueba si err no es nil, lo que indica que se ha producido un error.
    • .
  3. Beneficios de este enfoque:
    • Simplicidad: El código es más legible y menos mágico porque la lógica de error es explícita.
    • Control: Los desarrolladores tienen un control claro sobre cómo se gestionan los errores.
    • Seguridad: No hay excepciones "ocultas" que se puedan colar.
  4. Desventajas:
    • Más código: El código puede ser más prolijo porque cada llamada a función suele requerir comprobación de errores.
    • Necesidad de disciplina: Los desarrolladores siempre deben atrapar y manejar los errores correctamente, de lo contrario podrían ser ignorados.

Este enfoque refleja la filosofía de Go de preferir la simplicidad y la previsibilidad a mecanismos más complejos como las excepciones.

Evaluación del lenguaje Go

Personalmente, veo la ventaja del lenguaje de programación Go en que simplemente puedes desarrollar una aplicación en Linux y luego croc-compilar la aplicación para otra plataforma y simplemente subir el binario y ejecutarlo allí. Si usas una librería gráfica multiplataforma como QT, puede desarrollar fácilmente aplicaciones gráficas en Linux y luego el cliente puede ejecutar esas aplicaciones en Windows o Mac OS, por ejemplo.
El manejo explícito de errores hace que la aplicación sea más estable y segura. Así que cuando la rapidez no es una prioridad de desarrollo, sino la estabilidad y la seguridad, entonces en lugar de PHP será adecuado el lenguaje Go. O Utilizar el lenguaje seguro Rust.
Para aquellos que necesiten programar aplicaciones paralelas, el lenguaje Go será adecuado como herramienta sencilla que permite crear fácilmente aplicaciones funcionales para ejecutar en paralelo.

Artículos sobre un tema similar

Análisis de la asignación y fijación de precios del desarrollo de proyectos de software
Programa Python para controlar Docker mediante la API
Cómo utilizar MailCatcher para probar correos electrónicos
API OpenAI de Python
Creación de una aplicación web WebSocket y configuración de un proxy
Gestión de proyectos: desarrollo ágil de software
Cómo ejecutar aplicaciones PHP antiguas
Lo que debe saber un buen programador
Lenguaje de programación Rust
NodeJS: desarrollo, configuración del servidor
Fallo de seguridad de Nette CVE-2020-15227
API REST: API de plataforma
Alojamiento web y de correo personalizado con el software ISP Config
Programación en SQL: PostgreSQL, MySQL/MariaDB
HTTPS: web segura
Base de datos NoSQL Mongo DB
Connecting to Microsoft SQL Server from Linux
¿Cuál es la descripción del trabajo de un programador?
Localización de aplicaciones Python
Qué correo y alojamiento web elegir
Digispark - Programar microcontrolador Atmel ATtiny con Arduino IDE
Desarrollo para procesadores ARM con Arduino IDE
Cómo programar el procesador WiFi ESP8266
Smartphone abierto con Linux - Openmoko Neo FreeRunner

Boletin informativo

Si está interesado en recibir noticias puntuales por correo electrónico.
Puedes registrarte rellenando tu email suscripción de noticias.


+