Go (cunoscut inițial ca Golang) este un limbaj de programare open-source dezvoltat de Google, conceput pentru a fi simplu, rapid și eficient în execuție. În practică, el este standardul de facto pentru infrastructura cloud, microservicii și tool-uri de linie de comandă datorită compilării statice și gestionării automate a memoriei. Aflarea lui îți deschide ușa către roluri bine plătite în companii tech mari, unde performanța și scalabilitatea sunt critice. Spre deosebire de limbaje mai vechi, Go pune accent pe productivitatea dezvoltatorului și pe mentenabilitatea codului la scară largă.

Concepte cheie

  • Gorutine: Sunt fire de execuție (threads) foarte ușoare, gestionate de runtime-ul Go, care permit scrierea de cod concurent fără complexitatea firelor de sistem tradiționale.
  • Chanale (Channels): Mecanismul principal de comunicare între gorutine, bazat pe principiul „nu comunica prin partajarea memoriei, ci partajează memoria comunicând”.
  • Interfețe: O abordare duck-typing unde o structură implementează o interfață implicit, dacă are toate metodele definite, facilitând polimorfismul fără moștenire clasică.
  • Pachete și Module: Go organizează codul în pachete clare, iar dependențele sunt gestionate explicit prin go.mod, asigurând reproducibilitatea builds-urilor.
  • Gestionarea erorilor: Go nu folosește excepții (try/catch); erorile sunt valori returnate explicit, ceea ce forțează dezvoltatorul să le trateze la sursă.
  • Structuri și Metode: Go nu are clase; în schimb, definești structuri și atașezi metode acestora, oferind un model orientat-obiect minimalist.

Exemplu practic

Să presupunem că vrem să simulăm procesarea simultană a unor cereri web simple. Folosim gorutine pentru a nu bloca thread-ul principal și chanale pentru a colecta rezultatele.

package main

import (
    "fmt"
    "time"
)

func processTask(id int, resultCh chan<- string) {
    // Simulează o operație asincronă
    time.Sleep(time.Second)
    resultCh <- fmt.Sprintf("Task %d finalizat", id)
}

func main() {
    ch := make(chan string, 3) // Buffer de 3

    // Lansăm 3 gorutine
    for i := 1; i <= 3; i++ {
        go processTask(i, ch)
    }

    // Așteptăm rezultatele
    for i := 0; i < 3; i++ {
        fmt.Println(<-ch)
    }
}

Acest exemplu arată cum go lansează funcția în paralel, iar canalul ch sincronizează ieșirea, prevenind race conditions.

Greșeli frecvente

  1. Ignorarea erorilor: Utilizarea _ pentru a ignora valorile de eroare returnate de funcții poate ascunde bug-uri critice.
  2. Race Conditions: Accesul necontrolat la variabile partajate între gorutine fără mutex-uri (sync.Mutex) sau chanale duce la comportament nedefinit.
  3. Abuzul de Gorutine: Crearea a mii de gorutine fără limitare poate epuiza memoria; este preferabilă folosirea unui worker pool.
  4. Confuzia între slice și array: Slice-urile sunt referințe la un array subiacent; copierea lor superficială poate duce la modificări neașteptate ale datelor originale.

Întrebări de interviu

1. Care este diferența dintre un channel buffered și unul non-buffered? Un channel non-buffered blochează emitentul până când receptorul preia valoarea (sincron strict). Unul buffered permite emitentului să continue dacă buffer-ul nu este plin, decuplând ușor producția de consum.

2. De ce Go nu are excepții? Pentru a menține controlul fluxului explicit și predictibil. Tratarea erorilor ca valori normale simplifică debugging-ul și evită stiva de apeluri masivă generată de excepții nestocate.

3. Ce face funcția defer? Amână execuția unei funcții până când funcția care o apelează se termină. Este esențial pentru curățarea resurselor (închiderea fișierelor, deblocarea mutex-urilor).

Exercițiu

Creează un program Go care citește un fișier text mare și numără frecvența fiecărui cuvânt. Implementează această logică folosind gorutine: una pentru citirea fișierului și scrierea cuvintelor într-un channel, și alta pentru citirea din channel și actualizarea unui map cu contoare. Folosește sync.WaitGroup pentru a aștepta finalizarea corectă. Timp estimat: 45 minute.

Resurse gratuite

Subteme