Saiba como goroutines e canais permitem simultaneidade eficiente em seus programas Go.

A simultaneidade é um aspecto crucial do desenvolvimento de software moderno, pois permite que os programas lide com eficiência com várias tarefas simultaneamente. Você pode escrever programas que executam várias operações levando a melhor desempenho, capacidade de resposta e utilização de recursos.

A simultaneidade é um dos recursos responsáveis ​​pela rápida adoção do Go. O suporte integrado do Go para programação simultânea é considerado direto, ajudando a evitar armadilhas comuns, como condições de corrida e impasses.

Simultaneidade em Go

O Go fornece suporte robusto para simultaneidade por meio de vários mecanismos, todos disponíveis em sua biblioteca e cadeia de ferramentas padrão. ir programas obter simultaneidade por meio de goroutines e canais.

As goroutines são funções leves e de execução independente que são executadas simultaneamente com outras goroutines no mesmo espaço de endereço. As goroutines permitem que várias tarefas progridam simultaneamente sem gerenciamento explícito de encadeamentos. As goroutines são mais leves que os threads do sistema operacional e o Go pode executar com eficiência milhares ou até milhões de goroutines simultaneamente.

Canais são o mecanismo de comunicação para coordenação e compartilhamento de dados entre goroutines. Um canal é um conduíte tipado que permite que goroutines enviem e recebam valores. Os canais fornecem sincronização para garantir o compartilhamento seguro de dados entre goroutines, evitando condições de corrida e outros problemas comuns de simultaneidade.

Ao combinar goroutines e canais, o Go fornece um modelo de simultaneidade poderoso e direto que simplifica o desenvolvimento de programas simultâneos, mantendo a segurança e a eficiência. Esses mecanismos permitem que você use facilmente processadores multicore e crie aplicativos altamente escaláveis ​​e responsivos.

Como usar goroutines para execução de código concorrente

O tempo de execução Go gerencia goroutines. As goroutines têm sua pilha, permitindo que tenham uma pegada leve com um tamanho de pilha inicial de alguns kilobytes.

As goroutines são multiplexadas em vários threads do sistema operacional pelo tempo de execução do Go. O agendador de tempo de execução do Go os agenda em threads disponíveis, distribuindo a carga de trabalho com eficiência, permitindo a execução simultânea de várias goroutines em menos threads do sistema operacional.

Criar goroutines é simples. Você usará o ir palavra-chave seguida por uma chamada de função para declarar goroutines.

funçãoprincipal() {
ir função1() // Cria e executa goroutine para function1
ir função2() // Cria e executa goroutine para function2

// ...
}

funçãofunção1() {
// Código para function1
}

funçãofunção2() {
// Código para function2
}

Quando o programa invoca função1() e função2() com o ir palavra-chave, o tempo de execução do Go executa as funções simultaneamente como goroutines.

Aqui está um exemplo de uso de uma goroutine que imprime texto no console:

pacote principal

importar (
"fmt"
"tempo"
)

funçãoprintText() {
para eu := 1; eu <= 5; i++ {
fmt. Imprimirln("Imprimindo texto", eu)
tempo. Dormir(1 * tempo. Segundo)
}
}

funçãoprincipal() {
ir printText() // Inicia uma goroutine para executar a função printText simultaneamente

// Executa outras tarefas na goroutine principal
para eu := 1; eu <= 5; i++ {
fmt. Imprimirln("Execução de outras tarefas", eu)
tempo. Dormir(500 * tempo. milissegundo)
}

// Espera a goroutine terminar
tempo. Dormir(6 * tempo. Segundo)
}

O printText função imprime repetidamente algum texto no console com um para loop que é executado cinco vezes após um atraso de um segundo entre cada instrução com o pacote de tempo.

O principal função inicia uma goroutine chamando ir imprimirTexto, que lança o printText funcionar como uma goroutine simultânea separada que permite que a função seja executada simultaneamente com o restante do código no principal função.

Finalmente, para garantir que o programa não saia antes do printText acabamentos goroutine, o tempo. Dormir A função pausa a goroutine principal por seis segundos. Em cenários do mundo real, você usaria mecanismos de sincronização como canais ou grupos de espera para coordenar a execução de goroutines.

Usando Canais para Comunicação e Sincronização

As goroutines têm suporte integrado para comunicação e sincronização por meio de canais, tornando a escrita simultânea código mais fácil do que os threads tradicionais, que geralmente exigem mecanismos de sincronização manual, como bloqueios e semáforos.

Você pode pensar em canais como pipelines para fluxo de dados entre goroutines. Uma goroutine pode enviar um valor para o canal e outra goroutine pode receber esse valor do canal. Esse mecanismo garante que a troca de dados seja segura e sincronizada.

Você usará o operadora para enviar e receber dados através de canais.

Aqui está um exemplo demonstrando o uso básico de canais para comunicação entre duas goroutines:

funçãoprincipal() {
// Cria um canal sem buffer do tipo string
ch := fazer(chancorda)

// Goroutine 1: Envia uma mensagem para o canal
irfunção() {
ch "Olá, canal!"
}()

// Goroutine 2: Recebe a mensagem do canal
msg := fmt. Println (msg) // Saída: Olá, Canal!
}

O canal no principal função é um canal sem buffer chamado CH criado com o fazer() função. A primeira goroutine envia a mensagem "Hello, Channel!" no canal usando o operador, e a segunda goroutine recebe a mensagem do canal usando o mesmo operador. finalmente, o principal A função imprime a mensagem recebida no console.

Você pode definir canais digitados. Você especificará o tipo de canal na criação. Aqui está um exemplo que demonstra o uso de diferentes tipos de canais:

funçãoprincipal() {
// canal sem buffer
ch1 := fazer(chanint)

// Canal com buffer com capacidade para 3
ch2 := fazer(chancorda, 3)

// Enviando e recebendo valores dos canais
ch1 42// Envia um valor para ch1
valor1 := // Recebe um valor de ch1

ch2 "Olá"// Envia um valor para ch2
valor2 := // Recebe um valor de ch2
}

O principal função cria dois canais: ch1 é um canal inteiro sem buffer, enquanto ch2 é um canal de string em buffer com uma capacidade de 3. Você pode enviar e receber valores de e para esses canais usando o operador (os valores devem ser do tipo especificado).

Você pode usar canais como mecanismos de sincronização para coordenar a execução de goroutine, aproveitando a natureza de bloqueio das operações de canal.

funçãoprincipal() {
ch := fazer(chanbool)

irfunção() {
fmt. Imprimirln("Gorotina 1")
ch verdadeiro// conclusão do sinal
}()

irfunção() {
// Aguarda o sinal de conclusão da Goroutine 1
fmt. Imprimirln("Gorotina 2")
}()

// Espera pelo sinal de conclusão da Goroutine 2
fmt. Imprimirln("Goroutine principal")
}

O CH canal é booleano. Duas goroutines rodam simultaneamente no principal função. Goroutine 1 sinaliza sua conclusão enviando um verdadeiro valor no canal CH. Goroutine 2 espera pelo sinal de conclusão recebendo um valor do canal. Finalmente, a goroutine principal espera pelo sinal de conclusão da goroutine dois.

Você pode criar aplicativos da Web no Go With Gin

Você pode criar aplicativos da Web de alto desempenho no Go with Gin enquanto aproveita os recursos de simultaneidade do Go.

Você pode usar o Gin para lidar com roteamento HTTP e middleware com eficiência. Aproveite o suporte de simultaneidade integrado do Go empregando goroutines e canais para tarefas como consultas de banco de dados, chamadas de API ou outras operações de bloqueio.