Els canals són una característica fonamental de Go que permet la comunicació segura entre goroutines. Els canals proporcionen una manera de sincronitzar l'execució i compartir dades sense necessitat d'utilitzar mutexes o altres mecanismes de sincronització complexos.

Conceptes Clau

  1. Creació de Canals: Els canals es creen utilitzant la funció make.
  2. Enviament i Recepció: Els canals permeten enviar i rebre dades entre goroutines.
  3. Canals Buferejats i No Buferejats: Els canals poden ser buferejats (amb una capacitat definida) o no buferejats (sense capacitat).
  4. Tancament de Canals: Els canals es poden tancar per indicar que no s'enviaran més dades.

Creació de Canals

Els canals es creen amb la funció make, especificant el tipus de dades que transportaran.

ch := make(chan int) // Canal no buferejat que transporta enters

Per crear un canal buferejat, es pot especificar la capacitat com a segon argument.

ch := make(chan int, 5) // Canal buferejat amb capacitat per a 5 enters

Enviament i Recepció de Dades

Enviament

Per enviar dades a un canal, s'utilitza l'operador <-.

ch <- 42 // Envia el valor 42 al canal ch

Recepció

Per rebre dades d'un canal, també s'utilitza l'operador <-.

value := <-ch // Rep un valor del canal ch i l'assigna a la variable value

Exemple Pràctic

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)

    // Goroutine que envia dades al canal
    go func() {
        ch <- 42
    }()

    // Recepció de dades del canal
    value := <-ch
    fmt.Println(value) // Imprimeix: 42
}

Canals Buferejats

Els canals buferejats permeten enviar múltiples valors sense necessitat que hi hagi una goroutine receptora immediatament disponible.

Exemple Pràctic

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 2)

    ch <- 1
    ch <- 2

    fmt.Println(<-ch) // Imprimeix: 1
    fmt.Println(<-ch) // Imprimeix: 2
}

Tancament de Canals

Els canals es poden tancar per indicar que no s'enviaran més dades. Això es fa amb la funció close.

Exemple Pràctic

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 2)

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

    for value := range ch {
        fmt.Println(value)
    }
}

Exercicis Pràctics

Exercici 1: Comunicació Bàsica

Crea un programa que utilitzi un canal per enviar un missatge des d'una goroutine a la goroutine principal.

Solució

package main

import (
    "fmt"
)

func main() {
    ch := make(chan string)

    go func() {
        ch <- "Hola, món!"
    }()

    msg := <-ch
    fmt.Println(msg) // Imprimeix: Hola, món!
}

Exercici 2: Canal Buferejat

Crea un programa que utilitzi un canal buferejat per enviar i rebre múltiples valors.

Solució

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 3)

    ch <- 1
    ch <- 2
    ch <- 3

    fmt.Println(<-ch) // Imprimeix: 1
    fmt.Println(<-ch) // Imprimeix: 2
    fmt.Println(<-ch) // Imprimeix: 3
}

Exercici 3: Tancament de Canals

Crea un programa que tanqui un canal després d'enviar diversos valors i utilitzi un bucle range per rebre'ls.

Solució

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 3)

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

    for value := range ch {
        fmt.Println(value)
    }
}

Errors Comuns i Consells

  1. Enviar a un Canal Tancat: Intentar enviar dades a un canal tancat provoca un pànic. Assegura't de no enviar dades després de tancar el canal.
  2. Recepció de Canals Tancats: Rebre d'un canal tancat retorna el valor zero del tipus de dades del canal. Utilitza un segon valor per comprovar si el canal està tancat.
value, ok := <-ch
if !ok {
    fmt.Println("El canal està tancat")
}

Conclusió

Els canals són una eina poderosa per gestionar la concurrència en Go. Permeten la comunicació segura entre goroutines i simplifiquen la sincronització de dades. Amb la pràctica, els canals esdevenen una part essencial del teu arsenal de programació en Go.

© Copyright 2024. Tots els drets reservats