Lenguaje de programación Go
5 de diciembre de 2024Hace 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
.
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.
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:
-
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
.
-
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 esnil
, lo que indica que se ha producido un error.
.
-
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.
-
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.
+