← Voltar para o blog

Go 1.13: Novidades e Recursos

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

Go 1.13: O que há de novo na linguagem da Google?

Go 1.13 foi lançado em 3 de setembro de 2019, trazendo diversas melhorias e novidades para a linguagem. Esta versão se concentra em melhorar a experiência do desenvolvedor, a performance da linguagem e aprimorar a biblioteca padrão. Este artigo explora as principais mudanças e como elas podem impactar seu código.

Erros Embrulhados (Wrapped Errors)

Uma das adições mais significativas do Go 1.13 é o suporte para erros embrulhados (wrapped errors). Essa funcionalidade permite que você adicione contexto a um erro sem perder a informação original, facilitando o diagnóstico e tratamento de falhas.

O Problema Anterior

Antes do Go 1.13, era comum a prática de retornar novos erros formatados com informações adicionais, o que acabava obscurecendo a causa raiz do problema. Por exemplo:

func processFile(filename string) error {
    f, err := os.Open(filename)
    if err != nil {
        return fmt.Errorf("failed to open file %s: %w", filename, err)
    }
    defer f.Close()

    // ... processamento do arquivo ...
    return nil
}

Neste exemplo, fmt.Errorf era usado para adicionar contexto ao erro os.Open. No entanto, o erro original os.Open ficava “escondido” dentro da nova mensagem.

A Solução: errors.Is e errors.As

Go 1.13 introduziu duas novas funções no pacote errors: errors.Is e errors.As. A função errors.Is verifica se um erro é do tipo esperado, mesmo que esteja embrulhado. A função errors.As tenta converter um erro para um tipo específico, permitindo acessar informações detalhadas sobre o erro original.

Para usar erros embrulhados, é necessário utilizar o verbo %w em fmt.Errorf:

import (
	"errors"
	"fmt"
	"os"
)

func processFile(filename string) error {
    f, err := os.Open(filename)
    if err != nil {
        return fmt.Errorf("failed to open file %s: %w", filename, err)
    }
    defer f.Close()

    // ... processamento do arquivo ...
    return nil
}

func main() {
    err := processFile("arquivo_inexistente.txt")
    if err != nil {
        if errors.Is(err, os.ErrNotExist) {
            fmt.Println("Arquivo não encontrado!")
        } else {
            fmt.Printf("Erro ao processar arquivo: %v\n", err)
        }
    }
}

Neste exemplo, errors.Is(err, os.ErrNotExist) verifica se o erro retornado por processFile é um erro os.ErrNotExist, mesmo que esteja embrulhado dentro de outro erro.

A função errors.As permite converter o erro para um tipo específico:

import (
	"errors"
	"fmt"
	"os"
)

func processFile(filename string) error {
    f, err := os.Open(filename)
    if err != nil {
        return fmt.Errorf("failed to open file %s: %w", filename, err)
    }
    defer f.Close()

    // ... processamento do arquivo ...
    return nil
}

func main() {
    err := processFile("arquivo_inexistente.txt")
    if err != nil {
        var pathError *os.PathError
        if errors.As(err, &pathError) {
            fmt.Printf("Erro no caminho: %s, Operação: %s, Erro: %v\n", pathError.Path, pathError.Op, pathError.Err)
        } else {
            fmt.Printf("Erro ao processar arquivo: %v\n", err)
        }
    }
}

Neste caso, errors.As(err, &pathError) tenta converter o erro para um tipo os.PathError. Se a conversão for bem-sucedida, as informações específicas do os.PathError (como o caminho do arquivo, a operação e o erro subjacente) podem ser acessadas.

Interface Unwrap

Para que um erro seja considerado um erro embrulhado, ele deve implementar o método Unwrap que retorna o erro subjacente. A função fmt.Errorf com o verbo %w automaticamente cria um erro que implementa essa interface.

type unwrapper interface {
    Unwrap() error
}

Se você criar seus próprios tipos de erro, pode implementar a interface Unwrap para torná-los compatíveis com errors.Is e errors.As.

Melhorias na Numeração de Literais Inteiros

Go 1.13 introduziu suporte para literais inteiros binários, octais e hexadecimais mais legíveis, usando o prefixo 0b para binário, 0o para octal e 0x para hexadecimal, além do separador _ (underscore) para melhorar a legibilidade.

Literais Binários

Agora você pode escrever literais binários diretamente no código:

package main

import "fmt"

func main() {
	binary := 0b101010 // Representa o número 42
	fmt.Println(binary)
}

Literais Octais

O prefixo 0o permite representar números em base octal:

package main

import "fmt"

func main() {
	octal := 0o52 // Representa o número 42
	fmt.Println(octal)
}

