Saltar al contenido

Qué es Go y tu primer programa

Al terminar esta lección vas a poder escribir un programa completo en Go, entender para qué sirve cada una de sus líneas y usar funciones de otros paquetes. También vas a saber leer dos errores que el compilador muestra a menudo: un paquete importado que no se usa y un nombre escrito con minúscula.

Qué es Go

Go es un lenguaje de programación: una forma de escribir instrucciones que una computadora puede ejecutar. Es de código abierto (cualquiera puede leer y usar su código), nació en Google y se publicó en 2009. Hoy se usa mucho para programas que corren en servidores de internet y para herramientas que se usan desde la terminal.

Tres características lo definen, y las vas a notar desde el primer programa:

  • Es compilado. Antes de ejecutar tu programa, otro programa, el compilador, lo lee completo y lo traduce a instrucciones que la computadora ejecuta directamente. Si encuentra un error, se detiene y no se ejecuta ninguna línea.
  • Tiene tipado estático. Cada valor tiene un tipo: por ejemplo, un texto, un número entero o un número con decimales. Antes de ejecutar, el compilador revisa que cada valor se use como su tipo lo permite: no te deja multiplicar un texto por un número. Los tipos los verás en la lección Variables y valores cero.
  • Tiene recolector de basura (en inglés, garbage collector). Mientras corre, tu programa usa memoria para guardar sus datos. Cuando un dato ya no se usa, Go libera esa memoria por su cuenta: no tienes que escribir nada para eso.

En este curso, el compilador oficial de Go corre dentro de tu navegador. En los ejercicios, el botón Ejecutar primero compila tu programa y, si no hay errores, lo ejecuta.

Si vienes de JavaScript, Python o Java…

En Python y JavaScript no compilas el programa antes de ejecutarlo: un error de tipos aparece solo cuando se ejecuta la línea que lo tiene. En Go, el compilador lo encuentra antes de que se ejecute cualquier línea.

Java también compila, pero a un código intermedio (bytecode) que necesita la máquina virtual de Java para correr. Go compila a código de máquina: un archivo ejecutable que corre sin tener Go instalado. En este sitio, como el compilador corre en el navegador, compila a WebAssembly, un formato que el navegador sabe ejecutar.

La memoria, en cambio, funciona como en los tres: la libera un recolector de basura.

Tu primer programa

Este es un programa completo en Go. Como manda la tradición, el primero saluda al mundo:

main.go
package main

import "fmt"

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

Salida:

¡Hola, mundo!

Debajo del código ves la salida: lo que el programa imprimió al ejecutarse. En programación, imprimir es mostrar texto en la salida, no en papel. Lo impreso es exactamente el texto que está entre las comillas dobles, ¡Hola, mundo!, sin las comillas. Un texto entre comillas dobles es un string (un valor de texto): Go lo usa tal cual, con sus tildes, signos y espacios.

fmt.Println muestra en la salida lo que le pasas entre los paréntesis, en una línea. Lo veremos en la lección Salida y entrada con fmt.

Las otras líneas no imprimen nada, pero todo programa en Go las necesita. Las vas a ver una por una en las secciones que siguen:

  • package main dice que este archivo es un programa.
  • import "fmt" trae el paquete fmt, que es donde está Println. Un paquete es un grupo de código con nombre.
  • func main() y sus llaves encierran lo que hace el programa.

package main y func main

Un programa puede imprimir tantas líneas como quieras. Este imprime el cartel de una papelería:

main.go
package main

import "fmt"

// main es donde empieza el programa.
func main() {
	fmt.Println("Papelería Central")
	fmt.Println("Abierto de lunes a sábado")
	fmt.Println("¡Te esperamos!")
}

Salida:

Papelería Central
Abierto de lunes a sábado
¡Te esperamos!

Las tres líneas salen en el mismo orden en que están escritas. Así funciona main: cuando ejecutas el programa, Go ejecuta las instrucciones de func main una por una, de arriba abajo. Al llegar a la llave de cierre, el programa termina.

Cada parte tiene su función:

  • package main va al principio del archivo. Todo archivo de Go pertenece a un paquete, y el paquete main es el que se puede ejecutar como programa.
  • func main() declara la función main. Una función es un bloque de código con nombre, y main es especial: es la que Go ejecuta al iniciar el programa. Sus instrucciones van entre las llaves { y }. Cómo escribir tus propias funciones lo verás en la lección Funciones.
  • La línea que empieza con // es un comentario: una nota para quien lee el código, que Go ignora. Los ejercicios usan comentarios para marcar dónde escribir.

La regla: un programa en Go necesita package main y una func main, y lo que pones dentro de main se ejecuta en orden.

La llave { va al final de la línea de func main(), como en los ejemplos. No es cuestión de gusto: si la pasas a la línea siguiente, el programa no compila.

Consejo

Escribe tu código con la forma de los ejemplos: sangría con tabulador y una instrucción por línea. Es el formato oficial de Go, el que deja la herramienta gofmt, y cualquier persona que programa en Go lo lee sin esfuerzo.

Paquetes e imports

Un paquete agrupa código relacionado. Go trae una biblioteca estándar con muchos paquetes listos para usar. fmt es uno; strings, con funciones para trabajar con textos, es otro:

main.go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println("papelería central")
	fmt.Println(strings.ToUpper("papelería central"))
}

Salida:

papelería central
PAPELERÍA CENTRAL

