close în Go

Închide un canal: anunță că nu se mai trimit valori; range se oprește, iar primirea dă ok == false.

Sintaxă
func close(c chan<- Type)

close(c)
v, ok := <-c   // ok == false după close și golirea buffer-ului

Ce face close

close(c) marchează canalul ca închis. Valorile deja aflate în buffer se pot citi în continuare; după ce buffer-ul se golește, orice primire returnează imediat valoarea zero a tipului, iar în forma v, ok := <-c, ok este false. Bucla for v := range c se oprește singură.

Doar expeditorul ar trebui să închidă canalul, o singură dată, când a terminat de trimis. Închiderea nu este obligatorie: un canal neînchis este eliberat oricum de colectorul de memorie. Se închide doar când destinatarul trebuie să afle că nu mai vin date. Un canal închis este și un semnal pentru mai multe goroutine deodată: toate cele care așteaptă pe <-c se deblochează.

Parametri

Parametru Descriere
c Un canal bidirecțional sau doar pentru trimitere (chan<- T).

Exemple

Exemplul 1: Valorile din buffer rămân disponibile

package main

import "fmt"

func main() {
    c := make(chan int, 3)
    c <- 10
    c <- 20
    close(c)

    v, ok := <-c
    fmt.Println(v, ok)
    v, ok = <-c
    fmt.Println(v, ok)
    v, ok = <-c // buffer gol și canal închis
    fmt.Println(v, ok)
}

Rezultat

10 true
20 true
0 false

Exemplul 2: Semnal de oprire pentru mai multe goroutine

close(stop) deblochează toți lucrătorii deodată; fiecare raportează în propria poziție, iar afișarea este în ordine.

package main

import (
    "fmt"
    "sync"
)

func main() {
    stop := make(chan struct{})
    stari := make([]string, 3)
    var wg sync.WaitGroup
    for i := range 3 {
        wg.Add(1)
        go func() {
            defer wg.Done()
            <-stop // așteaptă semnalul
            stari[i] = fmt.Sprintf("lucrătorul %d s-a oprit", i+1)
        }()
    }
    close(stop)
    wg.Wait()
    for _, s := range stari {
        fmt.Println(s)
    }
}

Rezultat

lucrătorul 1 s-a oprit
lucrătorul 2 s-a oprit
lucrătorul 3 s-a oprit

Greșeli frecvente

  • Trimitere după close: panic: send on closed channel.
  • Închiderea de două ori: panic: close of closed channel.
  • close pe un canal nil: panic: close of nil channel.
  • Închiderea unui canal doar pentru primire (<-chan T): invalid operation: cannot close receive-only channel.

Comenzi înrudite

  • chan și canale (channels): Canalele (chan) transmit valori între goroutine în siguranță și le sincronizează; se creează cu make.
  • select: Așteaptă mai multe operații pe canale deodată și o execută pe prima care este gata; cu default nu blochează.
  • go și goroutine: Cuvântul go pornește o funcție într-o goroutine: un fir de execuție ușor, care rulează în paralel cu restul programului.
  • range: Parcurge într-un for elementele unui slice, array, map, text, canal, număr sau iterator.