← Voltar para o blog

Go 1.6: Novidades e Recursos

Descubra as principais novidades do Go 1.6, incluindo novos recursos, melhorias de performance e mudancas na biblioteca padrao.

Novidades do Go 1.6: Uma Análise Detalhada

O Go 1.6, lançado em 17 de fevereiro de 2016, trouxe uma série de melhorias e adições significativas à linguagem. Embora não tenha introduzido mudanças radicais na sintaxe, focou-se em otimizações de performance, aprimoramentos na biblioteca padrão e novas funcionalidades para facilitar o desenvolvimento e a implantação de aplicações Go. Este artigo explora as principais novidades desta versão, oferecendo uma visão detalhada para desenvolvedores que buscam aprimorar seus conhecimentos e tirar o máximo proveito do Go.

Principais Novidades do Go 1.6

Suporte HTTP/2

Uma das adições mais notáveis do Go 1.6 foi o suporte nativo para HTTP/2. Isso permitiu que os desenvolvedores criassem servidores e clientes web mais eficientes, aproveitando os benefícios do protocolo HTTP/2, como multiplexação de streams, compressão de headers e push de servidor.

Anteriormente, para utilizar HTTP/2 em Go, era necessário recorrer a bibliotecas externas. Com o Go 1.6, a implementação foi integrada diretamente no pacote net/http, simplificando o processo de adoção.

Para habilitar o suporte HTTP/2 em um servidor, basta configurar o servidor HTTPS de maneira usual. O Go detectará automaticamente se o cliente suporta HTTP/2 e utilizará o protocolo apropriado.

package main

import (
	"fmt"
	"log"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Olá, HTTP/2!")
}

func main() {
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServeTLS(":443", "server.crt", "server.key", nil))
}

Neste exemplo, o servidor HTTPS está configurado para escutar na porta 443. Se o cliente suportar HTTP/2, a conexão será estabelecida utilizando este protocolo. Caso contrário, será utilizada a versão HTTP/1.1. Para verificar se uma requisição utilizou HTTP/2, pode-se inspecionar o campo Proto do objeto Request:

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Protocolo: %s", r.Proto) // Output: HTTP/2.0 ou HTTP/1.1
}

Para mais informações sobre HTTP/2 no Go, consulte a documentação do pacote net/http: https://pkg.go.dev/net/http

Opções de Vendorização Aprimoradas

O Go 1.6 introduziu melhorias significativas no suporte à vendorização, um mecanismo para incluir as dependências de um projeto diretamente no seu repositório. Isso garante que o projeto utilize as versões específicas das dependências com as quais foi testado, evitando problemas de incompatibilidade causados por atualizações nas bibliotecas externas.

Anteriormente, o Go utilizava a variável de ambiente GO15VENDOREXPERIMENT para habilitar a vendorização. No Go 1.6, a vendorização foi ativada por padrão, eliminando a necessidade de configurar essa variável. O processo de vendorização continuou a envolver a criação de uma pasta vendor na raiz do projeto e a cópia das dependências para essa pasta.

O Go 1.6 também melhorou a forma como o compilador resolve os imports, priorizando as dependências localizadas na pasta vendor. Isso simplificou o processo de gerenciamento de dependências e tornou a vendorização uma prática mais acessível e eficiente.

Para utilizar a vendorização, basta copiar as dependências para a pasta vendor na raiz do projeto. Por exemplo, se o projeto depende da biblioteca github.com/gorilla/mux, a estrutura de diretórios seria semelhante a:

meuprojeto/
├── main.go
├── vendor/
│   └── github.com/
│       └── gorilla/
│           └── mux/
│               ├── mux.go
│               └── ...
└── ...

Ao compilar o projeto, o compilador Go procurará primeiro as dependências na pasta vendor antes de procurar no $GOPATH. Isso garante que o projeto utilize as versões das dependências localizadas na pasta vendor.

Melhorias no Coletor de Lixo (Garbage Collector)

O Go 1.6 introduziu melhorias significativas no coletor de lixo, resultando em reduções no tempo de pausa (pause time) e no consumo de memória. O coletor de lixo foi otimizado para lidar melhor com grandes alocações de memória e para reduzir a fragmentação da memória.

Essas melhorias foram alcançadas através de diversas técnicas, incluindo a otimização da varredura da memória e a redução da necessidade de alocações de memória durante a coleta de lixo. O resultado foi uma experiência de execução mais suave e eficiente para aplicações Go, especialmente aquelas que lidam com grandes quantidades de dados.

Embora as melhorias no coletor de lixo sejam automáticas e não exijam nenhuma configuração adicional por parte do desenvolvedor, é importante estar ciente delas ao otimizar o desempenho de aplicações Go. Compreender como o coletor de lixo funciona e como ele interage com o código pode ajudar a evitar padrões de codificação que podem levar a um desempenho subótimo.

Suporte para Contextos em Requisições HTTP

O Go 1.6 introduziu o suporte para contextos em requisições HTTP, permitindo que os desenvolvedores controlem o ciclo de vida das requisições e cancelem requisições em andamento. Isso é particularmente útil em cenários onde as requisições podem levar muito tempo para serem concluídas ou onde é necessário cancelar requisições devido a timeouts ou erros.

O pacote context fornece as ferramentas necessárias para criar e gerenciar contextos. Um contexto pode ser associado a uma requisição HTTP através do método WithContext do tipo Request. O contexto pode então ser utilizado para cancelar a requisição ou para passar valores entre diferentes partes do código.

