HTTP
1.http 编程 (http 是文本协议, socket 是二进制协议)
a.Go 原生支持 http,import(net/http)
b.Go 的 http 服务性能和 nginx 比较接近
c. 几行代码就可以实现 一个 web 服务
http 请求包
- GET /domains/example/ HTTP/1.1 // 请求行: 请求方法 请求 URI HTTP 协议 / 协议版本
- Host:www.iana.org // 服务端的主机名
- User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (Khtml, like Gecko) Chrome/22.0.1229.94 Safari/
- // 浏览器 信息
- Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 // 客户端能接收的 mine
- Accept-Encoding:gzip,deflate,sdch // 是否支持流压缩
- Accept-Charset:UTF-8,*;q=0.5 // 客户端字符编码集
- // 空行, 用于分割请求头和消息体
- // 消息体, 请求资源参数, 例如 POST 传递的参数
http 响应包
- HTTP/1.1 200 OK // 状态行
- Server: nginx/1.0.8 // 服务器使用的 WEB 软件名及版本
- Date:Date: Tue, 30 Oct 2012 04:14:25 GMT // 发送时间
- Content-Type: text/html // 服务器发送信息的类型
- Transfer-Encoding: chunked // 表示发送 HTTP 包是分段发的, http/1.0 是全部一起发, http/1.1 是一段一段的发
- Connection: keep-alive // 保持连接状态
- Content-Length: 90 // 主体内容长度
- // 空行用来分割消息头和主体
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... // 消息体
发送 http 请求
- package main
- import (
- "fmt"
- "io"
- "net"
- )
- func main() {
- conn, err := net.Dial("tcp", "www.baidu.com:80")
- if err != nil {
- fmt.Println("Error dialing", err.Error())
- return
- }
- defer conn.Close()
- msg := "GET / HTTP/1.1\r\n"
- msg += "Host: www.baidu.com\r\n"
- msg += "Connection: close\r\n"
- msg += "\r\n\r\n"
- _, err = io.WriteString(conn, msg)
- if err != nil {
- fmt.Println("write string failed,", err)
- return
- }
- buf := make([]byte, 4096)
- for {
- count, err := conn.Read(buf)
- if err != nil {
- break
- }
- fmt.Println(string(buf[0:count]))
- }
- }
- View Code
HTTP 服务端
- package main
- import (
- "fmt"
- "net/http"
- )
- func Hello(w http.ResponseWriter, r *http.Request) {
- //r 是请求头信息
- fmt.Println("handle hello")
- fmt.Fprintf(w, "hello") // 将数据返回给客户端
- }
- func main() {
- http.HandleFunc("/", Hello)
- err := http.ListenAndServe("0.0.0.0:8880", nil) // 检测端口, 解析请求, 分发请求进行处理
- if err != nil {
- fmt.Println("http listen failed")
- }
- }
HTTP 客户端
- package main
- import (
- "fmt"
- "io/ioutil"
- "net/http"
- )
- func main() {
- res, err := http.Get("https://www.baidu.com/")
- if err != nil {
- fmt.Println("get err:", err)
- return
- }
- data, err := ioutil.ReadAll(res.Body) // 读取网络链接里面数据
- if err != nil {
- fmt.Println("get data err:", err)
- return
- }
- fmt.Println(string(data))
- }
2.http 常见请求方法
1)Get 请求
2)Post 请求
3)Put 请求
4)Delete 请求
5)Head 请求
Head 请求头
- package main
- import (
- "fmt"
- "net/http"
- )
- var url = []string{
- "http://www.baidu.com",
- "http://google.com",
- "http://taobao.com",
- }
- func main() {
- for _, v := range url {
- resp, err := http.Head(v) //Head 请求时只会返回响应头
- if err != nil {
- fmt.Printf("head %s failed, err:%v\n", v, err)
- continue
- }
- fmt.Printf("head succ, status:%v\n", resp.Status)
- }
- }
- View Code
3.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 // 服务器有问题
- 502 // 有代理, 后端服务挂了
- 504 // 后端处理请求超时
4 表单处理
- package main
- import (
- "io"
- "net/http"
- )
- const form =`<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <body><form action="#" method="post" name="bar">
- <div> 姓名:<input type="text" name="username1"/></div>
- <div> 密码:<input type="text" name="password"/></div>
- <input type="submit" value="登录"/>
- </form></html></body>`
- func SimpleServer(w http.ResponseWriter, request *http.Request) {
- io.WriteString(w, "<h1>hello, world</h1>") // 返回 h1 标签至前端渲染
- }
- func FormServer(w http.ResponseWriter, request *http.Request) {
- w.Header().Set("Content-Type", "text/html") // 设置响应头
- w.Header().Set("Server", "Go 1.9.2 Server")
- w.Header().Set("Niubi", "hahahaha")
- switch request.Method {
- case "GET":
- io.WriteString(w, form)
- case "POST":
- request.ParseForm() // 解析 post 请求, 才能得到请求内容
- io.WriteString(w, request.Form["username"][0]) //go 支持文本框 name 相同
- io.WriteString(w, "\n")
- io.WriteString(w, request.FormValue("username"))// 取不到内容返回空
- }
- }
- func main() {
- http.HandleFunc("/test1", SimpleServer)
- http.HandleFunc("/test2", FormServer)
- if err := http.ListenAndServe(":8088", nil); err != nil {
- }
- }
- View Code
5panic 处理
- package main
- import (
- "io"
- "net/http"
- "log"
- )
- const form = `<html>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <body><form action="#" method="post" name="bar">
- <div> 姓名:<input type="text" name="username1"/></div>
- <div> 密码:<input type="text" name="password"/></div>
- <input type="submit" value="登录"/>
- </form></html></body>`
- func SimpleServer(w http.ResponseWriter, request *http.Request) {
- io.WriteString(w, "<h1>hello, world</h1>")
- }
- func FormServer(w http.ResponseWriter, request *http.Request) {
- w.Header().Set("Content-Type", "text/html")
- w.Header().Set("Server", "Go 1.9.2 Server")
- w.Header().Set("Niubi", "hahahaha")
- var p *int
- *p = 10 // 出现 panic,go 自动处理了异常, 线程挂掉, 但是进程不会挂掉
- switch request.Method {
- case "GET":
- io.WriteString(w, form)
- case "POST":
- request.ParseForm()
- io.WriteString(w, request.FormValue("username"))
- io.WriteString(w, "\n")
- io.WriteString(w, request.FormValue("password"))
- }
- }
- func main() {
- http.HandleFunc("/test1", logPanics(SimpleServer)
- http.HandleFunc("/test2", logPanics(FormServer))
- if err := http.ListenAndServe(":8088", nil); err != nil {
- }
- }
- func logPanics(handle http.HandlerFunc) http.HandlerFunc {
- return func(writer http.ResponseWriter, request *http.Request) {// 返回匿名函数, 原型和处理函数一致
- defer func() {
- if x := recover(); x != nil {
- log.Printf("[%v] caught panic: %v", request.RemoteAddr, x) // 捕获错误
- }
- }()
- handle(writer, request) // 执行处理函数
- }
- }
- View Code
模板的使用
1 渲染到终端
模板文件 index.html
- <html>
- <head>
- </head>
- <body>
- {{if gt .Age 18}} //gt 大于, . 指后端传过来的数据集
- <p>hello, old man, {{.Name}}</p>
- {{else}}
- <p>hello,young man, {{.Name}}</p>
- {{end}}
- </body>
- </html>
- package main
- import (
- "fmt"
- "os"
- "text/template"
- )
- type Person struct {
- Name string
- Age string
- }
- func main() {
- t, err := template.ParseFiles("./index.html") // 加载模板
- if err != nil {
- fmt.Println("parse file err:", err)
- return
- }
- p := Person{Name: "Mary", Age: "31"}
- if err := t.Execute(os.Stdout, p); err != nil{
- fmt.Println("There was an error:", err.Error())
- }
- }
2 渲染到前端
- <html>
- <head>
- </head>
- <body>
- <p>hello, old man, {{.age}}</p>
- </body>
- </html>
- package main
- import (
- "fmt"
- "text/template"
- "net/http"
- )
- type Person struct {
- Name string
- Age int
- }
- var (
- gtemp *template.Template
- )
- func init() {
- t, err := template.ParseFiles("./index2.html")
- if err != nil {
- fmt.Println("parse file err:", err)
- return
- }
- gtemp = t
- }
- func handleUserInfo(w http.ResponseWriter, r *http.Request) {
- p := &Person{
- Name:"mary",
- Age: 20,
- }
- // 执行模板渲染
- gtemp.Execute(w, p)
- }
- func main() {
- http.HandleFunc("/user_info", handleUserInfo)
- http.ListenAndServe(":8080", nil)
- }
模板
1)if 判断
- <html>
- <head>
- </head>
- <body>
- {{if gt .Age 18}}
- <p>hello, old man, {{.Name}}</p>
- {{else}}
- <p>hello,young man, {{.Name}}</p>
- {{end}}
- </body>
- </html>
2)if 常见操作符
not 非
- {{if not .condition}}
- {{end}}
and 与
- {{if and .condition1 .condition2}}
- {{end}}
or 或
- {{if or .condition1 .condition2}}
- {{end}}
eq 等于
- {{if eq .var1 .var2}}
- {{end}}
ne 不等于
- {{if ne .var1 .var2}}
- {{end}}
lt 小于 (less than)
- {{if lt .var1 .var2}}
- {{end}}
le 小于等于
- {{if le .var1 .var2}}
- {{end}}
gt 大于
- {{if gt .var1 .var2}}
- {{end}}
ge 大于等于
- {{if ge .var1 .var2}}
- {{end}}
- View Code
- 3){{.}}
后端传过来的结构体或者 map, 都是. xx 提取数据
- <html>
- <head>
- </head>
- <body>
- <p>hello, old man, {{.}}</p>
- </body>
- </html>
- 4){{with .Var}}
- <html>
- <head>
- </head>
- <body>
- {{with .Name}}
- <p>hello, old man, {{.}}</p> //. 代表 Name 的值
- {{end}}
- </body>
- </html>
5) 循环
- <html>
- <head>
- </head>
- <body>
- {{range .}}
- {{if gt .Age 18}}
- <p>hello, old man, {{.Name}}</p>
- {{else}}
- <p>hello,young man, {{.Name}}</p>
- {{end}}
- {{end}}
- </body>
- </html>
来源: http://www.bubuko.com/infodetail-2496013.html