Basics of Go Language: net/http Package

Source:jianshu.com/p/8bf41fef20c7

【Introduction】This article introduces the Go language’s standard library net/http.

The built-in net/http package in Go is excellent, providing implementations for both HTTP clients and servers.

Introduction to net/http

The built-in net/http package in Go provides implementations for both HTTP clients and servers.

HTTP Protocol

The HyperText Transfer Protocol (HTTP) is the most widely used network transfer protocol on the Internet, and all WWW files must adhere to this standard. The initial design purpose of HTTP was to provide a method for publishing and receiving HTML pages.

HTTP Client

Basic HTTP/HTTPS Requests

The Get, Head, Post, and PostForm functions issue HTTP/HTTPS requests.

resp, err := http.Get("http://example.com/")...resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)...resp, err := http.PostForm("http://example.com/form", url.Values{"key": {"Value"}, "id": {"123"}})

After using the response, the program must close the response body.

resp, err := http.Get("http://example.com/")if err != nil {    // handle error}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)// ...
👉Click to receive Go backend development resources

GET Request Example

Using the net/http package, write a simple client to send an HTTP request. The code is as follows:

package main
import (    "fmt"    "io/ioutil"    "net/http")
func main() {    resp, err := http.Get("https://www.liwenzhou.com/")    if err != nil {        fmt.Printf("get failed, err:%v\n", err)        return    }    defer resp.Body.Close()    body, err := ioutil.ReadAll(resp.Body)    if err != nil {        fmt.Printf("read from resp.Body failed, err:%v\n", err)        return    }    fmt.Print(string(body))}

Save the above code, compile it into an executable file, and execute it to print the content of the liwenzhou.com homepage in the terminal. Our browser is essentially a client that sends and receives HTTP protocol data. When we access a webpage through the browser, we are actually receiving HTTP data from the website’s server, and the browser renders the webpage according to HTML, CSS, and other rules.

GET Request with Parameters Example

Parameters for GET requests need to be handled using the Go language’s built-in net/url standard library.

func main() {    apiUrl := "http://127.0.0.1:9090/get"    // URL param    data := url.Values{}    data.Set("name", "mi")    data.Set("age", "18")    u, err := url.ParseRequestURI(apiUrl)    if err != nil {        fmt.Printf("parse url requestUrl failed, err:%v\n", err)    }    u.RawQuery = data.Encode() // URL encode    fmt.Println(u.String())    resp, err := http.Get(u.String())    if err != nil {        fmt.Printf("post failed, err:%v\n", err)        return    }    defer resp.Body.Close()    b, err := ioutil.ReadAll(resp.Body)    if err != nil {        fmt.Printf("get resp failed, err:%v\n", err)        return    }    fmt.Println(string(b))}

The corresponding server-side HandlerFunc is as follows:

func getHandler(w http.ResponseWriter, r *http.Request) {    defer r.Body.Close()    data := r.URL.Query()    fmt.Println(data.Get("name"))    fmt.Println(data.Get("age"))    answer := `{"status": "ok"}`    w.Write([]byte(answer))}

POST Request Example

The above demonstrated an example of sending a GET request using the net/http package. The example code for sending a POST request is as follows:

package main
import (    "fmt"    "io/ioutil"    "net/http"    "strings")
// net/http post demo
func main() {    url := "http://127.0.0.1:9090/post"    // form data    //contentType := "application/x-www-form-urlencoded"    //data := "name=mi&age=18"    // json    contentType := "application/json"    data := `{"name":"mi","age":18}`    resp, err := http.Post(url, contentType, strings.NewReader(data))    if err != nil {        fmt.Printf("post failed, err:%v\n", err)        return    }    defer resp.Body.Close()    b, err := ioutil.ReadAll(resp.Body)    if err != nil {        fmt.Printf("get resp failed, err:%v\n", err)        return    }    fmt.Println(string(b))}

The corresponding server-side HandlerFunc is as follows:

func postHandler(w http.ResponseWriter, r *http.Request) {    defer r.Body.Close()    // 1. When the request type is application/x-www-form-urlencoded, parse the form data    r.ParseForm()    fmt.Println(r.PostForm) // Print form data    fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))    // 2. When the request type is application/json, read data from r.Body    b, err := ioutil.ReadAll(r.Body)    if err != nil {        fmt.Printf("read request.Body failed, err:%v\n", err)        return    }    fmt.Println(string(b))    answer := `{"status": "ok"}`    w.Write([]byte(answer))}

Custom Client

To manage HTTP client headers, redirect policies, and other settings, create a Client:

client := &http.Client{    CheckRedirect: redirectPolicyFunc,}resp, err := client.Get("http://example.com")// ...req, err := http.NewRequest("GET", "http://example.com", nil)// ...req.Header.Add("If-None-Match", `W/"wyzzy"`)resp, err := client.Do(req)// ...

Custom Transport

To manage proxies, TLS configurations, keep-alive, compression, and other settings, create a Transport:

tr := &http.Transport{    TLSClientConfig:    &tls.Config{RootCAs: pool},    DisableCompression: true,}client := &http.Client{Transport: tr}resp, err := client.Get("https://example.com")

Both Client and Transport types can be safely used by multiple goroutines simultaneously. For efficiency, they should be established once and reused as much as possible.

Server

Default Server

ListenAndServe starts an HTTP server using the specified listening address and handler. The handler parameter is usually nil, which indicates using the package variable DefaultServeMux as the handler.

The Handle and HandleFunc functions can add handlers to DefaultServeMux.

http.Handle("/foo", fooHandler)http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))})log.Fatal(http.ListenAndServe(":8080", nil))

Default Server Example

Use the net/http package in Go to write a simple server that receives HTTP requests. The net/http package is a further encapsulation of the net package, specifically designed to handle HTTP protocol data. The specific code is as follows:

// http serverpackage main
import (    "fmt"    "net/http")
func sayHello(w http.ResponseWriter, r *http.Request) {    fmt.Fprintln(w, "Hello Shanghai!")}
func main() {    http.HandleFunc("/", sayHello)    err := http.ListenAndServe(":9090", nil)    if err != nil {        fmt.Printf("http server failed, err:%v\n", err)        return    }}

Compile the above code and execute it, then open your browser and enter 127.0.0.1:9090 in the address bar to see the following page.

Basics of Go Language: net/http Package

Custom Server

To manage server behavior, you can create a custom server:

s := &http.Server{    Addr:           ":8080",    Handler:        myHandler,    ReadTimeout:    10 * time.Second,    WriteTimeout:   10 * time.Second,    MaxHeaderBytes: 1 << 20,}log.Fatal(s.ListenAndServe())

Leave a Comment