A beleza de Go

Gopher – Mascote icônico de Go

Comecei recentemente a explorar Go para alguns dos meus projetos paralelos e foi realmente impressionado com a beleza.

Percebi o quão lindamente conseguiu um equilíbrio entre a facilidade de uso (geralmente associada a linguagens interpretadas dinamicamente e interpretadas) e desempenho e segurança (tipo de segurança, segurança de memória) (geralmente associada a linguagens estaticamente digitadas e compiladas).

Além disso, mais duas características tornam o idioma perfeito para o desenvolvimento de sistemas modernos. Ambos os recursos são explicados em mais detalhes na seção Fortes abaixo.

Um deles é o suporte de primeira classe para a linguagem (através de goroutines e canais, explicado abaixo). Concorrência, por seu design, permite que você use eficientemente sua potência de CPU. Mesmo que seu processador tenha apenas um núcleo, o design da concorrência permite que você use esse núcleo de forma eficiente. É por isso que normalmente você pode ter centenas de milhares de goroutines simultâneos (threads leves) em execução em uma única máquina. Canais e goroutines são centrais para os sistemas distribuídos, uma vez que abstraem o paradigma de mensagens produtor-consumidor.

A outra característica que eu realmente gosto de Go é as interfaces. As interfaces permitem componentes vagamente acoplados ou desacoplados para seus sistemas . O que significa que uma parte do seu código pode apenas confiar em um tipo de interface e realmente não se preocupa com quem implementa a interface ou como a interface é efetivamente implementada. Seu controlador pode então fornecer uma dependência que satisfaça a interface (implementa todas as funções na interface) para esse código. Isso também permite uma arquitetura realmente limpa para testes de unidade (através da injeção de dependência). Agora, o seu controlador pode apenas injetar uma implementação simulada da interface requerida pelo código para poder testar se está fazendo seu trabalho corretamente ou não.

Mantendo todos esses recursos em mente, acho que Go é realmente uma ótima linguagem. Especialmente para casos de uso como o desenvolvimento de sistemas em nuvem (servidores web, CDNs, caches, etc.), sistemas distribuídos, microservices, etc. Então, se você é um engenheiro ou uma inicialização tentando decidir qual o idioma que quer explorar ou experimentar, um pensamento sério.

Nesta publicação, falo sobre os seguintes aspectos do idioma:

a) Introdução
b) Por que foi necessário o Go
c) público-alvo
d) Os pontos fortes de Go
e) As fraquezas de Go
f) Rumo a Go 2
g) filosofia de design de Go
h) Como começar
i) Quem está usando Go

Introdução

Go é uma linguagem de código aberto, criada no Google por Robert Griesemer, Rob Pike e Ken Thompson. A fonte aberta aqui significa que todos podem contribuir com o idioma, abrindo propostas para novos recursos, corrigir bugs etc. O código do idioma está disponível no GitHub . A documentação sobre como você pode contribuir com o idioma é fornecida aqui .

Por que foi necessário Go

Os autores mencionam que o principal motivo para projetar uma nova linguagem foi resolver problemas de engenharia de software no Google. Eles também mencionam que o Go foi realmente desenvolvido como uma alternativa ao C ++.

Rob Pike menciona o propósito da linguagem de programação Go:

"O objetivo de Go, portanto, não é fazer pesquisa em design de linguagem de programação; é melhorar o ambiente de trabalho para seus designers e seus colegas de trabalho. Go é mais sobre engenharia de software do que a pesquisa de linguagem de programação. Ou para reformular, trata-se de design de linguagem ao serviço da engenharia de software ".

As questões que estavam assolando o horizonte de engenharia de software no Google foram (tiradas de https://talks.golang.org/2012/splash.article ):

a) construções lentas – as compilações levariam algum tempo até uma hora para completar
b) dependências descontroladas
c) cada programador usando um subconjunto diferente do idioma
d) má compreensão do programa (código difícil de ler, mal documentado e assim por diante)
e) duplicação de esforços
f) custo das atualizações
g) inclinação da versão
h) dificuldade em escrever ferramentas automáticas
i) construções em linguagem cruzada

