Trabalhando com Json e Go
Tags: json, go
Published: 2022-03-25 14:33:03

Pra mim que vim do `javascript` onde o json é algo tão "banal", entender o funcionamento com Go foi um tanto quanto diferente.

O Go tem uma pegada muito grande com ponteiros e bytes, então, de primeiro momento, é meio cabuloso saber que uma variável que foi passada como parâmetro vai ter o retorno da função diretamente no local da memória em que ela foi alocada e por aí vai.

Em `javascript`, uma estrutura do tipo:

```json
{
  "campo": "qualquer coisa",
  "numero": 10
}
```
é entendível na hora, contudo, em Go, a coisa não é bem assim.

Bora ver um exemplo prático e eu vou detalhar coisa por coisa.

```go
package main

import (
	"encoding/json"
	"fmt"
)

type Car struct {
	Color string `json:"color"`
	Model string `json:"model"`
}

func main() {
	car := Car{"Black", "Lancer"}

	b, err := json.Marshal(car)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(string(b))
}

```

Explicando:
```go
package main
```
estou definindo que o conteúdo dese arquivo pertence ao pacote `main`. Por exemplo, se eu tivesse uma estrutura
```shell
app
   services
       main.go
   controllers
       main.go
       users.go
   main.go
```
Eu poderia dizer que `services/main.go` pertence ao pacote `services`, portanto, `package services`, `controllers/main.go` e `controllers/users.go` ao pacote `controllers` e por aí vai. Mas enfim, a ideia aqui é explicar json com go, outros detalhes eu vou abordar em outro capítulo. Prossigamos ...

```go
type Car struct {
	Color string `json:"color"`
	Model string `json:"model"`
}
```
Aqui eu estou "definindo o meu objeto". Não sei se seria a melhor comparação, mas sabe o `Type` do `typescript`? Quase isso! Diferença que aqui eu consigo passar esse cara como ponteiro e trabalhar diretamente nele.

```go
func main() {
	car := Car{"Black", "Lancer"}
//  car := Car{
//    Color: "Black",
//    Model: "Lancer",
//  }
        ...
```
Aqui eu to dizendo: _cria a varíavel car e atribui à ela o tipo Car com os seguintes valores ..._.
Note que existem duas maneiras de atribuir uma struct à uma variável. Pode ser parecido como é em `javascript`, ou passar os valores diretamente na `struct` sem precisar inserir as chaves. Em `structs` mais simples é até viável, mas pensa num negócio gigante passar os valores sem saber o que é o que. 

Ah, só uma observação: isso `:=` é diferente de `=`.
No primeiro, eu estou criando a variável e reservando ela em memória, ou seja, dando vida à ela e lhe atribuindo um valor,
enquanto que no segundo, a variável já existe em memória e eu estou reatribuindo um valor à ela. 0.o

Continuando ...

Aqui o bicho pega

```go
b, err := json.Marshal(car)

if err != nil {
   fmt.Println(err)
}

fmt.Println(string(b))
```
O go pode trazer mais de um retorno numa função. Uma espécie de tupla, por assim dizer. 

E também em Go, as chamadas de funções geralmente são o nome do pacote e a função. No nosso exemplo, estamos chamando do pacote `json` a função `Marshal`.

A função `Marshal` retorna dois resultados: um `slice` de bytes (é praticamente um array mas sem limite como um array) e um erro. Como parâmetro, essa função espera uma variável do tipo `struct` que no nosso caso é `car`.

Logo após é feita a checagem pra garantir que não houve algum erro (lembrando que o foco aqui é json e não tratativas de erros, uso correto da linguagem nem nada).

E depois, por último, convertemos aqueles bytes em uma string para ser mostrado pelo `Println`, nosso `console.log` do `Go`.

E pah, a saída que teremos vai ser
```shell
{"color":"Black","model":"Lancer"}
```

Outras observações cabulosas do Go:

Quando se define uma struct, as "chaves" dela, para serem lidas por qualquer função ou algo do tipo, precisam ser em letras maiúsculas. Portanto, se eu tivesse:
```go
type Car struct {
	color string `json:"color"`
	model string `json:"model"`
}
```
a saída seria simplesmente
```shell
{}
```
uma vez que os atributos dessa `struct` não foram exportados (implicitamente escrever iniciando em letra minúscula fala pro Go que o atributo daquela struct não é para ser exportado).

Mas fica estranho né, imagina uma api que esteja esperando esse objeto:
```json
{
   "color": "black",
   "model": "Lancer"
}
```
mas estamos enviando "Color" e "Model" no body da request.

Para resolver isso, colocamos aquele ``json:"color"`` na frente do atributo da `struct`. Com isso estamos dizendo para o Go: Cara, a `struct Car` tem o atributo `Color`, então, internamente, a gente referencia `Color` mas externamente, ou seja, se formos enviar esse json pra fora do programa ou vamos receber esse json de algum outro lugar, ele vai ter o campo "color" e não "Color".

É, isso é Go ...

Essa é a primeira parte, transformando uma struct em um json. Vamos ter a segunda parte onde vamos transformar um json em uma struct.

Te espero lá!!!