使用Go语言,我们可以轻松创建出Web服务,这一点比Node.js还要简单,今天就来总结一下Go语言中Web服务的创建方式。
首先,我们需要引入net/http
这个包来处理HTTP请求,然后在指定的端口开启服务,下面来写一个最简单的Web服务程序:
// server.gopackage mainimport ( ???"fmt" ???"log" ???"net/http")func main() { ???http.HandleFunc("/", handler) ???log.Println("go server listening at port 3000...") ???err := http.ListenAndServe(":3000", nil) ???if err != nil { ???????log.Fatal("err: ", err) ???}}func handler(res http.ResponseWriter, req *http.Request) { ???log.Println(req.URL.Path) ???fmt.Fprintf(res, "URL.Path = %q\n", req.URL.Path)}
上面代码中,我们会处理所有3000
端口的请求,然后在页面显示请求的路径
。另外,我们在代码中引入了log
包,使用log.Println(s)
方法打印信息,运行代码后,在浏览器请求localhost:3000
及localhost:3000/test
,控制台打印信息如下:
$ go run server.go2018/08/30 13:26:58 go server listening at port 3000...2018/08/30 13:27:01 /2018/08/30 13:27:07 /test
接下来,我们希望这个服务能够解析出浏览器的请求信息,返回并显示到页面,下面是经过改进后的代码:
// server.gopackage mainimport ( ???"fmt" ???"log" ???"net/http")func main() { ???http.HandleFunc("/", handler) ???log.Println("go server listening at port 3000...") ???err := http.ListenAndServe(":3000", nil) ???if err != nil { ???????log.Fatal("err: ", err) ???}}func handler(res http.ResponseWriter, req *http.Request) { ???// 请求方法 请求地址 协议类型 ???fmt.Fprintf(res, "%s %s %s\n", req.Method, req.URL, req.Proto) ???// 请求头信息 ???for k, v := range req.Header { ???????fmt.Fprintf(res, "Header[%q] = %q\n", k, v) ???} ???// 请求的服务器URL & 请求的远程地址 ???fmt.Fprintf(res, "Host = %q\n", req.Host) ???fmt.Fprintf(res, "RemoteAddr = %q\n", req.RemoteAddr) ???if err := req.ParseForm(); err != nil { ???????log.Print(err) ???} ???// 表单信息 ???for k, v := range req.Form { ???????fmt.Fprintf(res, "Form[%q] = %q\n", k, v) ???}}
在handler
函数中,我们从http.Request
中取出相应的HTTP请求信息,然后返回给浏览器,大家可以亲自运行以上代码,来观察实际效果。
接下来,我们希望做个小功能 - 统计用户的访问次数,这是一项很古老的技术了,在上个世纪的论坛网站中曾广泛应用。:)
我们改进后的代码如下:
// server.gopackage mainimport ( ???"fmt" ???"log" ???"sync" ???"net/http")var mutex sync.Mutexvar count intfunc main() { ???http.HandleFunc("/", handler) ???// 添加/count路由及处理函数 ???http.HandleFunc("/count", counter) ???log.Println("go server listening at port 3000...") ???err := http.ListenAndServe(":3000", nil) ???if err != nil { ???????log.Fatal("err: ", err) ???}}// 每次访问时 count递增func handler(res http.ResponseWriter, req *http.Request) { ???mutex.Lock() ???count++ ???mutex.Unlock() ???fmt.Fprintf(res, "URL.Path = %q\n", req.URL.Path)}// 显示当前访问次数func counter(res http.ResponseWriter, req *http.Request) { ???mutex.Lock() ???fmt.Fprintf(res, "Visit Count: %d\n", count) ???mutex.Unlock()}
这次我们引入了sync
包,来应对并发访问带来的数据更新问题,sync.Mutex
类提供了Lock()
和Unlock()
方法,分别对更新操作进行加锁和解锁,保证count
的递增操作不会受到并发访问的影响。
运行上面的代码,然后在浏览器中访问除/count
之外的路径,都可以累积访问次数,最后,在访问/count
路径时,会返回当前服务被访问的次数。
Golang系列文章:创建Web服务
原文地址:https://www.cnblogs.com/liuhe688/p/9602397.html