Para ir para ter sucesso, Go deve resolver esses problemas (tirados de https://talks.golang.org/2012/splash.article ):

a) Go deve trabalhar em escala, para grandes equipes de programadores que trabalham neles, para programas com grande número de dependências.
b) Vá deve ser familiar, aproximadamente como C. O Google precisa tornar os programadores produtivos rapidamente em Go, significa que o idioma não pode ser muito radical.
c) Vá deve ser moderno. Deve ter recursos como a simultaneidade para que os programas possam usar eficientemente as máquinas multi-core. Ele deve ter bibliotecas integradas e bibliotecas de servidores web para que ele ajude o desenvolvimento moderno.

Público-alvo

Go é uma linguagem de programação de sistemas. Ir realmente brilha para coisas como sistemas de nuvem (servidores web, caches), microservices, sistemas distribuídos (devido ao suporte de concorrência).

Forças

a) Estaticamente digitado: Go é estaticamente digitado. Isso significa que você precisa declarar tipos para todas as suas variáveis ​​e seus argumentos de função (e retornar variáveis) no tempo de compilação. Embora isso possa parecer inconveniente, esta é uma grande vantagem, uma vez que muitos erros serão encontrados no próprio tempo de compilação. Este fator desempenha um papel muito importante quando o tamanho da sua equipe aumenta, uma vez que os tipos declarados tornam as funções e as bibliotecas mais legíveis e mais fáceis de entender.

b) Velocidade de compilação: O código do go compila muito rápido , então você não precisa continuar aguardando seu código para compilar. 🙂 Na verdade, o comando 'go run' dispara o seu programa Go rapidamente para que você nem tenha a sensação de que seu código foi compilado primeiro. Parece uma linguagem interpretada.

c) Velocidade de Execução: O código Go é compilado diretamente para o código da máquina, dependendo do sistema operacional (Linux / Windows / Mac) e da arquitetura do conjunto de instruções da CPU (x86, x86-64, braço, etc.) da máquina em que o código está sendo compilado . Então, ele corre muito rápido.

d) Portable: uma vez que o código é compilado diretamente para o código da máquina, portanto, os binários tornam-se portáteis. A portabilidade aqui significa que você pode retirar o binário de sua máquina (digamos Linux, x86-64) e execute diretamente isso no seu servidor (se o servidor também estiver executando o Linux em uma arquitetura x86-64).

Isso se torna possível porque os binários do Go estão vinculados de forma estática, o que significa que todas as bibliotecas de sistemas operacionais compartilhadas que seu programa precisa estão incluídas no binário no momento da compilação. Eles não estão vinculados dinamicamente no momento da execução do programa.

Isso tem um enorme benefício para a implantação de seus programas em várias máquinas em um data center. Se você tem 100 máquinas em seu centro de dados, você pode simplesmente "scp" seu binário de programa para todos eles, desde que o binário seja compilado para o mesmo sistema operacional e a arquitetura de conjunto de instruções em que suas máquinas funcionam. Você não precisa se preocupar com a versão do Linux que eles estão executando. Não há necessidade de verificar / gerenciar dependências. Os binários simplesmente são executados e todos os seus serviços estão ativos 🙂

e) Concorrência: Go tem suporte de primeira classe para a concorrência. Concorrência é um dos principais pontos de venda do Go. Os designers de linguagem desenharam o modelo de concorrência em torno do documento " Comunicar Processos Sequenciais " de Tony Hoare.

O tempo de execução Go permite que você execute centenas de milhares de goroutines concorrentes em uma máquina . A Goroutine é um fio leve de execução. O tempo de execução do Go é multiplexado aqueles goroutines sobre os segmentos do sistema operacional. Isso significa que múltiplos goroutines podem ser executados simultaneamente em um único segmento de sistema operacional. O tempo de execução do Go tem um agendador cujo trabalho é agendar esses goroutines para execução.

Existem dois benefícios dessa abordagem:

i) Um Goroutine quando inicializado tem uma pilha de 4 KB. Isso é realmente pequeno, em comparação com uma pilha de um segmento OS, que geralmente é de 1 MB. Esse número é importante quando você precisa ter centenas de milhares de goroutines diferentes executando simultaneamente. Se você executasse mais de milhares de threads do sistema operacional em paralelo, a RAM, obviamente, se tornaria um gargalo.

ii) Go poderia ter seguido o mesmo modelo que outros idiomas, como o Java, que suportam o mesmo conceito de tópicos que OS threads. Mas, nesse caso, o custo de uma mudança de contexto entre os threads do sistema operacional é muito maior do que o custo de uma mudança de contexto entre diferentes goroutines.

