GO语言WEB编程初识

在 Go 语言中,net/http 是一个非常常用的标准库,专门用于构建 HTTP 客户端和服务器。它提供了丰富的功能来处理 HTTP 请求和响应,支持 HTTP/1.x、HTTP/2 协议,并且可以与第三方库一起使用来简化开发。

下面是对 net/http 包的详细介绍。

1. 基本概念

  • HTTP 客户端:用于发起 HTTP 请求并处理响应。
  • HTTP 服务器:用于监听 HTTP 请求并发送响应。

2. HTTP 客户端使用

详情: Go语言的httpclient  

发送 GET 请求

package main

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

func main() {
    // 发起 GET 请求
    response, err := http.Get("https://www.example.com")
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()

    // 读取响应体
    body, err := ioutil.ReadAll(response.Body)
    if err != nil {
        log.Fatal(err)
    }

    // 打印响应
    fmt.Println("Response Status:", response.Status)
    fmt.Println("Response Body:", string(body))
}

http.Get 是一个简便的 HTTP 客户端方法,它会返回一个 *http.Response 对象,你可以通过它读取响应体(Body)及状态码等信息。

发送 POST 请求

package main

import (
    "bytes"
    "fmt"
    "log"
    "net/http"
)

func main() {
    // 构造 POST 请求数据
    data := []byte(`{"name": "John", "age": 30}`)
    
    // 发起 POST 请求
    response, err := http.Post("https://www.example.com", "application/json", bytes.NewBuffer(data))
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()

    // 打印响应状态
    fmt.Println("Response Status:", response.Status)
}

使用 http.Client 自定义请求

对于需要更多控制的场景,可以使用 http.Client 对象。通过它你可以配置请求的超时、重定向策略等。

package main

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

func main() {
    // 创建自定义的 HTTP 客户端
    client := &http.Client{
        Timeout: 10 * time.Second, // 设置请求超时
    }

    // 发起 GET 请求
    response, err := client.Get("https://www.example.com")
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()

    fmt.Println("Response Status:", response.Status)
}

3. HTTP 服务器使用

创建基本的 HTTP 服务器

package main

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

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", handler) // 注册处理函数
    log.Fatal(http.ListenAndServe(":8080", nil)) // 启动 HTTP 服务器
}

在这个例子中,http.HandleFunc 用于将请求 URL 路径(/)和处理函数(handler)关联起来。http.ListenAndServe 启动服务器,监听指定端口(8080)。

创建一个更复杂的服务器

package main

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

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.URL.Query().Get("name"))
}

func main() {
    http.HandleFunc("/hello", helloHandler) // 处理 /hello 路径
    log.Fatal(http.ListenAndServe(":8080", nil))
}

访问 http://localhost:8080/hello?name=John 会返回 "Hello, John!"

使用 http.ServeMux 路由

ServeMux 是默认的路由器,它能够将 URL 路径映射到处理函数。你也可以创建自定义的 ServeMux

package main

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

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello from custom ServeMux!")
    })
    
    log.Fatal(http.ListenAndServe(":8080", mux))
}

4. 处理请求和响应

  • Request 对象:包含了客户端发起的 HTTP 请求的信息,如方法(GET、POST)、URL、请求头、请求体等。
  • Response 对象:包含了 HTTP 响应的信息,如状态码、响应头、响应体等。

你可以使用 RequestResponse 对象来获取更详细的信息:

package main

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

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Method:", r.Method)
    fmt.Println("Request URI:", r.RequestURI)
    fmt.Println("Header:", r.Header)

    w.Write([]byte("Response from server"))
}

func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

5. 中间件

在 Go 中可以使用 http.Handlehttp.HandleFunc 来注册路由。要实现中间件功能,可以通过包装处理函数来实现。

package main

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

func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Request received:", r.Method, r.URL)
        next(w, r)
    }
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello from handler!")
}

func main() {
    http.HandleFunc("/", loggingMiddleware(handler))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

6. 表单和文件上传

处理表单

package main

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

func formHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodPost {
        err := r.ParseForm()
        if err != nil {
            fmt.Println(err)
        }
        fmt.Fprintf(w, "Received: %v\n", r.Form)
    } else {
        fmt.Fprintf(w, `
            <form method="POST">
                Name: <input type="text" name="name"><br>
                Age: <input type="text" name="age"><br>
                <input type="submit" value="Submit">
            </form>
        `)
    }
}

func main() {
    http.HandleFunc("/", formHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

处理文件上传

package main

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

func fileUploadHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodPost {
        file, _, err := r.FormFile("file")
        if err != nil {
            fmt.Println(err)
            return
        }
        defer file.Close()

        // 将文件保存到服务器
        dst, err := os.Create("/tmp/uploaded_file")
        if err != nil {
            fmt.Println(err)
            return
        }
        defer dst.Close()

        _, err = io.Copy(dst, file)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Fprintf(w, "File uploaded successfully")
    } else {
        fmt.Fprintf(w, `
            <form method="POST" enctype="multipart/form-data">
                Choose a file: <input type="file" name="file"><br>
                <input type="submit" value="Upload">
            </form>
        `)
    }
}

func main() {
    http.HandleFunc("/", fileUploadHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

总结

net/http 包是 Go 语言中非常强大且常用的一个包,用于 HTTP 请求的发起和响应的处理。通过它,你可以方便地创建 HTTP 客户端、服务器,并且实现复杂的功能,如中间件、文件上传、表单处理等。

如果有特定问题或想要深入了解某个方面,可以进一步提问!


文章标签:

评论(0)