http包提供了HTTP客户端和服务端的实现
*http.Request 获取客户端提交的数据
http.ResponseWriter向客户端响应数据
http_server.go:
/*
自定义http的业务逻辑函数
*/
// response是一个io.Writer, 相当于一个打开了的文件(浏览器窗口)
func login(response http.ResponseWriter, request *http.Request) {
fmt.Println("do login ... ") // 在这函数内部就可以实现具体的业务逻辑
fmt.Fprintf(response, "login") // 响应回去
}
func history(response http.ResponseWriter, request *http.Request) {
fmt.Println("do history ... ")
fmt.Fprintf(response, "history")
}
func index(response http.ResponseWriter, request *http.Request) {
fmt.Println("do index ... ")
fmt.Fprintf(response, "login")
}
func main() {
/*根据业务需要, 创建多个路由url*/
http.HandleFunc("/", index)
http.HandleFunc("/login", login)
http.HandleFunc("/history", history)
fmt.Println("start http server ...")
/*监听并开启服务*/
err := http.ListenAndServe("127.0.0.1:9000", nil)
if err != nil {
fmt.Println("http server failed")
}
}
http_client.go:
func main() {
res, err := http.Get("https://www.qq.com/") // get请求, 获取*Response
if err != nil {
fmt.Println("get error", err)
return
}
data, err := ioutil.ReadAll(res.Body) // 数据放在Response的Body字段中
if err != nil {
fmt.Println("read error", err)
return
}
fmt.Println(string(data))
}
http请求方式:
http.Get(url) -- get请求, 如上所示
http.Post(url) -- post请求
http.Head(url) -- 请求头部, 常用于监控服务器是否正常
func main() {
var urls = []string{
"https://www.qq.com",
"https://www.goole.com",
"https://www.baidu.com",
}
for _, v := range urls {
res, err := http.Head(v)
if err != nil {
fmt.Printf("%s is error: %v\n", v, err)
continue
}
fmt.Printf("%s success status: %s\n", v, res.Status)
}
}
自定义创建Client:
文档: 要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client
要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport
然后使用自定义的Client来发送get, post等请求
type Client struct {
// 里面有个字段是Transport, 用于拨号请求
TransportTransport RoundTrippe
}
type Transport struct {
// 它里面有一个Dial字段, 用于收发数据的
Dial func(network, addr string) (net.Conn, error)
}
自定义Client, 控制请求的超时时间:
func main() {
var urls = []string{
"https://www.qq.com",
"https://www.goole.com",
"https://www.baidu.com",
}
for _, v := range urls {
/*自建客户端, 代理http用于请求*/
c := http.Client {
Transport : &http.Transport {
Dial: func(network, addr string)(net.Conn, error) { //它是一个函数, 传一个此函数的实现
timeout := time.Second * 2 // 修改这个时间
return net.DialTimeout(network, addr, timeout) // 表示使用底层的函数
},
},
}
res, err := c.Head(v) // 用这个自定义的Client来发请求
if err != nil {
fmt.Printf("%s is error: %v\n", v, err)
continue
}
fmt.Printf("%s success status: %s\n", v, res.Status)
}
}
http状态码:
http.StatusContinue = 100 上传数据请求时, 先咨询服务端是否允许上传
http.StatusOK = 200 请求成功
http.StatusFound = 302 跳转
http.StatusBadRequest = 400 非法的请求
http.StatusUnauthorized = 401 权限不够
http.StatusForbidden = 403 禁止访问
http.StatusNotFound = 404 访问的资源不存在
http.StatusInternalServerError = 500 服务器内部错误
表单处理:
数据提交一般都是用表单来的, 但go一般不用于写页面
而是用于写服务器, 做json协议处理
本文最前面已用到了Handler函数
一个Handler函数会带两个参数:
http.ResponseWriter -- 向客户端写数据
*http.Request -- 接收客户端提交的数据
func DoOneServer(w http.ResponseWriter, r *http.Request)
package main
import (
"fmt"
"net/http"
"io"
)
const form = `
<html>
<body>
<form method="post" action="#">
<input type="text" name="in"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
`
// 处理函数
func SimpleServer(writer http.ResponseWriter, request *http.Request) {
io.WriteString(writer, "<h1>hello</h1>")
}
// 处理函数
func FormServer(writer http.ResponseWriter, request *http.Request) {
// 设置响应类型
writer.Header().Set("Content_type", "text/html")
// 判断请求的类型
if request.Method == "GET" {
io.WriteString(writer, form)
}
if request.Method == "POST" {
fmt.Println("post request ...")
request.ParseForm() // 解析当前提交的表单
io.WriteString(writer, request.FormValue("in")) // 获取表单元素的内容
}
}
func main() {
http.HandleFunc("/", SimpleServer) // 里面会自动调用处理函数
http.HandleFunc("/form", FormServer)
fmt.Println("sever start ...")
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("start server error: ", err)
}
}
panic处理:
实际上每一个处理函数都需要加上panic处理函数
这样做的话, 一个处理函数挂掉, 其它的处理函数正常进行, 进程也不会终止
封装panic处理函数(处理函数不变):
func main() {
http.HandleFunc("/", handlePanic(SimpleServer)) //使用panic处理函数
http.HandleFunc("/form", handlePanic(FormServer))
fmt.Println("sever start ...")
err := http.ListenAndServe(":9000", nil)
if err != nil {
fmt.Println("start server error: ", err)
}
}
// panic处理, 返回HandlerFunc函数
func handlePanic(handler http.HandlerFunc) http.HandlerFunc{
return func(writer http.ResponseWriter, request *http.Request) {
defer func() {
if x:=recover(); x != nil {
fmt.Println("error : ", x)
}
}()
handler(writer, request) // 实际执行处理函数
}
}