go http

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) // 实际执行处理函数
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值