go语言web开发01 - 之go原生的web-server开发
go语言里自带的net/http包提供了http客户端和服务端的实现,也就是说go语言原生支持web服务开发,下面我们来看一下go原生的http服务端实现吧
一、go简单实现web Server
1.1、代码部分
package main import ( "fmt" "io" "net/http" ) // 定义url路径对应的处理函数 func Hello(w http.ResponseWriter, r *http.Request) { fmt.Println("handle Hello") // 后台输出的信息 fmt.Fprintf(w, "hello") // 响应请求的数据 } // 定义url路径对应的处理函数 func login(w http.ResponseWriter, r *http.Request) { fmt.Println("handle Hello") // 后台输出的信息 // fmt.Fprintf(w, "login") // 响应请求的数据 io.WriteString(w, "response data") // 也可以使用io包下的方法返回消息 } func main() { // 1.定义url路径与url路径对应的处理函数 http.HandleFunc("/", Hello) http.HandleFunc("/user/login", login) // 2.设置http监听 err := http.ListenAndServe("0.0.0.0:8088", nil) if err != nil { fmt.Println("http listen failed:", err) } }
1.2、请求展示
1.请求/路径
2.请求/user/login路径
二、http客户端实现
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { // 发送http GET请求 ret, err := http.Get("https://www.baidu.com") if err != nil { // 错误处理 fmt.Println("get url err:",err) return } // 利用ioutil.ReadAll方法读取返回结果里的Body内容 data, err := ioutil.ReadAll(ret.Body) if err != nil { // 错误处理 fmt.Println("get data err:",err) return } fmt.Println(string(data)) // 打印最终结果 }
三、网站检测
package main import ( "fmt" "net/http" "time" "net" ) // http head检测 var url = []string{ "https://www.baidu.com", "http://www.taobao.com", "https://www.uxuan.cc", "https://google.com", } func main() { for _,v := range url { // 1.循环获取url c := http.Client{ // 2.自己生成http客户端 Transport: &http.Transport { // (语法是固定的,记住怎么用就可以了) Dial: func(network, addr string) (net.Conn, error) { timeout := time.Second * 2 // 3.设置请求超时时间,超过两秒就退出请求 return net.DialTimeout(network, addr, timeout) }, }, } resp, err := c.Head(v) // 4.http.head请求循环获取到的url if err != nil { fmt.Printf("head %s failed, err:%v\n",v,err) continue } fmt.Printf("head succ, status:%v\n",resp.Status) // 5.打印http状态吗 } }
四、web server模板示例
1.服务端代码部分
package main import ( "fmt" "text/template" "net/http" ) // 定义模板变量 var myTemplate *template.Template // 定义结构体 type Person struct { Name string Age int } // 处理请求的函数(http.ResponseWriter:为响应数据的值。 *http.Request:为接受请求的参数) func index(w http.ResponseWriter, r *http.Request) { // 初始化结构体 p := Person{Name: "Dream", Age: 10} // 模板文件作用在哪里,p为往模板文件里传的变量 myTemplate.Execute(w, p) // myTemplate.Execute(os.Stdout, p) // 支持将模板作用到终端、文件或者其他的地方 } // 初始化模板文件的函数 func initTemplate(filename string) (err error) { // 通过template.ParseFiles初始化模板文件,获得一个初始化后的模板文件和err myTemplate, err = template.ParseFiles(filename) if err != nil { // 判断错误并返回错误 fmt.Println("parse templatefile err:",err) return } return } func main() { // 调用初始化模板文件的函数初始化模板文件 initTemplate("E:/Scripts/go/src/go_dev/day10/5_wen-template/main/index.html") // 请求url与处理请求的函数指定 http.HandleFunc("/index", index) // 监听端口 err := http.ListenAndServe("0.0.0.0:8888", nil) if err != nil { fmt.Println("http listen failed") } }
2.模板内容
<html> <head> <title>My GoLang Test Package</title> <body> <h1>标题</h1> {{if gt .Age 18}} <p>your age big 18</p> {{else}} <p>your age min 18</p> {{end}} <p>Hell, {{.Name}}</p> <!-- .代表当前的p标签 --> </body> </head> </html>
3.模板里的一些其他操作
1. not 非 {{if not .condition}} 代码 {{end}} 2. and 与 {{if and .condition1 .condition2}} 代码 {{end}} 3. or 或 {{if or .condition1 .condition2}} 代码 {{end}} 4. eq 等于 {{if eq .var1 .var2}} 代码 {{end}} 5. ne 不等于 {{if ne .var1 .var2}} 代码 {{end}} 6. lt 小于 (less than) {{if lt .var1 .var2}} 代码 {{end}} 7. le 小于等于 {{if le .var1 .var2}} 代码 {{end}} 8. gt 大于 {{if gt .var1 .var2}} 代码 {{end}} 9. ge 大于等于 {{if ge .var1 .var2}} 代码 {{end}} 10.with <html> <head> </head> <body> {{with .Name}} <p>hello, old man, {{.}}</p> {{end}} </body> </html>
4.访问模板
五、http from表单示例
package main import ( "io" "net/http" "log" ) // 通过const定义一个form表单的常量 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></body></html>` // SimpleServer 函数 ,http.ResponseWriter:响应请求 , http.Request:接收请求 func SimpleServer(w http.ResponseWriter, request *http.Request) { io.WriteString(w, "<h1>hello, world</h1>") // 响应的数据为:"<h1>hello, world</h1>" panic("url: /test1, func: SimpleServer, failed !!") // panic捕获 } // FormServer函数 func FormServer(w http.ResponseWriter, request *http.Request) { w.Header().Set("Content-Type", "text/html") // w.Header().Set()设置响应的head信息 switch request.Method { // 通过switch语句判断http请求的方法 case "GET": // 如果是GET方法 io.WriteString(w, form) // 返回上面定义的form表单 case "POST": // 如果是post方法 request.ParseForm() // 通过request.ParseForm()来解析表单 io.WriteString(w, request.Form["in"][0]) // 获取表单里的name为in的下标是0的参数(获取的格式是数组) io.WriteString(w, "\n") // 设置换行 io.WriteString(w, request.FormValue("in")) // 获取表单里name为in的值(推荐用这种获取form值得方法) } } func main() { http.HandleFunc("/test1", logPanics(SimpleServer)) // 如果请求的是 ip:port/test1就指定SimpleServer函数处理(logPanics()为处理panic的函数) http.HandleFunc("/test2", logPanics(FormServer)) // 如果请求的是 ip:port/test2就指定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() { // 返回之前执行defer方法 if x := recover(); x != nil { // 处理recover() log.Printf("[%v] caught panic: %v", request.RemoteAddr, x) } }() handle(writer, request) // 调用传进来得函数,即真正处理请求得函数 } }