Separador Underscore

O separador _ pode ser usado para agrupar dígitos em literais inteiros e de ponto flutuante, tornando-os mais fáceis de ler:

package main

import "fmt"

func main() {
	number := 1_000_000 // Representa um milhão
	floatNumber := 3.141_592_653_589_793
	fmt.Println(number, floatNumber)
}

Essas mudanças melhoram a legibilidade do código, especialmente ao trabalhar com constantes que representam valores binários, octais ou grandes números.

Suporte a TLS 1.3 por Padrão

Go 1.13 habilitou o TLS 1.3 por padrão para conexões HTTPS. TLS 1.3 oferece melhorias significativas em segurança e performance em comparação com versões anteriores do TLS.

Benefícios do TLS 1.3

  • Maior segurança: Remove algoritmos criptográficos considerados obsoletos ou vulneráveis.
  • Menor latência: Reduz o número de handshakes necessários para estabelecer uma conexão segura.
  • Maior simplicidade: Simplifica o protocolo, removendo opções desnecessárias e potencialmente problemáticas.

Impacto no Código

Na maioria dos casos, essa mudança não requer nenhuma alteração no código existente. O pacote crypto/tls automaticamente negocia a versão mais alta do TLS suportada pelo servidor e pelo cliente.

Se você precisar desabilitar o TLS 1.3 ou especificar uma versão mínima do TLS, pode configurar o campo MinVersion na estrutura tls.Config:

package main

import (
	"crypto/tls"
	"fmt"
	"net/http"
)

func main() {
	tlsConfig := &tls.Config{
		MinVersion: tls.VersionTLS12, // Define a versão mínima para TLS 1.2
	}

	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: tlsConfig,
		},
	}

	resp, err := client.Get("https://example.com")
	if err != nil {
		fmt.Println("Erro:", err)
		return
	}
	defer resp.Body.Close()

	fmt.Println("Status Code:", resp.StatusCode)
}

É importante notar que desabilitar o TLS 1.3 pode reduzir a segurança das suas conexões.

Pequenas Melhorias e Mudanças

Além das funcionalidades destacadas, Go 1.13 incluiu diversas outras melhorias e mudanças menores.

Mudanças no Pacote context

O pacote context recebeu algumas otimizações de performance e correções de bugs. As mudanças não introduzem novas funcionalidades, mas melhoram a estabilidade e eficiência do pacote.

Mudanças no Pacote net

O pacote net teve algumas melhorias no tratamento de erros e na resolução de nomes de domínio. Em particular, a função net.ParseCIDR agora aceita endereços IPv6 com prefixos maiores que 64.

Mudanças no Pacote os

O pacote os teve algumas adições e correções relacionadas ao tratamento de arquivos e diretórios. A função os.ReadDir foi adicionada para ler o conteúdo de um diretório de forma mais eficiente.

Mudanças no Pacote reflect

O pacote reflect recebeu algumas otimizações de performance e correções de bugs relacionados à manipulação de tipos e valores.

Garbage Collector

O Garbage Collector (GC) do Go 1.13 recebeu melhorias que resultaram em um menor consumo de memória e uma menor latência. Essas melhorias são especialmente importantes para aplicações que alocam e liberam memória frequentemente.

Como Atualizar para Go 1.13

Para atualizar para Go 1.13, você pode usar o comando go install:

go install golang.org/dl/go1.13@latest
go1.13 download
go1.13 install

Após a instalação, você pode usar o comando go1.13 para compilar e executar seus programas com a versão Go 1.13. Para tornar a versão 1.13 a versão padrão, você pode usar o comando go env -w GO111MODULE=auto e em seguida, remover a instalação anterior do Go.

Alternativamente, você pode baixar e instalar o Go 1.13 diretamente do site oficial: https://go.dev/dl/

Após a instalação, verifique a versão do Go:

go version

A saída deve indicar go1.13.

Conclusão

Go 1.13 trouxe melhorias significativas para a linguagem, incluindo o suporte para erros embrulhados, literais inteiros mais legíveis e TLS 1.3 por padrão. Essas mudanças tornam o Go uma linguagem ainda mais poderosa e eficiente para o desenvolvimento de aplicações modernas. Ao atualizar para Go 1.13, você pode aproveitar esses benefícios e melhorar a qualidade e o desempenho de seu código. É importante revisar as notas de lançamento completas em https://go.dev/doc/go1.13 para entender todas as mudanças e como elas podem afetar seus projetos. A introdução de erros embrulhados, em particular, representa um avanço significativo na forma como os erros são tratados e diagnosticados em Go, promovendo um código mais robusto e fácil de manter.