Gomic y primeras impresiones sobre Go

Unos 7 minutos de lectura Publicado:

Go, también llamado golang, es un lenguaje de programación diseñado por Google. Es de tipado estático, compilado y similar a C. Algunas diferencias con este son que tiene protección de memoria, recolector de basura y concurrencia nativa. Este articulo tiene dos fines, enseñar lo bonico que me ha quedado un programa que he hecho en go y plasmar mis impresiones sobre mi primera incursión en este lenguaje.

Empecemos por el principio. Hace un tiempo decidí que quería hacer un programa que descargase imágenes y las mostrase como una galería en un servidor web tonto. No iban a ser unas imágenes cualquiera, en un principio quería que fuesen los cómics que hace Julia Evans (recomiendo muy fuerte echarle un ojo a su blog). Mediante cómics explica conceptos y herramientas tecnológicas con un estilo muy interesante. Quería poder ver uno de ellos de forma aleatoria, visitando una página web. Me parecía interesante por que hay veces que en el trabajo tengo cinco minutos muertos mientras espero que se ejecute alguna CI, y me parece que aprender cosas que no se suelen buscar es una forma útil de usar ese tiempo.

Tenia pensado hacerlo en python, por que ya he tocado alguna cosilla en flask. El proceso lo tenia claro. Hacia falta un fichero con la lista de las imágenes a descargar. Una vez descargadas, habría que lanzar un servidor web que mediante templates de html, renderizaria una página con las imágenes. Teniendo tan claro lo que habia que hacer, decidí hacerlo en algún otro lenguaje for the lulz.

Go es un lenguaje por el que siento curiosidad desde hace un tiempo. Muchas de las tecnologías que he estado usando el último año están hechas en go, como por ejemplo docker, kubernetes, terraform o prometheus. Y alguna vez me he encontrado algún funcionamiento fuera de lo normal y no he sabido determinar si era un bug o cosa mia, y si hubiese sabido algo de go me habría venido bien.

Como el fin de semana pasado estaba malo y no podía hacer mucho, decidí darle al tema. Y salió gomic.daemons.it.

No entraré en detalles de como se hace nada, porqué el código del programa está muy comentado. De lo que hablaré es de las cosas de este lenguaje que me han llamado la atención (sobretodo en comparación con python) y las cosas que me han gustado del proyecto.

Disclaimer: Mis conocimientos de programación son limitados, por lo que es probable que suelte alguna burrada.

  • Lenguaje compilado: Esto lo ves nada más empezar a leer sobre go. Lo que no ves de primeras es que no es necesario compilar. Es recomendable y deberías crear binarios, pero para desarrollar puedes usar go run . y se ejecuta del tirón. Incluso se pueden hacer scripts en go. Hay formas de hacerlo, más o menos estándar, aquí hablan más del tema. Pero si a este script se le da permisos de ejecución y se ejecuta con ./script.go, funciona sin más:
//usr/bin/go run $0; exit
package main
import "fmt"
func main () {fmt.Println("Holi")}
  • Declarar tipo de variable VS asignar valor a una variable: No se si es así en otros lenguajes de tipado estático, pero en go se puede hacer de ambas formas:
var variable "holi"
variable := "holi"
  • El módulo de logueo: Como se ve aquí, se usa del tirón. Esto es algo que en python siempre me ha molestado mucho, para loguear tienes que hacer movidas muy raras. En go puedes usar log.Println para loguear a nivel info y log.Fatal para errores. Hasta se encarga de parar el programa al haber detectado un error fatal.

  • Docker friendly: Una cosa muy interesante que tiene go, a diferencia de java por ejemplo, es que puedes compilar binarios dinámicos o estáticos. La diferencia básica es que el primero solo funcionará en un SO con las mismas características que en el que se ha compilado (es decir, mismas librerías), y el segundo en cualquiera. Mola por que si lo compilas estáticamente, no hace falta nada más. Y cuando digo nada más es literalmente nada más, se puede usar la imagen scratch para crear la imagen. Por comparar, veamos el tamaño de la imagen de drone-xmpp (python) comparado con la de gomic:

r.daemons.it/gomic                   9.24MB
r.daemons.it/drone-xmpp              139MB

