---
title: "Go 1.20: Novidades e Recursos"
url: "https://golang.com.br/blog/go-1-20/"
markdown_url: "https://golang.com.br/blog/go-1-20.MD"
description: "Go 1.20 trouxe PGO (Profile-Guided Optimization) preview, coverage profiling para binarios, errors.Join, melhorias no crypto/ecdh e slice-to-array nativo."
date: "2023-02-01"
author: "Golang Brasil"
---

# Go 1.20: Novidades e Recursos

Go 1.20 trouxe PGO (Profile-Guided Optimization) preview, coverage profiling para binarios, errors.Join, melhorias no crypto/ecdh e slice-to-array nativo.


# Go 1.20: As Novidades da Linguagem e do Ecossistema

A versão 1.20 da linguagem Go foi lançada em 1 de fevereiro de 2023, trazendo consigo uma série de melhorias e novidades que visam aprimorar a experiência do desenvolvedor, otimizar o desempenho das aplicações e fortalecer o ecossistema Go. Este artigo explora as principais mudanças introduzidas nesta versão, oferecendo exemplos práticos e referências à documentação oficial para auxiliar na transição e adoção das novas funcionalidades.

## Principais Novidades

Go 1.20 foca em refinamentos e adições que impactam diretamente a produtividade e eficiência do desenvolvimento. As principais novidades incluem:

*   **Suporte a Profile-Guided Optimization (PGO)**: Otimização guiada por perfil, que permite ao compilador otimizar o código com base em dados de execução reais.
*   **Melhorias na sintaxe de conversão de `slice` para `array`**: Uma sintaxe simplificada e mais segura para conversões entre `slice` e `array`.
*   **Novas funções no pacote `errors`**: Funções para facilitar o tratamento e inspeção de erros.
*   **Melhorias no `unsafe` package**: Adição de funções para conversão mais segura de `unsafe.Pointer` para `slice`.

### Profile-Guided Optimization (PGO)

Profile-Guided Optimization (PGO) é uma técnica de otimização de compilador que utiliza informações sobre o comportamento de um programa em tempo de execução para tomar decisões de otimização mais eficazes. Em Go 1.20, o PGO foi introduzido como um recurso experimental, permitindo que os desenvolvedores otimizem seus programas com base em dados reais de performance.

O processo de PGO envolve as seguintes etapas:

1.  **Construção do binário com instrumentação**: O compilador insere código de instrumentação no binário para coletar dados de performance durante a execução.
2.  **Execução do binário instrumentado**: O binário é executado em um ambiente representativo da carga de trabalho real. Durante a execução, o binário coleta dados sobre quais funções são chamadas com mais frequência, quais ramificações são tomadas com mais frequência e outros dados relevantes.
3.  **Compilação com o perfil coletado**: O compilador utiliza os dados coletados durante a execução do binário instrumentado para otimizar o código. Por exemplo, o compilador pode in-line funções chamadas com frequência ou otimizar ramificações com base na probabilidade de serem tomadas.

Para utilizar o PGO, siga os seguintes passos:

1.  **Coletar o perfil:**

    ```bash
    go test -bench=. -cpuprofile=cpu.pprof
    go tool pprof -proto ./cpu.pprof > profile.pprof
    ```

    Este comando executa os testes de benchmark e gera um arquivo de perfil (`profile.pprof`) contendo informações sobre o uso da CPU.

2.  **Construir o binário com PGO:**

    ```bash
    go build -pgo=auto .
    ```

    Este comando instrui o compilador Go a utilizar o arquivo de perfil para otimizar o binário.  O `auto` significa que o Go tentará encontrar um arquivo de perfil chamado `default.pgo` no diretório do pacote. Também é possível especificar um arquivo de perfil diferente com `-pgo=/path/to/profile.pprof`.

**Observações:**

*   O PGO é mais eficaz quando o perfil é coletado em um ambiente que representa a carga de trabalho real do programa.
*   O PGO pode não ser benéfico para todos os programas. Em alguns casos, o PGO pode até mesmo degradar o desempenho.
*   O PGO é uma técnica experimental e pode mudar em versões futuras do Go.

### Conversão Simplificada de Slice para Array

Go 1.20 introduz uma sintaxe mais concisa e segura para converter slices em arrays. Anteriormente, a conversão exigia o uso de ponteiros e `unsafe`, o que podia ser propenso a erros e difícil de ler. A nova sintaxe simplifica o processo e fornece verificação de tipo em tempo de compilação, reduzindo o risco de erros em tempo de execução.

A sintaxe anterior para converter um slice em um array era:

```go
s := []int{1, 2, 3}
a := (*[3]int)(s) // Converte o slice 's' para um array de 3 inteiros
```

Com Go 1.20, a conversão pode ser feita diretamente:

```go
s := []int{1, 2, 3}
a := [3]int(s) // Converte o slice 's' para um array de 3 inteiros
```

Esta nova sintaxe oferece as seguintes vantagens:

*   **Legibilidade**: O código fica mais fácil de ler e entender.
*   **Segurança**: O compilador verifica se o tamanho do slice corresponde ao tamanho do array, evitando erros em tempo de execução.
*   **Simplicidade**: A sintaxe é mais concisa e direta.

**Exemplo:**

```go
package main

import "fmt"

func main() {
	s := []int{1, 2, 3}
	a := [3]int(s) // Converte o slice 's' para um array de 3 inteiros
	fmt.Println(a)  // Imprime: [1 2 3]

	// Tentativa de conversão com tamanho incorreto resulta em erro de compilação
	// b := [4]int(s) // Erro de compilação: cannot convert s (type []int) to type [4]int
	_ = a
}
```

Este exemplo demonstra a nova sintaxe de conversão e mostra como o compilador detecta erros de tamanho incompatível.  A linha comentada que tenta converter o slice `s` em um array de tamanho 4 resulta em um erro de compilação, garantindo a segurança da operação.

### Novas Funções no Pacote `errors`

O pacote `errors` em Go 1.20 recebeu algumas adições importantes que facilitam o tratamento e a inspeção de erros. As novas funções são projetadas para simplificar tarefas comuns, como desembrulhar erros e verificar se um erro pertence a uma determinada classe.

As principais adições são:

*   `errors.Join`: Combina múltiplos erros em um único erro que implementa a interface `error` e contém todos os erros originais.
*   `errors.Is`: Simplifica a verificação se um erro na cadeia de erros corresponde a um erro específico.
*   `errors.As`: Simplifica a obtenção do erro específico na cadeia de erros.

**Exemplo de `errors.Join`:**

```go
package main

import (
	"errors"
	"fmt"
)

func main() {
	err1 := errors.New("erro 1")
	err2 := errors.New("erro 2")
	err3 := errors.New("erro 3")

	combinedErr := errors.Join(err1, err2, err3)

	fmt.Println(combinedErr)
}
```

Este exemplo demonstra como combinar múltiplos erros em um único erro usando `errors.Join`. O resultado é um erro que contém todos os erros originais.

**Exemplo de `errors.Is`:**

```go
package main

import (
	"errors"
	"fmt"
)

var ErrNotFound = errors.New("não encontrado")

func buscar(id int) error {
	// Simula uma busca que pode retornar ErrNotFound
	if id < 0 {
		return fmt.Errorf("id inválido: %w", ErrNotFound)
	}
	return nil
}

func main() {
	err := buscar(-1)
	if errors.Is(err, ErrNotFound) {
		fmt.Println("Erro: Recurso não encontrado")
	} else if err != nil {
		fmt.Println("Outro erro:", err)
	}
}
```

Este exemplo demonstra como usar `errors.Is` para verificar se um erro na cadeia de erros corresponde a um erro específico (`ErrNotFound`).

**Exemplo de `errors.As`:**

```go
package main

import (
	"errors"
	"fmt"
)

type MyError struct {
	Message string
}

func (e *MyError) Error() string {
	return e.Message
}

func processar() error {
	return fmt.Errorf("erro ao processar: %w", &MyError{Message: "detalhes do erro"})
}

func main() {
	err := processar()
	var myErr *MyError
	if errors.As(err, &myErr) {
		fmt.Println("Erro personalizado encontrado:", myErr.Message)
	} else if err != nil {
		fmt.Println("Outro erro:", err)
	}
}
```

Este exemplo demonstra como usar `errors.As` para obter um erro específico na cadeia de erros. Se o erro for do tipo `MyError`, a variável `myErr` será preenchida com o erro correspondente.

### Melhorias no `unsafe` Package

O pacote `unsafe` é usado para realizar operações que não são seguras para a memória, como acessar a memória diretamente através de ponteiros. Em Go 1.20, foram adicionadas novas funções ao pacote `unsafe` para tornar a conversão de `unsafe.Pointer` para `slice` mais segura.

A principal adição é a função `SliceData`:

```go
func SliceData(slice []Type) *Type
```

Esta função retorna um ponteiro para o primeiro elemento do slice.  Juntamente com `SliceData`, as funções `Slice` e `String` permitem criar slices e strings a partir de ponteiros e comprimentos, evitando o uso direto de aritmética de ponteiros.

**Exemplo:**

```go
package main

import (
	"fmt"
	"unsafe"
)

func main() {
	arr := [4]int{10, 20, 30, 40}
	ptr := unsafe.Pointer(&arr[0])

	// Cria um slice a partir do ponteiro e do comprimento
	slice := unsafe.Slice((*int)(ptr), 4)

	fmt.Println(slice) // Imprime: [10 20 30 40]
}
```

Este exemplo demonstra como criar um slice a partir de um ponteiro usando a função `unsafe.Slice`.  É importante notar que o uso do pacote `unsafe` deve ser feito com cautela, pois pode levar a erros de memória e comportamento imprevisível.  A introdução de `SliceData` e `Slice` visa mitigar alguns desses riscos, fornecendo uma interface mais segura para trabalhar com ponteiros.

## Melhorias de Performance

Embora Go 1.20 não traga mudanças drásticas em termos de performance em comparação com as versões anteriores, a introdução do PGO (Profile-Guided Optimization) tem o potencial de melhorar significativamente o desempenho de aplicações específicas.  O PGO permite que o compilador otimize o código com base em dados de execução reais, resultando em um código mais eficiente e rápido.

Além do PGO, outras otimizações menores no compilador e no garbage collector também contribuem para um desempenho geral ligeiramente melhorado.

## Mudanças na Biblioteca Padrão

Além das novas funções no pacote `errors` e das melhorias no pacote `unsafe`, Go 1.20 também inclui outras mudanças na biblioteca padrão:

*   **Pacote `net/http`**: Adicionado suporte para trailers HTTP/2.
*   **Pacote `time`**: Adicionado suporte para análise de formatos de data e hora mais flexíveis.
*   **Pacote `crypto/tls`**: Melhorias na segurança e no desempenho.

## Como Atualizar

Para atualizar para Go 1.20, siga os seguintes passos:

1.  **Remova a versão anterior do Go**:

    ```bash
    rm -rf /usr/local/go
    ```

    (Adapte o caminho se a instalação estiver em um local diferente)

2.  **Baixe a nova versão do Go**:

    Acesse o site oficial do Go ([https://go.dev/dl/](https://go.dev/dl/)) e baixe o pacote de instalação correspondente ao seu sistema operacional.

3.  **Instale a nova versão do Go**:

    Siga as instruções de instalação fornecidas no site oficial do Go.  Geralmente, isso envolve extrair o pacote baixado para um diretório (por exemplo, `/usr/local/go`) e configurar as variáveis de ambiente `GOROOT` e `PATH`.

4.  **Verifique a instalação**:

    Abra um terminal e execute o seguinte comando:

    ```bash
    go version
    ```

    O comando deve exibir a versão instalada do Go (por exemplo, `go version go1.20 linux/amd64`).

5.  **Atualize os módulos**:

    Após a instalação, execute o seguinte comando no diretório do seu projeto para atualizar as dependências para as versões mais recentes:

    ```bash
    go get -u all
    go mod tidy
    ```

## Conclusão Prática

Go 1.20 representa uma evolução significativa na linguagem, trazendo melhorias que impactam diretamente a produtividade do desenvolvedor, a segurança do código e o desempenho das aplicações. A introdução do PGO, a simplificação da conversão de slices para arrays e as novas funções no pacote `errors` são apenas alguns exemplos das novidades que tornam Go 1.20 uma versão valiosa para qualquer desenvolvedor Go.

A atualização para Go 1.20 é recomendada para todos os desenvolvedores Go, pois permite aproveitar as novas funcionalidades, as melhorias de desempenho e as correções de bugs.  Ao adotar as novas funcionalidades e otimizações, os desenvolvedores podem criar aplicações mais eficientes, seguras e fáceis de manter.  Consulte as release notes oficiais para uma lista completa de mudanças e detalhes adicionais: [https://go.dev/doc/go1.20](https://go.dev/doc/go1.20).