Uma vez que estou me referindo à "simultaneidade" várias vezes neste artigo, eu aconselharia você a verificar a conversa de Rob Pike sobre " Concorrência não é paralelismo ". Na programação, a concorrência é a composição dos processos de execução independentes, enquanto o paralelismo é a execução simultânea de cálculos (possivelmente relacionados). A menos que você tenha um processador com vários núcleos ou tenha vários processadores, você não pode realmente ter paralelismo, já que um núcleo de CPU só pode executar uma coisa por vez. Em uma única máquina central, é apenas a concorrência que está fazendo seu trabalho nos bastidores. O programador do sistema operacional agende processos diferentes (threads, na verdade, cada processo tem pelo menos um segmento principal) para diferentes timeslices no processador. Portanto, em um momento, você só pode ter um segmento (processo) executado no processador. Devido à alta velocidade de execução das instruções, temos a sensação de que várias coisas estão sendo executadas. Mas na verdade é apenas uma coisa de cada vez.

Concorrência é sobre lidar com muitas coisas ao mesmo tempo. Paralelismo é fazer muitas coisas ao mesmo tempo.

f) Interfaces: as interfaces permitem sistemas de acoplamento livre. Um tipo de interface em Go pode ser definido como um conjunto de funções. É isso aí. Qualquer tipo que implemente essas funções implemente implícita a interface, ou seja, não é necessário especificar que um tipo implemente a interface. Isso é verificado pelo compilador automaticamente no tempo de compilação.

Isso significa que uma parte do seu código pode apenas confiar em um tipo de interface e realmente não se preocupa com quem implementa a interface ou como a interface é efetivamente implementada. Sua função principal / controlador pode então fornecer uma dependência que satisfaça a interface (implementa todas as funções na interface) a esse código. Isso também permite uma arquitetura realmente limpa para testes de unidade (através da injeção de dependência). Agora, seu código de teste pode apenas injetar uma implementação simulada da interface requerida pelo código para poder testar se ele está fazendo seu trabalho corretamente ou não.

Embora isso seja ótimo para a dissociação, o outro benefício é que você comece a pensar sobre sua arquitetura como diferentes microservices. Mesmo se o seu aplicativo reside em um único servidor (se você está apenas começando), você arquiteta as diferentes funcionalidades necessárias em sua aplicação como diferentes microservices, cada uma implementando uma interface que promete. Assim, outros serviços / controladores apenas chamam os métodos em sua interface, na verdade, não se preocupam com o fato de serem implementados nos bastidores.

g) Coleta de lixo: Ao contrário de C, você não precisa se lembrar de liberar ponteiros ou se preocupar com ponteiros pendurados em Go. O coletor de lixo faz esse trabalho automaticamente.

h) Sem exceções, manipule erros você mesmo: adoro o fato de que Go não possui a lógica de exceção padrão que outros idiomas possuem. Ir forçar os desenvolvedores a lidar com erros básicos como "não conseguiu abrir o arquivo", em vez de deixá-los encerrar todo o código em um bloco de tentativa de captura. Isso também coloca pressão sobre os desenvolvedores para realmente pensar sobre o que precisa ser feito para lidar com esses cenários de falha.

i) Ferramentas incríveis: um dos melhores aspectos sobre Go é a sua ferramenta. Possui ferramentas como:

i) Gofmt: ele automaticamente formata e recua seu código para que seu código pareça o mesmo que todo o desenvolvedor Go no planeta. Isso tem um enorme efeito na legibilidade do código.

ii) Vá em execução: compila seu código e executá- lo, ambos :). Portanto, mesmo que a Go precise ser compilada, essa ferramenta faz com que você sinta que é uma linguagem interpretada, uma vez que apenas compila seu código tão rápido que você nem se sente quando o código foi compilado.

iii) Go get: Isso baixa a biblioteca do GitHub e copia-a para o GoPath para que você possa importar a biblioteca no seu projeto

iv) Godoc: Godoc analisa seu código-fonte Go – incluindo comentários – e produz sua documentação em formato HTML ou texto simples. Através da interface da web Godoc, você pode ver documentação bem acoplada ao código que ele documenta. Você pode navegar da documentação de uma função para sua implementação com um clique.

Você pode verificar mais ferramentas aqui.

j) Grandes bibliotecas integradas: Go tem excelentes bibliotecas integradas para auxiliar o desenvolvimento moderno. Alguns deles são:

a) net / http – Fornece implementações de cliente e servidor HTTP

b) banco de dados / sql – para interação com bancos de dados SQL

