Go / HTTP client

HTTP client

Бодит програм ихэвчлэн гадны API-тай харилцдаг — цаг агаарын мэдээ авах, төлбөр боловсруулах, мэдэгдэл илгээх гэх мэт. Go-ийн net/http package нь суурилагдсан HTTP client-тэй бөгөөд ямар нэмэлт library шаардлагагүй.

GET хүсэлт илгээх

Хамгийн энгийн GET хүсэлт:

go
package main

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

func main() {
    resp, err := http.Get("https://httpbin.org/get")
    if err != nil {
        fmt.Println("Хүсэлт илгээхэд алдаа:", err)
        return
    }
    defer resp.Body.Close() // response body заавал хаах

    fmt.Println("Статус:", resp.Status)
    fmt.Println("Статус код:", resp.StatusCode)

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Хариу уншихад алдаа:", err)
        return
    }

    fmt.Println("Хариу:")
    fmt.Println(string(body))
}

resp.Body.Close() нь маш чухал — defer ашиглан хэзээ ч мартахгүй байх хэрэгтэй. Хаагаагүй бол сүлжээний нөөц алдагдана.

JSON API-аас өгөгдөл авах

Бодит ажлын хамгийн нийтлэг хэв маяг — API-аас JSON хариу авах:

go
package main

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

type Post struct {
    ID     int    `json:"id"`
    Title  string `json:"title"`
    Body   string `json:"body"`
    UserID int    `json:"userId"`
}

func getPost(id int) (*Post, error) {
    url := fmt.Sprintf("https://jsonplaceholder.typicode.com/posts/%d", id)

    resp, err := http.Get(url)
    if err != nil {
        return nil, fmt.Errorf("хүсэлт амжилтгүй: %w", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("буруу статус: %d", resp.StatusCode)
    }

    var post Post
    err = json.NewDecoder(resp.Body).Decode(&post)
    if err != nil {
        return nil, fmt.Errorf("JSON задлахад алдаа: %w", err)
    }

    return &post, nil
}

func main() {
    post, err := getPost(1)
    if err != nil {
        fmt.Println("Алдаа:", err)
        return
    }

    fmt.Printf("Гарчиг: %s\n", post.Title)
    fmt.Printf("Хэрэглэгч: %d\n", post.UserID)
}

json.NewDecoder(resp.Body).Decode(&post) нь response body-г шууд decode хийдэг — io.ReadAll хийгээд json.Unmarshal дуудахаас хурдан.

POST хүсэлт — JSON илгээх

Серверт JSON өгөгдөл илгээх:

go
package main

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

type NewPost struct {
    Title  string `json:"title"`
    Body   string `json:"body"`
    UserID int    `json:"userId"`
}

func createPost(post NewPost) error {
    data, err := json.Marshal(post)
    if err != nil {
        return err
    }

    resp, err := http.Post(
        "https://jsonplaceholder.typicode.com/posts",
        "application/json",
        bytes.NewBuffer(data),
    )
    if err != nil {
        return fmt.Errorf("хүсэлт амжилтгүй: %w", err)
    }
    defer resp.Body.Close()

    fmt.Println("Статус:", resp.Status)
    return nil
}

func main() {
    newPost := NewPost{
        Title:  "Go хэлний тухай",
        Body:   "Go бол маш хурдан хэл юм.",
        UserID: 1,
    }

    err := createPost(newPost)
    if err != nil {
        fmt.Println("Алдаа:", err)
    }
}

Header болон timeout тохируулах

Бодит ажлын хүсэлтэд authorization header болон timeout шаардлагатай:

go
package main

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

func main() {
    // Timeout тохируулсан client үүсгэх
    client := &http.Client{
        Timeout: 10 * time.Second,
    }

    req, err := http.NewRequest("GET", "https://httpbin.org/headers", nil)
    if err != nil {
        fmt.Println("Хүсэлт үүсгэхэд алдаа:", err)
        return
    }

    // Header нэмэх
    req.Header.Set("Authorization", "Bearer токен_энд")
    req.Header.Set("Accept", "application/json")
    req.Header.Set("User-Agent", "MyGoApp/1.0")

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Хүсэлт илгээхэд алдаа:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}

http.DefaultClient-д timeout байхгүй — бодит програмд заавал тохируулах хэрэгтэй. Тохируулаагүй бол сервер хариу өгөхгүй байхад програм мөнхөд хүлээж болно.

Дараагийн хичээлд:

Энэ удаа эргэж — HTTP сервер үүсгэж хүсэлт хүлээн авах талыг сурна. Go-ийн net/http package маш хурдан HTTP сервер бичих боломж олгодог.