Cealaltă față a API-ului
Programele Go nu sunt doar servere — ele apelează și API-uri: aduc date, vorbesc cu servicii, integrează furnizori externi. Partea de client din net/http înseamnă trei obiceiuri:
1. trimite cererea (http.Get, http.Post sau http.NewRequest pentru control complet),
2. întotdeauna defer resp.Body.Close(),
3. verifică codul de stare înainte de a te încrede în corpul răspunsului.
Demonstrațiile de mai jos apelează un server de test local, așa că rezultatele sunt stabile — codul clientului este exact cel pe care l-ai îndrepta către un URL real.
GET și decodificare
Sarcina de zi cu zi: faci GET pe un URL, verifici starea, decodifici JSON-ul direct din corpul răspunsului în structuri cu json.NewDecoder(resp.Body).Decode(&value) — fără niciun șir de caractere intermediar.
Aduci o listă în structuri
Corpul răspunsului se decodifică direct în []User, iar de acolo încolo sunt date Go obișnuite — parcurse în buclă și afișate câmp cu câmp.
Ieșire: program Go și rezultatul capturat
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, `[{"id": 1, "name": "Ana"}, {"id": 2, "name": "Ben"}]`)
}))
defer server.Close()
resp, err := http.Get(server.URL + "/users")
if err != nil {
fmt.Println("cererea a eșuat:", err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Println("stare neașteptată:", resp.Status)
return
}
var users []User
if err := json.NewDecoder(resp.Body).Decode(&users); err != nil {
fmt.Println("JSON invalid:", err)
return
}
for _, u := range users {
fmt.Printf("utilizator %d: %s\n", u.ID, u.Name)
}
}
POST cu un corp JSON
Trimiterea datelor este imaginea în oglindă: serializezi structura, împachetezi octeții într-un reader, faci POST cu tipul de conținut corect — apoi decodifici răspunsul serverului, care aici conține id-ul atribuit de server.
Trimiți o structură, citești răspunsul
Structura pleacă sub formă de JSON, iar înregistrarea creată se întoarce cu noul ei id — întreg drumul de scriere al unui client de API într-un singur program mic.
Ieșire: program Go și rezultatul capturat
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var u User
json.NewDecoder(r.Body).Decode(&u)
u.ID = 7 // serverul atribuie id-ul
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(u)
}))
defer server.Close()
payload, _ := json.Marshal(User{Name: "Cleo"})
resp, err := http.Post(server.URL+"/users", "application/json",
bytes.NewReader(payload))
if err != nil {
fmt.Println("cererea a eșuat:", err)
return
}
defer resp.Body.Close()
var created User
json.NewDecoder(resp.Body).Decode(&created)
fmt.Println("stare: ", resp.Status)
fmt.Printf("creat: %+v\n", created)
}