HTTP client
Бодит програм ихэвчлэн гадны API-тай харилцдаг — цаг агаарын мэдээ авах, төлбөр боловсруулах, мэдэгдэл илгээх гэх мэт. Go-ийн net/http package нь суурилагдсан HTTP client-тэй бөгөөд ямар нэмэлт library шаардлагагүй.
GET хүсэлт илгээх
Хамгийн энгийн GET хүсэлт:
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 хариу авах:
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 өгөгдөл илгээх:
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 шаардлагатай:
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 сервер бичих боломж олгодог.