Go入门指南系列-XV-VIII-精巧的多功能网页服务器
为进一步深入理解 http
包以及如何构建网页服务器功能,让我们来学习和体会下面的例子:先列出代码,然后给出不同功能的实现方法,程序输出显示在表格中。
示例 15.20 elaborated_webserver.go
1 | package main |
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
Logger() | http://localhost:12345/ (根) | oops |
Logger()
处理函数用 w.WriteHeader(404)
来输出 “404 Not Found”头部。
这项技术通常很有用,无论何时服务器执行代码产生错误,都可以应用类似这样的代码:
1 | if err != nil { |
另外利用 logger
包的函数,针对每个请求在服务器端命令行打印日期、时间和 URL。
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
HelloServer() | http://localhost:12345/go/hello | hello, world! |
包 expvar
可以创建(Int,Float 和 String 类型)变量,并将它们发布为公共变量。它会在 HTTP URL /debug/vars
上以 JSON 格式公布。通常它被用于服务器操作计数。helloRequests
就是这样一个 int64
变量,该处理函数对其加 1,然后写入“hello world!”到浏览器。
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
Counter() | http://localhost:12345/counter | counter = 1 |
Counter() | 刷新(GET 请求) | counter = 2 |
计数器对象 ctr
有一个 String()
方法,所以它实现了 expvar.Var
接口。这使其可以被发布,尽管它是一个结构体。ServeHTTP()
函数使 ctr
成为处理器,因为它的签名正确实现了 http.Handler
接口。
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
FileServer() | http://localhost:12345/go/ggg.html | 404 page not found |
FileServer(root FileSystem) Handler
返回一个处理器,它以 root
作为根,用文件系统的内容响应 HTTP 请求。要获得操作系统的文件系统,用 http.Dir
,例如:
1 | http.Handle("/go/", http.FileServer(http.Dir("/tmp"))) |
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
FlagServer() | http://localhost:12345/flags | Flags: boolean = true root = /home/rsc |
该处理函数使用了 flag
包。VisitAll()
函数迭代所有的标签 (flag),打印它们的名称、值和默认值(当不同于“值”时)。
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
ArgServer() | http://localhost:12345/args | ./elaborated_webserver.exe |
该处理函数迭代 os.Args
以打印出所有的命令行参数。如果没有指定则只有程序名称(可执行程序的路径)会被打印出来。
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
Channel() | http://localhost:12345/chan | channel send #1 |
Channel() | 刷新 | channel send #2 |
每当有新请求到达,通道的 ServeHTTP()
方法从通道获取下一个整数并显示。由此可见,网页服务器可以从通道中获取要发送的响应,它可以由另一个函数产生(甚至是客户端)。下面的代码片段正是一个这样的处理函数,但会在 30 秒后超时:
1 | func ChanResponse(w http.ResponseWriter, req *http.Request) { |
处理函数 | 调用 URL | 浏览器获得响应 |
---|---|---|
DateServer() | http://localhost:12345/date | 显示当前时间(由于是调用 /bin/date,仅在 Unix 下有效) |
可能的输出:Thu Sep 8 12:41:09 CEST 2011
。
os.Pipe()
返回一对相关联的 File
,从 r
读取数据,返回已读取的字节数来自于 w
的写入。函数返回这两个文件和错误,如果有的话:
1 | func Pipe() (r *File, w *File, err error) |
链接
- 目录
- 上一节:探索 template 包
- 下一节:用 rpc 实现远程过程调用