c) codificação / json – JSON é tratado como um membro de primeira classe do idioma padrão 🙂

d) html / templates – biblioteca de modelos HTML

e) io / ioutil – Implementa funções de utilidade de E / S

Existe um grande desenvolvimento no horizonte Go. Você pode encontrar todas as bibliotecas e frameworks Go para todos os tipos de ferramentas e casos de uso aqui .

Fraquezas

1. Falta de genéricos – os genéricos nos permitem projetar algoritmos em torno de tipos a serem especificados – mais tarde. Digamos que você precisa escrever uma função para classificar uma lista de números inteiros. Mais tarde, você precisa escrever outra função para classificar uma lista de strings. Naquele momento, você percebe que o código seria praticamente o mesmo, mas você não pode usar a função original, pois a função pode incluir uma lista de tipo inteiro ou uma lista de tipo de letra como argumento. Isso exigiria duplicação de código. Portanto, os genéricos permitem que você crie algoritmos em torno de tipos que podem ser especificados mais tarde. Você pode projetar um algoritmo para classificar uma lista do tipo T. Então, você pode chamar a mesma função com números inteiros / strings / qualquer outro tipo dado que existe uma função de ordenação para esse tipo. O que significa que o compilador pode verificar se um valor desse tipo é maior do que outro valor desse tipo ou não (uma vez que isso é necessário para a classificação)

É possível implementar algum tipo de mecanismo genérico em Go usando o recurso de interface vazia (interface {}) do idioma. No entanto, não é ideal.

Genéricos é um tema altamente controverso. Alguns programadores juram por isso. Enquanto outros não querem que eles estejam incluídos na linguagem, pois os genéricos geralmente são um trade-off entre o tempo de compilação e o tempo de execução.

Dito isto, os autores de Go expressaram a abertura para implementar algum tipo de mecanismo genérico em Go. No entanto, não se trata apenas de genéricos. Os genéricos só podem ser implementados no idioma se funcionarem bem e, naturalmente, com todos os outros recursos do idioma. Aguarde e veja se o Go 2 fornece algum tipo de solução para eles.

2. Falta de gerenciamento de dependência – A promessa do Go1 significa que o idioma Go e sua biblioteca não podem alterar suas API ao longo da vida do Go 1. Isso significa que seu código fonte continuará a compilar tanto para o Go 1.5 quanto para o Go 1.9. Portanto, a maioria das bibliotecas do terceiro partido também seguem a mesma promessa. Uma vez que a principal maneira de obter uma biblioteca de terceiros do GitHub é através da ferramenta 'go get', portanto, quando você faz um 'go get github.com/vendor/library', você tem esperança de que o código mais recente em seu ramo principal não altera as APIs da biblioteca. Embora isso seja legal para projetos laterais casuais, uma vez que a maioria das bibliotecas não quebra a promessa, isso não é ideal para implementações de produção.

Deve haver alguma maneira ideal para o controle de dependência para que você possa simplesmente incluir o número de versão de uma biblioteca de terceiros em seu arquivo de dependência. Mesmo que a sua API mude, você não precisa se preocupar com isso, uma vez que a API mais recente virá com uma versão mais recente. Mais tarde, você pode voltar para verificar quais mudanças foram feitas e, em seguida, tomar uma decisão sobre se deseja ou não atualizar a versão em seu arquivo de dependência e alterar seu código de cliente de acordo com as mudanças na interface da API.

Oficial experimento de Go dep idealmente deve tornar-se a solução para este problema em breve. Provavelmente em Go 2 🙂

Rumo a Go 2

Eu realmente adoro a forma como os autores tomaram uma abordagem de código aberto para a língua. Se você quiser que um recurso seja implementado no Go 2, você precisa escrever um documento onde você precisa:

a) descreva seu caso de uso ou problema
b) ilustre como você não pode resolver o caso / problema de uso usando Go
c) descreva o quão grande é o problema (alguns problemas simplesmente não são suficientemente grandes ou são suficientes para serem priorizados para resolver um determinado momento).
d) opcionalmente, propor uma solução para resolver o problema

Os autores irão analisá-lo e vinculá-lo aqui . Todas as discussões em torno de problemas acontecerão em mídias públicas, como listas de discussão e rastreadores de problemas.

