---
title: "Channel em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/channel/"
markdown_url: "https://kotlin.dev.br/glossario/channel.MD"
description: "Saiba o que é Channel em Kotlin, como usar canais para comunicação entre coroutines e quando aplicar no seu código."
date: "2026-02-06"
author: "Karina Melo"
---

# Channel em Kotlin: O que É e Como Funciona | Kotlin Brasil

Saiba o que é Channel em Kotlin, como usar canais para comunicação entre coroutines e quando aplicar no seu código.


## O que é Channel em Kotlin?

Um `Channel` em Kotlin é uma estrutura para **comunicação entre [coroutines](/glossario/coroutine/)**. Funciona como uma fila: uma coroutine envia dados pelo canal e outra recebe do outro lado. E o jeito mais seguro de trocar informações entre coroutines sem problemas de concorrencia. O conceito foi diretamente inspirado pelos channels de [Go](https://golang.com.br/) — a implementação em Kotlin segue padrões similares, mas adaptados para o ecossistema de coroutines da JVM.

Se o [Flow](/glossario/flow/) e como uma torneira (um produtor, um consumidor), o Channel é mais como um cano de comunicação bidirecional entre partes independentes do código.

Imagine uma esteira de fabrica: de um lado, um operario coloca pecas na esteira (send), e do outro lado, outro operario retira as pecas para montar o produto (receive). A esteira tem uma capacidade limitada -- se estiver cheia, o primeiro operario espera; se estiver vazia, o segundo espera. E exatamente assim que um Channel funciona.

### Exemplo básico

```kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

fun main() = runBlocking {
    val canal = Channel<String>()

    launch {
        canal.send("Primeira mensagem")
        canal.send("Segunda mensagem")
        canal.close()
    }

    for (msg in canal) {
        println("Recebido: $msg")
    }
}
```

O `send` envia dados para o canal e o `for` consome. Quando o canal e fechado com `close()`, o loop encerra automaticamente.

### Tipos de Channel

Kotlin oferece diferentes capacidades de buffer:

```kotlin
// Sem buffer -- send suspende ate alguem fazer receive
val rendezvous = Channel<Int>()

// Buffer limitado
val buffered = Channel<Int>(capacity = 10)

// Buffer ilimitado
val unlimited = Channel<Int>(Channel.UNLIMITED)

// Mantem so o ultimo valor
val conflated = Channel<Int>(Channel.CONFLATED)
```

### Produtor e consumidor

O padrão produtor-consumidor fica bem elegante com `produce`:

```kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

fun CoroutineScope.produzirNumeros() = produce {
    for (i in 1..5) {
        delay(300)
        send(i)
    }
}

fun main() = runBlocking {
    val numeros = produzirNumeros()

    for (n in numeros) {
        println("Numero: $n")
    }
}
```

### Channel vs Flow

A principal diferenca e que Channel e **hot** -- ele produz dados independente de ter alguem consumindo. Ja o Flow e **cold** -- só produz quando alguem coleta.

| Caracteristica | Channel | Flow |
|---|---|---|
| Tipo | Hot | Cold |
| Produtores | Um ou vários | Um |
| Consumidores | Um | Um ou vários |

Use Channel quando precisar de comunicação ativa entre coroutines. Para streams de dados reativos, prefira [Flow](/glossario/flow/).

### Pipeline com Channels

Channels permitem criar pipelines onde cada estagio processa dados e passa para o proximo, similar a um fluxo de producao industrial:

```kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

fun CoroutineScope.gerarPedidos() = produce {
    val pedidos = listOf("Pedido-001", "Pedido-002", "Pedido-003", "Pedido-004")
    for (pedido in pedidos) {
        delay(200)
        send(pedido)
    }
}

fun CoroutineScope.validarPedidos(entrada: ReceiveChannel<String>) = produce {
    for (pedido in entrada) {
        delay(150)
        send("$pedido [VALIDADO]")
    }
}

fun CoroutineScope.processarPagamento(entrada: ReceiveChannel<String>) = produce {
    for (pedido in entrada) {
        delay(300)
        send("$pedido [PAGO]")
    }
}

fun main() = runBlocking {
    val pedidos = gerarPedidos()
    val validados = validarPedidos(pedidos)
    val pagos = processarPagamento(validados)

    for (resultado in pagos) {
        println(resultado)
    }
}
```

### Fan-out: múltiplos consumidores

Quando você tem trabalho pesado, pode distribuir itens de um canal entre várias coroutines trabalhadoras:

```kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

fun main() = runBlocking {
    val tarefas = Channel<Int>(capacity = 10)

    // Produtor: envia 20 tarefas
    launch {
        for (i in 1..20) {
            tarefas.send(i)
        }
        tarefas.close()
    }

    // 3 consumidores processando em paralelo
    repeat(3) { trabalhadorId ->
        launch {
            for (tarefa in tarefas) {
                delay(200) // simula processamento
                println("Trabalhador $trabalhadorId processou tarefa $tarefa")
            }
        }
    }
}
```

### Fan-in: múltiplos produtores

O cenário inverso também e comum -- vários produtores enviando para um único canal:

```kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

suspend fun produzirLogs(canal: SendChannel<String>, origem: String, quantidade: Int) {
    repeat(quantidade) { i ->
        delay(100)
        canal.send("[$origem] Log #$i")
    }
}

fun main() = runBlocking {
    val logs = Channel<String>(Channel.UNLIMITED)

    launch { produzirLogs(logs, "SERVIDOR-A", 3) }
    launch { produzirLogs(logs, "SERVIDOR-B", 3) }
    launch { produzirLogs(logs, "SERVIDOR-C", 3) }

    // Aguarda e depois fecha
    launch {
        delay(500)
        logs.close()
    }

    for (log in logs) {
        println(log)
    }
}
```

### Casos de Uso no Mundo Real

- **Filas de processamento**: sistemas que recebem eventos (cliques, logs, transacoes) e os processam de forma assíncrona usando channels como fila intermediaria.
- **Web scraping paralelo**: um produtor gera URLs para visitar e múltiplos consumidores fazem as requisicoes em paralelo, reportando resultados em outro channel.
- **Chat em tempo real**: mensagens enviadas por usuários sao colocadas em um channel e distribuidas para todos os participantes da sala.
- **Processamento de arquivos**: leitura de linhas de um arquivo grande em um channel, com múltiplos trabalhadores processando cada linha em paralelo.

### Boas Praticas

- Sempre feche o channel com `close()` quando o produtor terminar, para que consumidores saibam que não havera mais dados.
- Prefira `produce` em vez de criar channels manualmente, pois ele garante o fechamento automatico e trata cancelamento corretamente.
- Use buffer limitado na maioria dos casos. `Channel.UNLIMITED` pode causar problemas de memória se o produtor for mais rápido que o consumidor.
- Use `Channel.CONFLATED` quando você só se importa com o valor mais recente, como atualizações de posicao GPS.
- Considere [Flow](/glossario/flow/) antes de Channel. Muitas vezes um [Flow](/glossario/flow/) resolve o problema de forma mais simples e com menos risco de vazamento de recursos.

### Erros Comuns

- **Esquecer de fechar o channel**: se o produtor não chama `close()`, o consumidor ficara suspenso para sempre esperando mais dados, causando travamento.
- **Enviar para um channel fechado**: chamar `send()` apos `close()` lanca `ClosedSendChannelException`. Verifique o estado antes ou use `trySend()`.
- **Usar Channel quando Flow resolve**: Channel e mais complexo e exige gerenciamento manual de ciclo de vida. Se você só precisa de um stream de dados cold, use [Flow](/glossario/flow/).
- **Ignorar cancelamento**: quando uma coroutine consumidora e cancelada, o channel pode ficar com dados não processados. Estruture o código com `coroutineScope` para garantir limpeza adequada.

### Perguntas Frequentes

**Qual a diferenca entre Channel e [Flow](/glossario/flow/)?**
Channel e hot (produz dados independente de consumidores) e suporta múltiplos produtores. Flow e cold (só produz quando coletado) e e mais simples de usar. Prefira Flow para streams reativos e Channel para comunicação ativa entre coroutines.

**Posso ter vários consumidores no mesmo Channel?**
Sim, mas cada item sera recebido por apenas um consumidor (fan-out). Se você precisa que todos os consumidores recebam todos os itens, use `BroadcastChannel` ou `SharedFlow`.

**O que acontece se o buffer do Channel estiver cheio?**
A coroutine que chama `send()` sera suspensa até que haja espaco no buffer. Com `trySend()`, a operação retorna imediatamente com um resultado indicando se o envio foi bem-sucedido.

**Channels podem causar vazamento de memória?**
Sim, se você criar um Channel com buffer ilimitado e o produtor for muito mais rápido que o consumidor, os dados acumulam na memória. Use buffers limitados e monitore o fluxo de dados.
