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.