a. Go原生支持http,import(“net/http”)
b. Go的http服务性能和nginx比较接近
c. 几行代码就可以实现一个web服务
http常见请求方法
1)Get请求
2)Post请求
3)Put请求
4)Delete请求
5)Head请求
http示例:
package main
import (
"fmt"
"net/http"
)
func Hello(w http.ResponseWriter, r *http.Request) {
//服务端输出
fmt.Println("handle hello")
//浏览器输出
fmt.Fprintf(w, "hello ")
}
func Login(w http.ResponseWriter, r *http.Request) {
//服务端输出
fmt.Println("handle login")
//浏览器输出
fmt.Fprintf(w, "login ")
}
func main() {
http.HandleFunc("/", Hello)
http.HandleFunc("/login", Login)
err := http.ListenAndServe("0.0.0.0:8080", nil)
if err != nil {
fmt.Println("http listen failed")
}
}
客户端
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))
}
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)
if err != nil {
fmt.Printf("head %s failed, err:%v\n", v, err)
continue
}
fmt.Printf("head succ, status:%v\n", resp.Status)
}
}
输出:
head succ, status:200 OK
head http://google.com failed, err:Head http://google.com: dial tcp 172.217.160.78:80: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
head succ, status:200 OK
还可以自己设置过期时间:
package main
import (
"fmt"
"net/http"
"net"
"time"
)
var url = []string{
"http://www.baidu.com",
"http://google.com",
"http://taobao.com",
}
func main() {
for _, v := range url {
c := http.Client{
Transport: &http.Transport {
Dial:func(network, addr string) (net.Conn, error){
//自己设置超时时间
timeout := time.Second*2
return net.DialTimeout(network, addr, timeout)
},
},
}
resp, err := c.Head(v)
if err != nil {
fmt.Printf("head %s failed, err:%v\n", v, err)
continue
}
fmt.Printf("head succ, status:%v\n", resp.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
表单处理(此例两个input的name都是in,注意:w, request.Form["in"][0],很显然是个数组):
package main
import (
"io"
"net/http"
)
const form = `<html><body><form action="#" method="post" name="bar">
<input type="text" name="in"/>
<input type="text" name="in"/>
<input type="submit" value="Submit"/>
</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")
switch request.Method {
case "GET":
io.WriteString(w, form)
case "POST":
request.ParseForm()
//此处获取第一个in输入框数据
io.WriteString(w, request.Form["in"][0])
io.WriteString(w, "\n")
//此处获得的也是第一个in输入框的数据
io.WriteString(w, request.FormValue("in"))
}
}
func main() {
http.HandleFunc("/test1", SimpleServer)
http.HandleFunc("/test2", FormServer)
if err := http.ListenAndServe(":8088", nil); err != nil {
}
}
panic处理(注意类型):
package main
import (
"log"
"net/http"
)
const form = `<html><body><form action="#" method="post" name="bar">
<input type="text" name="in"/>
<input type="text" name="in"/>
<input type="submit" value="Submit"/>
</form></html></body>`
//代码省略
func main() {
http.HandleFunc("/test1", logPanics(SimpleServer))
http.HandleFunc("/test2", logPanics(FormServer))
if err := http.ListenAndServe(":8088", nil); err != nil {
}
}
//一个公共的panic方法
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)
}
}
go自己支持模板:
go文件:
package main
import (
"fmt"
"os"
"text/template"
)
type Person struct {
Name string
// 1.注意此处的大小写和模板中的大小写一致
// 2.注意Age的类型要是数字类型才能在模板中比大小
Age int
}
func main() {
t, err := template.ParseFiles("./index.html")
if err != nil {
fmt.Println("parse file err:", err)
return
}
p := Person{Name: "Mary", Age: 31}
//这里只是输出在终端,如果输出在浏览器,就用w http.ResponseWriter
if err := t.Execute(os.Stdout, p); err != nil {
fmt.Println("There was an error:", err.Error())
}
}
html文件:
<html>
<head></head>
<body>
{{if gt .Age 18}}
<p>hello, old man, {{.Name}}</p>
{{else}}
<p>hello,young man, {{.Name}}</p>
{{end}}
{{/*.代表go文件中的p*/}}
{{.}}
</body>
</html>
http版模板:
package main
import (
"fmt"
"html/template"
"io"
"net/http"
)
var myTemplate *template.Template
type Result struct {
output string
}
func (p *Result) Write(b []byte) (n int, err error) {
fmt.Println("called by template")
p.output += string(b)
return len(b), nil
}
type Person struct {
Name string
Title string
Age int
}
func userInfo(w http.ResponseWriter, r *http.Request) {
fmt.Println("handle hello")
//fmt.Fprintf(w, "hello ")
var arr []Person
p := Person{Name: "Mary001", Age: 10, Title: "我的个人网站"}
p1 := Person{Name: "Mary002", Age: 10, Title: "我的个人网站"}
p2 := Person{Name: "Mary003", Age: 10, Title: "我的个人网站"}
arr = append(arr, p)
arr = append(arr, p1)
arr = append(arr, p2)
resultWriter := &Result{}
io.WriteString(resultWriter, "hello world")
err := myTemplate.Execute(w, arr)
if err != nil {
fmt.Println(err)
}
fmt.Println("template render data:", resultWriter.output)
//myTemplate.Execute(w, p)
//myTemplate.Execute(os.Stdout, p)
//file, err := os.OpenFile("C:/test.log", os.O_CREATE|os.O_WRONLY, 0755)
//if err != nil {
// fmt.Println("open failed err:", err)
// return
//}
}
func initTemplate(filename string) (err error) {
myTemplate, err = template.ParseFiles(filename)
if err != nil {
fmt.Println("parse file err:", err)
return
}
return
}
func main() {
initTemplate("d:/project/src/go_dev/day10/template_http/index.html")
http.HandleFunc("/user/info", userInfo)
err := http.ListenAndServe("0.0.0.0:8880", nil)
if err != nil {
fmt.Println("http listen failed")
}
}
1)替换 {{.字段名}}
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())
}
}
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){{.}}:
<html>
<head>
</head>
<body>
<p>hello, old man, {{.}}</p>
</body>
</html>
4){{with .Var}}
5){{end}}
<html>
<head>
</head>
<body>
{{with .Name}}
<p>hello, old man, {{.}}</p>
{{end}}
</body>
</html>
6)循环,{{range.}} ,{{end }}
<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>
转载于:https://blog.51cto.com/5660061/2349748