Skip to content

Go Programming Language Cheat Sheet

Go (cunoscut și sub numele de Golang) este un limbaj compilat, tipizat static, dezvoltat de Robert Griesemer, Rob Pike și Ken Thompson la Google. Sintaxa Go este similară cu cea a limbajului C, dar oferă: siguranță a memoriei, GC (Garbage Collection), tipizare structurală și concurență în stil 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

Variabile

Declararea variabilelor

var msg string
msg = "Hello"

Formă scurtă

msg := "Hello"

Constante

const Phi = 1.618

Constantele pot fi caractere, șiruri de caractere, valori booleene sau numerice.

Tipuri de bază

Șiruri de caractere (Strings)

str := "Hello"
str := `Șir pe
mai multe linii`

Tipul pentru șiruri este string.

Numere

Tipuri tipice

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

Alte tipuri

var u uint = 7        // uint (fără semn)
var p float32 = 22.7  // float pe 32 de biți

Pointeri

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

Pointerii indică o locație de memorie a unei variabile. Go are management automat al memoriei (Garbage Collection).

Array-uri

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

Array-urile au o dimensiune fixă.

Slice-uri

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

Spre deosebire de array-uri, slice-urile au o dimensiune dinamică.

Controlul fluxului

Condiționale (If)

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

Instrucțiune în if

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

O instrucțiune if poate executa o instrucțiune simplă înainte de expresia condițională.

Switch

switch day {
  case "sunday":
    // case-urile nu continuă implicit (fall through)!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Funcții

Lambdas (Funcții anonime)

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

Funcțiile sunt obiecte de primă clasă.

Tipuri de return multiple

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

Valori de return numite

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

Numind valorile de return în declarație, return (fără argumente) va returna variabilele cu acele nume.

Pachete (Packages)

Încărcare

import "fmt"
import "math/rand"
import (
  "fmt"        // oferă fmt.Println
  "math/rand"  // oferă rand.Intn
)

Ambele sunt identice.

Alias-uri

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

Nume exportate

func Hello () {
  ···
}

Numele exportate încep cu literă mare.

Pachete

package hello

Fiecare fișier de pachet trebuie să înceapă cu instrucțiunea package.

Concurență

Goroutines

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

  // Pornirea rutinelor concurente
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Citire 3 rezultate
  // (Deoarece goroutine-urile sunt concurente,
  // ordinea nu este garantată!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

Canalele sunt obiecte de comunicare sigure pentru concurență utilizate în goroutine-uri.

Canale cu buffer (Buffered Channels)

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

Canalele cu buffer limitează numărul de mesaje pe care le pot reține.

Închiderea canalelor

Închide un canal

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

Iterarea printr-un canal până când este închis

for i := range ch {
  ···
}

Închis dacă ok == false

v, ok := <- ch

Defer & Panic

Defer

func main() {
  defer fmt.Println("Gata")
  fmt.Println("Lucrăm...")
}

Amână executarea unei funcții până când funcția în care se află returnează. Argumentele sunt evaluate imediat, dar apelul funcției nu este executat până la final.

Defer cu Lambdas

func main() {
  defer func() {
    fmt.Println("Gata")
  }()
  fmt.Println("Lucrăm...")
}

Lambdas sunt mai potrivite pentru blocurile amânate.

Structs

Definiție

type Vertex struct {
  X int
  Y int
}

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

Literali

v := Vertex{X: 1, Y: 2}
// Numele câmpurilor pot fi omise
v := Vertex{1, 2}
// Y este implicit
v := Vertex{X: 1}

De asemenea, puteți specifica numele câmpurilor.

Pointeri către Structs

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

Când v este un pointer, v.X și (*v).X sunt același lucru.

Metode

Receptori (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()

Nu există clase, dar puteți defini funcții pe tipuri utilizând receptori.

Receptori Pointer

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` este actualizat