Skip to content

Go Programación Cheat Sheet

Go (también conocido como Golang) es un lenguaje compilado de tipado estático desarrollado por Robert Griesemer, Rob Pike y Ken Thompson en Google. La sintaxis de Go es similar a C, pero presenta seguridad de memoria, GC (recolección de basura), tipado estructural y concurrencia estilo CSP.

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

Variables

Declaración de variables

var msg string
msg = "Hello"

Abreviatura

msg := "Hello"

Constantes

const Phi = 1.618

Las constantes pueden ser caracteres, cadenas, booleanos o valores numéricos.

Tipos Básicos

Cadenas (Strings)

str := "Hello"
str := `Multilínea
cadena`

El tipo para las cadenas es string.

Números

Tipos típicos

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (alias para uint8)

Otros tipos

var u uint = 7        // uint (sin signo)
var p float32 = 22.7  // float de 32 bits

Punteros

func main () {
  b := *getPointer()
  fmt.Println("El valor es", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

Los punteros apuntan a una ubicación de memoria de una variable. Go tiene recolección de basura completa.

Arreglos (Arrays)

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

Los arreglos tienen un tamaño fijo.

Slices (Segmentos)

slice := []int{2, 3, 4}
slice := []byte("Hello")

A diferencia de los arreglos, los slices tienen un tamaño dinámico.

Control de Flujo

Condicionales

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

Declaración en if

if _, err := getResult(); err != nil {
  fmt.Println("Uh oh")
}

Una declaración if puede ejecutar una declaración simple antes de la expresión condicional.

Switch

switch day {
  case "sunday":
    // ¡los casos no "fallan" (fall through) por defecto!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Funciones

Lambdas

myfunc := func() bool {
  return x > 10000
}

Las funciones son objetos de primera clase.

Múltiples tipos de retorno

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

Valores de retorno nombrados

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

Al nombrar los valores de retorno en la declaración, return (sin argumentos) devolverá las variables con esos nombres.

Paquetes (Packages)

Carga

import "fmt"
import "math/rand"
import (
  "fmt"        // proporciona fmt.Println
  "math/rand"  // proporciona rand.Intn
)

Ambos son iguales.

Alias

import r "math/rand"
 
r.Intn()

Nombres Exportados

func Hello () {
  ···
}

Los nombres exportados comienzan con una letra mayúscula.

Paquetes

package hello

Cada archivo de paquete debe comenzar con una declaración package.

Concurrencia

Goroutines

func main() {
  // Un "canal"
  ch := make(chan string)

  // Iniciar rutinas concurrentes
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Leer 3 resultados
  // (Dado que nuestras goroutines son concurrentes,
  // ¡el orden no está garantizado!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

Los canales son objetos de comunicación seguros para la concurrencia utilizados en goroutines.

Canales con Búfer

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// error fatal:
// all goroutines are asleep - deadlock!

Los canales con búfer limitan la cantidad de mensajes que pueden contener.

Cerrar Canales

Cierra un canal

ch <- 1
ch <- 2
ch <- 3
close(ch)

Iterar un canal hasta que se cierre

for i := range ch {
  ···
}

Cerrado si ok == false

v, ok := <- ch

Defer & Panic

Defer

func main() {
  defer fmt.Println("Hecho")
  fmt.Println("Trabajando...")
}

Retrasa la ejecución de una función hasta que la función circundante retorna. Los argumentos se evalúan inmediatamente, pero la llamada a la función no se ejecuta hasta el final.

Defer con Lambdas

func main() {
  defer func() {
    fmt.Println("Hecho")
  }()
  fmt.Println("Trabajando...")
}

Las lambdas son mejores para bloques diferidos.

Estructuras (Structs)

Definición

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

Literales

v := Vertex{X: 1, Y: 2}
// Los nombres de los campos se pueden omitir
v := Vertex{1, 2}
// Y es implícito
v := Vertex{X: 1}

También puede especificar nombres de campos.

Punteros a Estructuras

v := &Vertex{1, 2}
v.X = 2

Cuando v es un puntero, v.X y (*v).X son lo mismo.

Métodos

Receptores (Receivers)

type Vertex struct {
  X, Y float64
}
func (v Vertex) Abs() float64 {
  return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
 
v := Vertex{1, 2}
v.Abs()

No hay clases, pero puede definir funciones en tipos usando receptores.

Receptores de Puntero

func (v *Vertex) Scale(f float64) {
  v.X = v.X * f
  v.Y = v.Y * f
}
 
v := Vertex{6, 12}
v.Scale(0.5)
// `v` se actualiza