DEV Community

Matheus Mina
Matheus Mina

Posted on

6 1

Introdução a concorrência em Go

Uma das funcionalidades mais legais de Go é a facilidade de se utilizar concorrência. A linguagem nos fornece as chamadas goroutines que são lighweight threads gerenciadas pelo própio runtime do Go. Concorrência nos permite rodar diversas funções ao mesmo tempo. Isso é extremamente útil caso você queira melhorar a performance de sua aplicação.

Para utilizar essa funcionalidade, basta colocar a palavra-chave go antes de qualquer função e ela automaticamente vai estar rodando de forma concorrente. Para ficar mais fácil de entender, vamos ver um pouco de código. Aqui está implementado o SleepSort, é um algoritmo de ordenação que utiliza um sleep para poder colocar cada elemento no seu lugar.

package main

import (
    "fmt"
    "time"
)

func main() {
    arr := []int{3, 1, 5, 6, 9, 2, 0}

    fmt.Println("Sorting", arr)
    for _, v := range arr {
        go Sort(v)
    }
}

func Sort(x int) {
    time.Sleep(time.Duration(x) * time.Second)
    fmt.Printf("%d ", x)
}
Enter fullscreen mode Exit fullscreen mode

Nesse código, temos a função sort que dorme por x segundos e imprime o valor desejado. Assim, ao final da execução de todo mundo, vamos ter impresso o array na ordem certa, correto? Infelizmente a resposta é: não!

Resposta inicial do código

Como a função roda de forma concorrente ao processo principal, só vemos na saída o que este processo retorna. Uma maneira de solucionar este problema é fazermos os processos concorrentes se comunicarem de alguma forma com o processo principal. Para isso, a linguagem nos fornece o conceito de channel. Podemos entender este conceito como um canal, ou conduinte, responsável por enviar dados entre os processos. Vamos atualizar nosso código então para utilizar channels.

package main

import (
    "fmt"
    "time"
)

func main() {
    arr := []int{3, 1, 5, 6, 9, 2, 0}
    c := make(chan int)

    fmt.Println("Sorting", arr)
    for _, v := range arr {
        go sort(v, c)
    }

    fmt.Println("Sorted:")
    for range arr {
        x := <-c
        fmt.Printf("%d ", x)
    }
}

func sort(x int, c chan int) {
    time.Sleep(time.Duration(x) * time.Second)
    c <- x
}
Enter fullscreen mode Exit fullscreen mode

E finalmente temos como resposta:

Resposta após utilizarmos channels

Como podemos notar, existe um operador especial para os channels que é o <-. Para entender como ele funciona, é só pensar que o dado vai seguir o sentido da seta. Por exemplo, dentro da função sort o dado é enviado através do canal usando c <- x e na função principal recebemos um valor do canal e atribuímos em uma nova variável utilizando x := <-c.

Também é importante dizer que a assinatura da função sort foi alterada para receber um chan. Esse chan então é inicializado na função principal e passado para as goroutines.

Como podemos ver, começar a utilizar concorrência em Go é simples. A linguagem também suporta opções mais avançadas, mas isso fica para um próximo blog post. Se curtiu o assunto, você também pode me encontrar no Twitter, Github ou LinkedIn. Você também pode achar esse texto em Inglês.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post