Es normal la diferencia. La imagen de gomic solo tiene un binario y un par de htmls, css y js. En cambio la de drone-xmpp tiene alpine, que aún siendo un SO muy pequeño, sigue siendo mucho más que nada.

  • Linter chulo: Emacs tiene un paquete de linters llamado flycheck. He intentado sacar como funciona por debajo para dar una visión más general para quien no use emacs, pero no he sido capaz. Si alguien lo sabe, que comente. El motivo por el que me ha gustado tanto es que es capaz de decirte que no puedes asignar la variable a de tipo string al valor 1 por que este un integer. Parece algo como muy tonto, pero me sorprende mucho tener un análisis estático del código en tiempo real y que no consume recursos de forma aparente.

  • Control de error obligatorio (casi): Según he visto en muchas de las funciones que he usado suelen obligan a controlar el error. Por ejemplo:

file, err := os.Create(filePath)
if err != nil {
	log.Print("error creating " + filePath)
	log.Print(err)
}

Por que digo que es obligatorio (o casi)? os.Create devuelve la descripción del fichero (file descriptor, creo que se traduce así) y un objeto de error (vacío si no existe). Al devolverlo la función, hay que asignar a ambos valores una variable. Si una variable no es usada en go, el programa no compila. Y ale, de esta forma tan tonta te obligan a tener que hacer algo con esta variable, lo normal seria usarla para comprobar que no hay ningún error. Hay formas de usar la variable para saltarse el bloqueo sin que sea útil, pero la excusa de hacer eso es más bien pequeña.

  • repl: Gore es un repl, puedes hacer pruebas rápidas con ello.

  • Paquetes nativos muy potentes: Como se puede ver si se lee el código, no he tenido que usar ningún paquete externo para el programa. En un principio usé grab para descargar ficheros, pero realmente no me aportaba demasiado. Además, no dejaba escoger que nombre le ponía al fichero, lo cual es un problema. Pero seguramente lo que llama más la atención es que el servidor http nativo sea tan potente. O igual no es tan sorprendente, si tenemos en cuenta que go se usa mucho para la generación de apis.

  • Tipos de datos: Esto fue de lo que más me costó entender, aunque no tengo claro haberlo entendido del todo. Al ser tipado estático, tienes que saber exactamente el tipo de todas las variables, por ejemplo al hacer un return de una función. Me encontré con que no podía convertir estructuras (struct, que se llama) a tipos simples, como es un string o un integer. En realidad no sabia por que no podía, el tema de las estructuras lo descubrí después de muchas horas. Concretamente, lo que estaba haciendo era intentar convertir el tipo os.FileInfo a string. Y claro, no encontraba por internet la forma de hacerlo, por que, salvando las distancias, es como si intentase convertir una clase de python en un string. Sentido cero. Al final era mucho más simple, como solo me interesaba el atributo Nombre, solo habia que acceder al atributo de una forma intuitiva, con os.FileInfo.Name().

  • Muy buena documentación: La documentación está muy bien escrita y muchas veces tiene incluso ejemplos.

  • Bulma: Esto no tiene que ver con go directamente, pero lo cuento igual por que mola. Cuando hice la primera iteración del programa, la interfaz era esta.

Se lo enseñe a Ameba y como cualquier persona con ojos, se sintió muy ofendida por el “diseño”. Por ello, hizo una primera implementación de bulma, un framework CSS como lo es bootstrap. Viendo que se habia tomado la molestia, por sentido de la vergüenza y por que en realidad soy consciente de que la UX es importante, decidí terminar de implementarlo (con mucha ayuda) y aprender bastante de conceptos básicos de html, css y js, que siempre voy muy pez. Y ha quedado algo más cuqui, como se puede ver en la primera imagen.

Poco más que añadir. Go me parece un lenguaje interesante y probablemente siga aprendiendo porque hace ya tiempo que quiero tener algún otro lenguaje a parte de python. Es improbable que Gomic reciba muchas más actualizaciones más allá de añadir más orígenes, pero cualquier sugerencia siempre será bienvenida.

Cualquier duda, se puede preguntar aquí o en los canales descritos en la página principal. Saludos.