Os dois problemas mais prementes para o idioma, na minha opinião, são genéricos e gerenciamento de dependências. O gerenciamento de dependências é mais uma questão de engenharia de lançamento ou ferramentas. Espero que vejamos a dep (a experiência oficial) tornar-se a ferramenta oficial para resolver o problema. Dado que os autores expressaram abertura aos genéricos na linguagem, tenho curiosidade em ver como eles os implementam, uma vez que os genéricos vêm ao custo do tempo de compilação ou tempo de execução.

Filosofia de design de Go

Algumas coisas realmente brilharam para mim da conversa de Simplicidade de Rob Pike é complicada .

Especificamente, as coisas que eu gostei foram:

a) Tradicionalmente, todos os outros idiomas querem continuar a adicionar novos recursos . Desta forma, todos os idiomas estão apenas adicionando inchação, muita complexidade em seus compiladores e suas especificações. Se isso continuar, todo o idioma parecerá o mesmo no futuro, porque cada idioma continuará adicionando funcionalidades que não possui. Considere, adicionando JavaScript recursos orientados a objetos. Os autores do Go deliberadamente não incluíram muitos recursos no idioma. Somente essas características foram incluídas para as quais havia consenso dos autores, pois aqueles que realmente sentiram como eles trouxeram valor no que pode ser alcançado pela linguagem.

b) Os recursos são como vetores ortogonais em um espaço de solução. O importante é a capacidade de escolher e combinar diferentes vetores para o seu caso de uso. E esses vetores devem apenas trabalhar um com o outro naturalmente. Significa que todas as características do idioma devem funcionar previsivelmente com qualquer outro. Desta forma, esses conjuntos de recursos cobrem todo o espaço da solução. A implementação de todos esses recursos, que funcionam muito naturalmente entre si, traz muita complexidade na implementação do idioma. Mas a linguagem abstrai a complexidade e fornece uma interface simples e fácil de entender. Portanto, a simplicidade é apenas a arte de esconder a complexidade 🙂

c) A importância da legibilidade é muitas vezes subestimada. A legibilidade é fundamental, indiscutivelmente, uma das coisas mais importantes na concepção de linguagens de programação, uma vez que a importância e o custo da manutenção do software são elevados. Muitas características prejudicam a legibilidade de um idioma.

d) A legibilidade também significa confiabilidade. Se um idioma for complicado, você deve entender mais coisas para ler e trabalhar no código. Da mesma forma, para corrigi-lo e para consertá-lo. Isso também significa que os novos desenvolvedores em sua equipe precisarão de tempos de escala muito maiores, para entender sua linguagem até o ponto em que possam contribuir com sua base de código.

Tirado de: https://blog.digitalocean.com/get-your-development-team-started-with-go/

Como começar

Você pode fazer o download Ir e seguir as instruções de instalação a partir daqui .

Aqui está o guia oficial para começar com o Go. Vá pelo exemplo também é bom.

Se você quiser ler um livro, a linguagem de programação Go é excelente. Está escrito em um espírito semelhante ao lendário livro de linguagem de programação C e é de autoria de Alan AA Donovan e Brian W. Kernighan .

Você pode se juntar ao Gophers Slack Channel para se envolver com a comunidade e participar de discussões em torno do idioma.

Quem está usando Go

Muitas empresas começaram a investir muito em Go. Aqui estão alguns dos maiores nomes:

Google – Kubernetes , infraestrutura de escala MySQL , dl.google.com (servidores de download)

BaseCamp – Vá no BaseCamp

CloudFlare – Blog , artigo ArsTechnica

CockroachDB – Why Go foi a escolha certa para CockroachDB

CoreOS – GitHub , Blog

DataDog – Ir no DataDog

DigitalOcean – Comece sua equipe de desenvolvimento com o Go

Docker – Por que decidimos escrever Docker in Go

Dropbox – Open Sourcing nossas bibliotecas Go

Parse – Como mudamos nossa API de Ruby para Go e salvamos nossa sanidade

Facebook – GitHub

Intel – GitHub

Iron.IO – Vá após 2 anos em Produção /

MalwareBytes – Manipulação de 1 milhão de pedidos por minuto com golang /

Médio – Como o meio é social

MongoDB – Go Agent

Mozilla – GitHub

Netflix – GitHub

Pinterest – GitHub

Segmento – GitHub

SendGrid – Como convencer sua empresa a ir com Golang

Shopify – Twitter

SoundCloud – Vá no SoundCloud

SourceGraph – YouTube

Twitter – Manipulação de cinco bilhões de sessões por dia em tempo real

Uber – Blog , GitHub

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *