Pular para o conteúdo principal

victorstein.dev

Tag: Golang

17/100 Dias de Golang - Concorrência e Goroutines

# Concorrência

A concorrência é um dos pilares do desenvolvimento moderno, permitindo que programas executem múltiplas tarefas simultaneamente para melhor aproveitamento dos recursos computacionais. Em sistemas tradicionais, a concorrência é frequentemente implementada usando threads gerenciadas pelo sistema operacional, o que pode introduzir sobrecarga significativa devido à necessidade de alternância de contexto (context switching) e sincronização complexa.

Go foi projetado com a concorrência em mente, oferecendo uma abordagem mais eficiente e acessível por meio das goroutines. Essas unidades leves de execução permitem a construção de programas altamente concorrentes sem os custos elevados das threads convencionais. O runtime do Go gerencia automaticamente o escalonamento das goroutines, otimizando o uso do processador e simplificando o desenvolvimento de aplicações escaláveis e performáticas.

Ler Mais

16/100 Dias de Golang - Requests para APIs Externas - Parte 3

# Requests para APIs Externas - Parte 3

Go possui um forte compromisso com a biblioteca padrão. Isso significa que a maioria das funcionalidades que você precisa já estão disponíveis na biblioteca padrão. Porém, em alguns casos, você pode precisar de uma biblioteca externa. Vamos implantar o mesmo código usando a biblioteca [github.com/go-resty/resty/v3](https://github.com/go-resty/resty), que é uma biblioteca de cliente HTTP muito popular e fácil de usar.

package main

import (
	"fmt"
	"net/http"

	"github.com/go-resty/resty/v2"
)

func main() {
	client := resty.New()

	// Faz a requisição GET
	resp, err := client.R().
		Get("https://the-one-api.dev/v2/book")
	if err != nil {
		fmt.Println("Erro ao fazer request:", err)
		return
	}
	defer resp.RawResponse.Body.Close()

	// Verifica o status da resposta
	if resp.StatusCode() != http.StatusOK {
		fmt.Println("Erro na resposta:", resp.Status())
		return
	}

	// Imprime o corpo da resposta
	fmt.Println("Resposta:", string(resp.Body()))
}

A biblioteca resty facilita a criação de requisições HTTP. No exemplo acima, usamos o método R() para criar uma nova requisição e o método Get() para fazer a requisição GET. A resposta é retornada como um objeto Response, que possui métodos para acessar o corpo da resposta, o status da resposta e outros detalhes. Vou adicionar um exemplo adicionar um bearer token no cabeçalho da requisição. A única coisa que temos que fazer é adicionar o método SetAuthToken na requisição.

Ler Mais

15/100 Dias de Golang - Requests para APIs Externas - Parte 2

# Requests para APIs Externas - Parte 2

Agora que já sabemos como fazer um request básico, vamos incrementar um pouco. Adiciar a API Key, fazer um request para uma rota que precisa de autenticação. Vamos fazer um request para a rota /movie da API do Senhor dos Anéis, que precisa de autenticação. Para isso, precisamos passar a chave de API no cabeçalho da requisição.

package main

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

func main() {
	url := "https://the-one-api.dev/v2/movie"

	// Cria a request manualmente
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		fmt.Println("Erro ao criar request:", err)
		return
	}

	// Adiciona o header Authorization
	req.Header.Add("Authorization", "Bearer your-api-key-123")

	// Faz a requisição usando o client padrão
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println("Erro ao fazer request:", err)
		return
	}
	defer resp.Body.Close()

	// Lê a resposta
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Erro ao ler resposta:", err)
		return
	}


	fmt.Println("Resposta:", string(body))
}

A diferença nesse código é que criamos a requisição manualmente com o método http.NewRequest, onde passamos o método HTTP, a URL e o corpo da requisição (que no caso é nil). Depois, adicionamos o cabeçalho de autenticação com o método Header.Add. Por fim, fazemos a requisição com o método http.DefaultClient.Do, que retorna a resposta. Nesse caso o request vai falhar, pois não temos a chave de API. O último print vai imprimir o erro da requisição.

Ler Mais

14/100 Dias de Golang - Requests para APIs Externas - Parte 1

# Requests para APIs Externas - Parte 1

Vou tentar fazer alguma coisa mais prática, nesses últimos dias, foquei no estudo da base da linguagem, entender sintaxe, como as coisas funcionam, mas agora quero fazer algo mais prático. Vamos fazer uma aplicação que consome uma API externa, para isso, vamos usar a API do Senhor dos Anéis, que é uma API gratuita e fácil de usar. Para usar alguns endpoints, precisamos de uma chave de API, mas alguns endpoints não precisam. Para conseguir a chave, basta se cadastrar no site e gerar uma chave.

Ler Mais

13/100 Dias de Golang - Generics

# Generics

Seguindo com nosso exemplo do pacote utils, vamos analisar nossa função Soma

func Soma(a, b int) int {
    return a + b
}

Essa função Soma possui uma lógica muit simples, ele recebe dois inteiros e retorna um inteiro. Agora, imagine que queremos somar dois floats, teríamos que criar outra função SomaFloat que aceita dois floats e retorna um float.

func SomaFloat(a, b float64) float64 {
    return a + b
}

Essa função SomaFloat é praticamente igual a função Soma, a única diferença é que ela aceita dois floats e retorna um float. Aí agora tenho que fazer isso para todos os tipos de dados que eu quero somar e repetir para todas as operações matemáticas. Parece meio contra produtivo, não é mesmo? Antes da versão 1.18 do Go, resolveríaamos esse problema com interfaces, mas agora temos Generics! Veja como podemos resolver esse problema com Generics:

Ler Mais

12/100 Dias de Golang - Pacotes e Módulos

# Pacotes e Módulos

Temos várias funções e tipos em Go, mas é importante organizar essas funções e tipos em pacotes. Um pacote é um conjunto de arquivos Go no mesmo diretório que compartilham o mesmo package statement no topo do arquivo. O package statement é a primeira linha de um arquivo Go e define o nome do pacote. Por exemplo, o pacote fmt é um pacote padrão em Go que fornece funções para formatação de entrada e saída. Golang possui ínumeros pacotes que são padrão da linguagem. No site pkg.go.dev você pode encontrar todos os pacotes padrão da linguagem e os pacotes de terceiros, veja o exemplo do pacote Gin, que é um framework web para Go. Vamos criar um pacote utils com diversas funções.

Ler Mais

11/100 Dias de Golang - Ponteiros

# Ponteiros

Ponteiros são variáveis que armazenam endereços de memória de outras variáveis. Ponteiros são um conceito fundamental na programação, permitindo manipulação eficiente de memória e referências a valores. Golang possui gerenciamento automático de memória, porém a linguagem ainda oferece suporte explícito a ponteiros para maior controle. Veja esse exemplo em Go:

var count int = 10
var ptrCount *int = &count

fmt.Println("Valor de count:", count)
fmt.Println("Endereço de count:", &count)
fmt.Println("Valor de ptrCount:", ptrCount)
fmt.Println("Valor apontado por ptrCount:", *ptrCount)
Valor de count: 10
Endereço de count: 0xc000104040
Valor de ptrCount: 0xc000104040
Valor apontado por ptrCount: 1

Veja a explicação desse código, linha por linha. A primeira linha temos uma variável count do tipo int que armazena o valor 10.

Ler Mais

10/100 Dias de Golang - Interfaces

# Interfaces

Interfaces são um conceito muito presente em linguagem com orientação a objetos, de forma geral, as interfaces são um contrato que outras estruturas podem assinar, garantindo que elas implementem os métodos definidos na interface. Diferente de outras linguagens, como Java ou C#, Go implementa um modelo de interface implícita, onde qualquer tipo que implementa os métodos exigidos automaticamente implementa a interface. Veja como declaramos uma inteface:

Ler Mais

9/100 Dias de Golang - Structs 2

# Structs

Só para revisar o que vimos no Dia 5 - Structs. Structs são tipos de dados compostos que são usados para agrupar diferentes tipos de dados. Eles são usados para criar tipos de dados personalizados. A sintaxe para criar um struct é a seguinte:

type linguagem_de_programacao struct {
	nome string
	ano  int
	criador []string	
}

var go = linguagem_de_programacao{
	nome: "Go",
	ano: 2009,
	criador: []string{"Robert Griesemer", "Rob Pike", "Ken Thompson"},
}

fmt.Println(go.nome) // Go
go.nome = "Golang"
fmt.Println(go.nome) // Golang

# Structs com métodos

Structs podem ter métodos associados a eles, como se fosse os métodos de uma classe em POO. Métodos são funções que pertencem a um tipo de dados específico. Veja a sintaxe para criar um método:

Ler Mais

8/100 Dias de Golang - Funções

# Funções

Já vimos várias funções até agora, len, cap, append e outras. Vamos ver como criar nossas funções.

# Sintaxe da função

A sintaxe de uma função é a seguinte:

func nome_da_funcao(parametro1 tipo, parametro2 tipo) (retorno1 tipo, retorno2 tipo) {
	// Lógica da função
}

A função nome_da_funcao recebe dois parâmetros, parametro1 e parametro2, ambos do tipo tipo. A função retorna dois valores, retorno1 e retorno2, ambos do tipo tipo. Veja esse exemplo mais “real”:

Ler Mais