Usar una función se dice llamarla: escribes su nombre y, entre paréntesis, lo que le pasas. strings.ToUpper recibe un texto y devuelve el mismo texto en mayúsculas, tildes incluidas: papelería central pasa a ser PAPELERÍA CENTRAL. Como esa llamada está dentro de los paréntesis de fmt.Println, Go primero obtiene el texto en mayúsculas y después fmt.Println lo imprime.

Para usar un paquete, lo importas con import y su nombre entre comillas dobles. Si son dos o más, lo habitual es agruparlos entre paréntesis, uno por línea. Después usas lo que trae con el nombre del paquete, un punto y el nombre de lo que necesitas: strings.ToUpper.

Si importas un paquete y no lo usas, el programa no compila. Aquí sobra strings:

main.go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println("papelería central")
}

Salida:

./main.go:5:2: "strings" imported and not used

Lee el mensaje por partes:

  • ./main.go:5:2 es el lugar: archivo main.go, línea 5, columna 2. En la línea 5 está "strings", y el tabulador de la sangría cuenta como la columna 1.
  • "strings" imported and not used dice el problema: importaste strings y no lo usas.

Para corregirlo, usa el paquete o borra su línea del import. Go es estricto con esto a propósito: un import que sobra hace más lenta la compilación y confunde a quien lee el código.

Consejo

Agrupa todos los imports en un solo bloque entre paréntesis. El orden no cambia nada para el compilador; por convención van en orden alfabético, que es como los deja gofmt.

Si vienes de JavaScript, Python o Java…

En Python, JavaScript y Java, un import que no usas es como mucho una advertencia del editor. En Go es un error: el programa no compila hasta que lo usas o lo borras.

Nombres exportados

Fíjate en cómo se escriben los nombres que usas de otros paquetes:

main.go
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Repeat("=", 17))
	fmt.Println(strings.ToUpper("papelería central"))
	fmt.Println(strings.Repeat("=", 17))
}

Salida:

=================
PAPELERÍA CENTRAL
=================

strings.Repeat recibe un texto y un número, y devuelve el texto repetido esa cantidad de veces: strings.Repeat("=", 17) da diecisiete signos =, el mismo ancho que PAPELERÍA CENTRAL.

Println, ToUpper y Repeat empiezan con mayúscula, y no es casualidad. En Go, un nombre que empieza con mayúscula está exportado: se puede usar desde otros paquetes. Un nombre que empieza con minúscula solo se puede usar dentro de su propio paquete.

main va con minúscula porque Go exige ese nombre exacto. Tampoco necesita estar exportada: ningún otro paquete la usa, Go la ejecuta por su cuenta.

Si escribes println con minúscula, el programa no compila:

main.go
package main

import "fmt"

func main() {
	fmt.Println("Papelería Central")
	fmt.println("Abierto de lunes a sábado")
}

Salida:

./main.go:7:6: undefined: fmt.println (but have Println)

Lee el mensaje por partes:

  • ./main.go:7:6: archivo main.go, línea 7, columna 6, justo donde empieza println.
  • undefined: fmt.println significa “no definido”: Go no encuentra ningún println entre los nombres que exporta fmt.
  • (but have Println) significa “pero tiene Println”: Go te sugiere el nombre que sí existe.

Fíjate en que la salida no muestra Papelería Central, aunque esa línea estaba bien. Es lo que viste al principio: Go es compilado, y con un error en cualquier línea no se ejecuta ninguna.

Para corregirlo, escribe fmt.Println. Go distingue mayúsculas de minúsculas en todos los nombres: println, Println y PrintLn son tres nombres distintos.

Tampoco sirve borrar el fmt.: println, sin fmt., es otra función. Viene integrada en Go para casos especiales y escribe en otro lugar, la salida de errores, que los ejercicios no revisan.

Consejo

Si no recuerdas cómo se escribe un nombre, búscalo en la documentación oficial de su paquete, por ejemplo pkg.go.dev/strings. Ahí aparece todo lo que el paquete exporta, con sus mayúsculas exactas.

Si vienes de JavaScript, Python o Java…

En Java decides quién puede usar un nombre con public o private. En Go no hay palabras para esto: decide la primera letra, y el compilador lo hace cumplir. Un nombre con minúscula se parece más a la visibilidad de paquete de Java (sin modificador) que a private: lo usa todo el código de su paquete.

En JavaScript, un módulo comparte solo lo que marcas con export. En Python, un guion bajo al inicio (_precio) avisa que algo es interno, pero nada impide usarlo.

En resumen

  • Go es compilado y tiene tipado estático: el compilador revisa el programa completo antes de ejecutar una sola línea. La memoria la libera el recolector de basura.
  • Todo programa empieza con package main, y lo que escribes en func main se ejecuta en orden, de arriba abajo.
  • Para usar un paquete, lo importas con import. Cada import tiene que usarse.
  • De otro paquete solo puedes usar los nombres que empiezan con mayúscula: los exportados.
  • Un error del compilador se lee por partes: primero el lugar (archivo:línea:columna) y después qué pasó.

Ejercicios

Debajo de Papelería Central, imprime Cuadernos, lápices y más en otra línea.

  main.go

Para salir del editor con el teclado, pulsa Escape y luego Tab.

package main

import "fmt"

func main() {
	fmt.Println("Papelería Central")
	// Escribe aquí la segunda línea.
}
 

¿Ver la solución?

La solución reemplazará tu código en el editor. Antes de verla, prueba con una pista: se aprende más cuando lo resuelves tú.