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 ???//客户端能接收的mineAccept-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 mainimport ( ???"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])) ???}}
HTTP服务端
package mainimport ( ???"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 mainimport ( ???"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 mainimport ( ???"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) ???}}
3.http 常见状态码
http.StatusContinue = 100 ??//继续访问http.StatusOK = 200http.StatusFound = 302 ???????//跳转http.StatusBadRequest = 400 ???//发送的请求,协议格式不对http.StatusUnauthorized =401 ???//没有授权http.StatusForbidden = 403 ???????//没有权限访问http.StatusNotFound = 404 ???????//请求地址不存在http.StatusInternalServerError = 500 ???//服务器有问题502 ?//有代理,后端服务挂了504 ?//后端处理请求超时
4、表单处理
package mainimport ( ???"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 { ???????????}}
5、panic处理
package mainimport ( ???"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) ?//执行处理函数 ???}}
模板的使用
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 mainimport ( ???"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 mainimport ( ???"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}}
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编程
原文地址:https://www.cnblogs.com/domestique/p/8443754.html