http in GO tutorial

Go's standard library provides robust, built-in support for both creating HTTP servers and making HTTP requests as a client via the net/http package.

Go's standard library provides robust, built-in support for both creating HTTP servers and making HTTP requests as a client via the net/http package.

In python,python ask entire response body and put it in r.text in go lang http.Get() only return headers but connection keeps open The server has already sent (or is sending) the entire response over the TCP connection and the data is kernel network buffers waiting to be read.

response,error := http.Get("https://api.restful-api.dev/objects/4")
    if error != nil{
            panic(error)
        }

must run as it Schedules response.Body.Close() to run when main() exits defer response.Body.Close()

defer refers to even if the code crash still execute it

it realeases the file descriptor so the go can reuse the tcp file descriptor connection to be returned to the connection pool for reuse (HTTP keep-alive). can also put response.Body.Close() at the end but connection may still be open if it crashes

reading response as text

io.ReadAll(resp.Body) when you run this This drains data from the kernel's network buffers (where the server's response is already sitting) into our program's memory as a []byte slice. No additional request is made to the server - we're just consuming data that was already transmitted.

b, err := io.ReadAll(response.Body)
    if err != nil {
        panic(err)
    }
fmt.Println(string(b))

reading response as json

"encoding/json" import is required to get all json funtionality

first we have to make a struct to store the json data in format its not like python which gives automatically its for men >:)

type PhoneRes struct {
    ID   string `json:"id"`
    Name string `json:"name"`
    Data Dat    `json:"data"`
}

type Dat struct {
    Price float64 `json:"price"` // number in JSON → float64 in Go
    Color string  `json:"color"`
}

this is for {"id":"4","name":"Apple iPhone 11, 64GB","data":{"price":389.99,"color":"Purple"}}

now we have to convert response.Body into this struct for doing that we do

json.NewDecoder(response.Body) -> json.NewDecoder() build upon io.ReadAll which drain the from buffers and then convert it into a struct

note:- if you run io.ReadAll(response.Body) before this it will drain the data and it will raise a error

to read from already drained data we use:

json.Unmarshal(data, &struct) data is the []bytes this reads from existing bytes and convert it into struct

all in action:

package main

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


type PhoneRes struct {
    ID   string `json:"id"`
    Name string `json:"name"`
    Data Dat    `json:"data"`
}

type Dat struct {
    Price float64 `json:"price"` // number in JSON → float64 in Go
    Color string  `json:"color"`
}


func main(){

    response,error := http.Get("https://api.restful-api.dev/objects/4")

    if error != nil{
            panic(error)
        }
    defer response.Body.Close() 

    b, err := io.ReadAll(response.Body)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))

    var phone PhoneRes 

    json.NewDecoder() 
    decoder := json.NewDecoder(response.Body)
    if err := decoder.Decode(&phone); err != nil {
        fmt.Println("error decoding response body")
        return
    }

    fmt.Println(phone.Data.Price)


    derr := json.Unmarshal(b, &phone);
    if derr != nil {
        fmt.Println("error decoding response body")
        return
    }
    fmt.Println(phone.Data.Price)
    fmt.Println(response.Status)
    fmt.Println(response.Header)

}

creating a request (GET)

we only looked at http.Get() but hold up!

we also have http.NewRequest(method,url,body) this give us more control to request. this create a request object

note:- it dosent open socket send request or anything we have to make http.Client for that

u can use req.Header.Set("User-Agent", "my-go-client/1.0") to set headers a

client := http.Client{}
response, err := client.Do(req)
if err != nil {
    fmt.Println("error making request: ", err)
    return
}
defer response.Body.close()

now make a client to actually send the request

    request,error := http.NewRequest("GET","https://google.com",nil)

    request.Header.Set("User-Agent", "my-go-client/1.0")

    if error != nil{
        fmt.Println("error bro")
        return
    }

    client := &http.Client{}
    resp, err := client.Do(request)
    if err != nil{
        fmt.Println("error bro 2")
        return
    }
    defer resp.Body.Close()

    b, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))

creating a request (POST)

main difference between get and post is post has body or payload which we send. that can we crafted with: json.Marshal(Struct)

like in get request we filled the struct with data now we convert that struct into a json

first create a json struct

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

now convert it into json

u := User{Name: "Alice", Age: 20}

    body, err := json.Marshal(u)
    if err != nil {
        log.Fatal(err)
    }

now send the rocket bytes.NewReader convert into buffer (bytes)

req, err := http.NewRequest("POST", "https://httpbin.org/post", bytes.NewReader(body))

full code:

    u := User{Name: "Alice", Age: 20}

    body, err := json.Marshal(u)
    if err != nil {
        log.Fatal(err)
    }

    req, err := http.NewRequest("POST", "https://httpbin.org/post", bytes.NewReader(body))
    if err != nil {
        log.Fatal(err)
    }

    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Accept", "application/json")

    client := &http.Client{Timeout: 10 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    log.Println("Status:", resp.Status)
Coding with Gromax
← Back to all blog posts View Source on GitHub