package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
	if err != nil {
		log.Fatal(err)
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(body))
}

Neste exemplo, um contexto com um timeout de 5 segundos é criado. Se a requisição não for concluída dentro desse período, o contexto será cancelado e a requisição será interrompida. O método NewRequestWithContext associa o contexto à requisição HTTP.

Para mais informações sobre contextos no Go, consulte a documentação do pacote context: https://pkg.go.dev/context

Pequenas Melhorias na Linguagem

Embora o Go 1.6 não tenha introduzido grandes mudanças na sintaxe da linguagem, algumas pequenas melhorias foram feitas para tornar o código mais conciso e legível. Uma dessas melhorias foi a capacidade de utilizar a palavra-chave _ (underscore) para descartar múltiplos valores retornados por uma função.

Anteriormente, para descartar um valor retornado por uma função, era necessário atribuí-lo a uma variável temporária. Com o Go 1.6, é possível utilizar o _ diretamente na lista de variáveis de atribuição.

package main

import "fmt"

func dividir(a, b int) (int, error) {
	if b == 0 {
		return 0, fmt.Errorf("Divisão por zero")
	}
	return a / b, nil
}

func main() {
	resultado, _ := dividir(10, 2) // Ignora o erro
	fmt.Println(resultado)

	_, err := dividir(10, 0) // Ignora o resultado
	if err != nil {
		fmt.Println(err)
	}
}

Neste exemplo, a função dividir retorna dois valores: o resultado da divisão e um erro. Em alguns casos, pode ser necessário ignorar um desses valores. O uso do _ permite descartar o valor indesejado de forma concisa e legível.

Melhorias de Performance

Além das melhorias no coletor de lixo, o Go 1.6 também introduziu otimizações em outras áreas do compilador e do runtime, resultando em ganhos de performance em diversas operações. Essas otimizações incluíram melhorias na alocação de memória, na execução de goroutines e na implementação de funções built-in.

Em particular, a implementação de algumas funções built-in, como copy e append, foi otimizada para utilizar instruções de baixo nível mais eficientes, resultando em um desempenho superior em operações que envolvem a manipulação de slices.

Essas melhorias de performance foram alcançadas através de uma combinação de técnicas, incluindo a otimização do código gerado pelo compilador, a utilização de algoritmos mais eficientes e a redução da sobrecarga do runtime. O resultado foi um aumento geral na velocidade e na eficiência das aplicações Go.

Mudanças na Biblioteca Padrão

O Go 1.6 também trouxe diversas mudanças e adições à biblioteca padrão, incluindo novos pacotes e funcionalidades para facilitar o desenvolvimento de aplicações Go. Algumas das mudanças mais notáveis incluem:

  • Novos métodos no pacote time: O pacote time recebeu novos métodos para facilitar a manipulação de datas e horários, como Truncate e Round.
  • Melhorias no pacote encoding/json: O pacote encoding/json foi aprimorado para lidar melhor com dados JSON complexos e para oferecer mais opções de personalização.
  • Novos métodos no pacote net/http: O pacote net/http recebeu novos métodos para facilitar a criação de servidores e clientes HTTP, como NewRequestWithContext e Client.Do.
  • Adição do pacote crypto/chacha20: O pacote crypto/chacha20 adicionou suporte ao algoritmo de criptografia ChaCha20, oferecendo uma alternativa mais rápida e segura ao AES em algumas plataformas.

Essas mudanças na biblioteca padrão tornaram o Go ainda mais completo e versátil, permitindo que os desenvolvedores criassem aplicações mais complexas e eficientes com menos esforço.

Como Atualizar

Para atualizar para o Go 1.6, siga os passos abaixo:

  1. Baixe a versão mais recente do Go 1.6 no site oficial: https://go.dev/dl/

  2. Remova a instalação anterior do Go. O método varia dependendo do sistema operacional. Em Linux, geralmente envolve remover a pasta /usr/local/go. Em macOS, pode ser necessário remover o pacote instalado via .pkg. Em Windows, utilize o painel de controle para desinstalar.

  3. Instale a nova versão do Go. Siga as instruções específicas para o seu sistema operacional.

  4. Configure as variáveis de ambiente. Certifique-se de que as variáveis GOROOT e PATH estejam configuradas corretamente para apontar para a nova instalação do Go. Por exemplo:

    export GOROOT=/usr/local/go
    export PATH=$PATH:$GOROOT/bin
    
  5. Verifique a instalação. Abra um terminal e execute o comando go version. A saída deve indicar que você está utilizando o Go 1.6.

    go version
    
  6. Recompile seus projetos. Após a atualização, é recomendável recompilar todos os seus projetos para garantir a compatibilidade com a nova versão do Go.

Conclusão Prática

O Go 1.6 representou um passo importante na evolução da linguagem, trazendo melhorias significativas em performance, funcionalidades e facilidade de uso. O suporte nativo para HTTP/2, as opções de vendorização aprimoradas, as melhorias no coletor de lixo e o suporte para contextos em requisições HTTP foram adições valiosas que beneficiaram desenvolvedores de todos os níveis de experiência.

Embora o Go tenha evoluído significativamente desde a versão 1.6, compreender as novidades desta versão ainda é relevante para desenvolvedores que buscam aprofundar seus conhecimentos sobre a linguagem e apreciar a sua trajetória. As mudanças introduzidas no Go 1.6 pavimentaram o caminho para as versões subsequentes e contribuíram para consolidar o Go como uma das linguagens de programação mais populares e eficientes da atualidade.