文章目录
Go基础 — net/http包
知识转载于李文周博客
1. Http协议
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。
Go语言内置的 net/http包提供了HTTP客户端和服务端的实现
2. net/http net/url包常用方法
2.1 net/http
2.1.1构建服务器
- http.HandleFunc : 用于注册HTTP请求的处理函数,接受两个参数:一个URL路径和一个处理函数(handler),当服务器收到匹配该url路径的请求时,将调用相应的处理函数来处理请求
http.HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
http.ResponseWriter 用于写入响应数据
http.Request 表示http请求的信息
- http.ListenandServer:用于创建一个简单的HTTP服务器,监听指定的地址和端口,并提供服务
http.ListenAndServe(addr string, handler http.Handler) error
addr:要监听的地址,格式为host:port
handler:用于处理HTTP请求的处理器
示例
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello,My net/http")
})
if err := http.ListenAndServe(":9090", nil); err != nil {
panic(err)
}
}
2.1.2 发送HTTP请求
net/http 包提供了多种方法来发送 HTTP 请求,比如 http.Get、http.Post等 详细见下文 3.基本的HTTP/HTTPS请求
2.1.3 设置请求头
- http.NewRequest:创建自定义的http请求
http.NewRequest(method, url string, body io.Reader) (*http.Request, error)
method:请求方法,例如“GET” “POST” “PUT” 等
url:请求的目标URL
body:请求体,通常是一个实现了io.Reader接口的对象
示例
package main
import (
"fmt"
"net/http"
)
func main() {
// 创建一个 GET 请求到指定 URL
req, err := http.NewRequest("GET", "https://example.com", nil)
if err != nil {
panic(err)
}
// 发送请求并获取响应
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 处理响应...
}
2.2 net/url
- url.Parse:解析URL字符串并返回url.URL结构体 其中包含URL的各个组成部分
url.Parse(rawurl string) (*url.URL, error):
parsedURL, err := url.Parse("https://example.com/path?foo=bar&baz=qux")
- url.URL{}: 创建一个空的url.URL结构体,然后可以通过字段赋值的方式构建URL
- u.String() string:将url.URL结构体转换为字符串形式的URL
u := url.URL{
Scheme: "https",
Host: "example.com",
Path: "/path",
}
- url.ParseRequestURI:用于解析请求的 URI(Uniform Resource Identifier),返回一个 url.URL 结构体。
url.ParseRequestURI(rawurl string) (*url.URL, error)
package main
import (
"fmt"
"net/url"
)
func main() {
// 解析 URI
uri := "http://example.com/path/to/resource?query=value"
parsedURL, err := url.ParseRequestURI(uri)
if err != nil {
panic(err)
}
// 输出解析结果
fmt.Println("Scheme:", parsedURL.Scheme)
fmt.Println("Host:", parsedURL.Host)
fmt.Println("Path:", parsedURL.Path)
fmt.Println("Query:", parsedURL.RawQuery)
}
3. 基本的HTTP/HTTPS请求
- Get、Head、Post和PostForm 发出HTTP/HTTPS请求
resp, err := http.Get("http://example.com/")
resp, err := http.Post("http://example.com/upload","image/jpeg",&buf)
resp, err := hrrp.PostForm("http://example.com/form",url.Values{"key":{"Value"},"id":{"123"}})
程序在使用完response后必须关闭回复的主体
resp , err := http.Get("http://example.com/")
if err != null{
//handle error
}
defer resp.Body.Close()
body,err := ioutil.ReadALL(resp.Body)
4. Get请求案例
- 使用net/http包编写一个简单的发送HTTP请求的Client端,代码如下
package main
import(
"fmt"
"io/ioutil"
"net/http"
)
func main(){
resp, err := http.Get("https://www.example.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))
将上面的代码保存之后编译成可执行文件,执行之后就能在终端打印example.com网站首页的内容了,我们的浏览器其实就是一个发送和接收HTTP协议数据的客户端,我们平时通过浏览器访问网页其实就是从网站的服务器接收HTTP数据,然后浏览器会按照HTML、CSS等规则将网页渲染展示出来。
5.带参数的GET请求案例
关于GET请求的参数需要使用Go语言内置的net/url这个标准库来处理。
func main(){
apiUrl := "http://127.0.0.1:9090/get"
data := url.Values{}
data.Set("name","小王子")
data.Set("age","18")
u,err := url.ParseRequestURI(apiUrl)
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))
}
对应的Server端HandlerFunc如下:
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))
}
6.Post请求
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// net/http post demo
func main() {
url := "http://127.0.0.1:9090/post"
// 表单数据
//contentType := "application/x-www-form-urlencoded"
//data := "name=小王子&age=18"
// json
contentType := "application/json"
data := `{"name":"小王子","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))
}
对应的Server端 HandlerFunc 如下
func postHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
// 1. 请求类型是application/x-www-form-urlencoded时解析form数据
r.ParseForm()
fmt.Println(r.PostForm) // 打印form数据
fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))
// 2. 请求类型是application/json时从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))
}