Skip to content

Listă recapitulativă limbaj Go

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 C, dar oferă: siguranța memoriei, GC (garbage collection), tipizare structurală și calcul concurent de tip 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"

Abreviere

msg := "Hello"

Constante

const Phi = 1.618

Constantele pot fi caractere, șiruri, valori booleane sau numerice.

Tipuri de bază

Șiruri de caractere (Strings)

str := "Hello"
str := `Multiline
string`

Tipul șirurilor de caractere este string.

Valori numerice

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("Value is", b)
}

func getPointer () (myPointer *int) {
  a := 234
  return &a
}

Pointerii indică locația de memorie a unei variabile. Go are un sistem complet de colectare a reziduurilor (garbage collection).

Tablouri (Arrays)

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

Dimensiunea tablourilor este fixă.

Slices (Secțiuni)

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

Spre deosebire de tablouri, secțiunile au o dimensiune dinamică.

Controlul fluxului

Condiție (If)

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

Instrucțiuni în if

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

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

Switch

switch day {
  case "sunday":
    // cazurile nu „merg mai departe” (fall through) implicit!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Funcții

Lambdas

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

Funcțiile sunt obiecte de primă clasă.

Tipuri de returnare multiple

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

Specificarea valorilor de returnare

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

Prin declararea numelor valorilor de returnare, 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 la fel.

Alias

import r "math/rand"

r.Intn()

Numele de apel (Exported names)

func Hello () {
  ···
}

Numele exportate încep cu literă mare.

Pachete

package hello

Fiecare fișier de pachet trebuie să înceapă cu declarația package.

Concurență

Goroutines

func main() {
  // Un „canal” (channel)
  ch := make(chan string)

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

  // Citirea a 3 rezultate
  // (Deoarece goroutine-urile noastre 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 tampon (Buffered Channels)

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

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

Închiderea canalului

Închide un canal

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

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

for i := range ch {
  ···
}

Închis dacă ok == false

v, ok := <- ch

Controlul erorilor

Defer (Amânare)

func main() {
  defer fmt.Println("Done")
  fmt.Println("Working...")
}

Amână rularea unei funcții până când funcția care o conține returnează. Parametrii sunt evaluați imediat, dar apelul funcției nu rulează până la sfârșit.

Funcții amânate

func main() {
  defer func() {
    fmt.Println("Done")
  }()
  fmt.Println("Working...")
}

Lambdas sunt mai potrivite pentru blocurile defer.

Structuri (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}

Puteți introduce, de asemenea, numele câmpurilor.

Pointeri către structuri

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

Când v este un pointer, execuția v.X este aceeași cu (*v).X.

Metode

Receptor (Receiver)

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 folosi un receptor pentru a defini funcții.

Modificare (Pointer receiver)

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