pointeri (* și &) în Go

Un pointer (*T) ține adresa unei variabile; prin el funcțiile pot modifica valoarea originală.

Sintaxă
p := &x      // adresa lui x, tip *int
*p = 10      // scrie în x prin pointer
var q *int   // nil
r := new(int)

Ce face pointeri (* și &)

Un pointer este o valoare care ține adresa unei variabile. &x dă adresa lui x, iar tipul ei este *T (de exemplu *int). *p înseamnă „valoarea de la adresa p”: o poți citi sau modifica. Valoarea zero a unui pointer este nil.

În Go argumentele se transmit prin copiere. Dacă o funcție trebuie să modifice o variabilă sau un struct al apelantului, primește un pointer. Tot cu pointeri se evită copierea struct-urilor mari. La struct-uri nu trebuie scris (*p).Camp: Go acceptă direct p.Camp.

Go nu are aritmetică pe pointeri (nu poți face p++) și are colector de memorie: poți returna liniștit adresa unei variabile locale (return &Cont{}), iar ea trăiește cât timp este folosită.

Exemple

Exemplul 1: Modificare prin pointer

dubleazaCopie primește o copie; dubleaza primește adresa, deci schimbă originalul.

package main

import "fmt"

func dubleazaCopie(n int) { n *= 2 }
func dubleaza(n *int)     { *n *= 2 }

func main() {
    puncte := 10
    dubleazaCopie(puncte)
    fmt.Println("după copie:", puncte)
    dubleaza(&puncte)
    fmt.Println("după pointer:", puncte)

    p := &puncte
    *p += 5
    fmt.Println("prin p:", puncte, "p == nil:", p == nil)
}

Rezultat

după copie: 10
după pointer: 20
prin p: 25 p == nil: false

Exemplul 2: Pointeri la struct și constructori

c.Sold funcționează direct pe pointer, fără (*c).Sold.

package main

import "fmt"

type Cont struct {
    Titular string
    Sold    float64
}

func ContNou(titular string) *Cont {
    return &Cont{Titular: titular} // adresa unei valori locale: corect în Go
}

func depune(c *Cont, suma float64) {
    c.Sold += suma
}

func main() {
    c := ContNou("Ana")
    depune(c, 250)
    depune(c, 100.5)
    fmt.Printf("%s are %.2f lei\n", c.Titular, c.Sold)

    var gol *Cont
    if gol == nil {
        fmt.Println("pointerul gol este nil; gol.Sold ar da panic")
    }
}

Rezultat

Ana are 350.50 lei
pointerul gol este nil; gol.Sold ar da panic

Greșeli frecvente

  • Folosirea unui pointer nil: panic: runtime error: invalid memory address or nil pointer dereference. Verifică p != nil.
  • Pointeri la slice-uri sau map-uri „ca să fie mai rapid”: ele conțin deja o referință internă; pointerul este rareori necesar.
  • Crezând că p++ mută pointerul: Go nu permite aritmetică pe pointeri.

Comenzi înrudite

  • new: Alocă o variabilă nouă și returnează un pointer la ea; primește un tip (valoare zero) sau, din Go 1.26, o expresie.
  • struct și struct-uri: Grupează mai multe câmpuri cu nume și tipuri diferite într-un singur tip; baza pentru modelarea datelor în Go.
  • metode: Funcții legate de un tip prin receptor; cu receptor pointer pot modifica valoarea pe care sunt apelate.
  • zero values (valori zero): Orice variabilă fără valoare inițială primește valoarea zero a tipului: 0, „”, false sau nil.