Go实现web服务器

Go 允许您使用它的标准库函数自己实现一个 web 服务器。在这本书中您第一次看到一个用 Go 实现的 web 服务器应用程序是在第10章,Go 并发-进阶讨论,我们讨论 context 包的时候。

尽管用 Go 实现的 web 服务器能做需要高效安全的事情,但如果您真正需要一个强大的 web 服务器,支持模块,多站点和虚拟主机的话,您最好使用如 ApacheNginx 这样的 web 服务器

这个例子程序命名为 www.go,由五部分展示。它的第一部分包含期望的 import 声明:

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "os"
  6. "time"
  7. )

对于 web 服务器不需要操作 time 包。然而,由于服务器要发送时间和日期给客户端,所以这个例子里需要它。

www.go 的第二段代码如下:

  1. func myHandler(w http.ResponseWriter, r *http.Request) {
  2. fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
  3. fmt.Printf("Served: %s\n", r.Host)
  4. }

这是该程序的第一个处理函数的实现。一个处理函数取决于使用的配置可以服务一个或多个 URL。

www.go 的第三部分包含如下代码:

  1. func timeHandler(w http.ResponseWriter, r *http.Request) {
  2. t := time.Now().Format(time.RFC1123)
  3. Body := "The current time is:"
  4. fmt.Fprintf(w, "<h1 align=\"center\">%s</h1>", Body)
  5. fmt.Fprintf(w, "<h2 align=\"center\">%s</h2>\n", t)
  6. fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
  7. fmt.Fprintf(w, "Served time for: %s\n", r.Host)
  8. }

 从上面这段 Go 代码,您能看到该程序的第二个处理函数的实现。该函数输出动态内容。

我们的 web 服务器代码的第四部分处理命令行参数和定义支持的 URL:

  1. func main() {
  2. PORT := ":8001"
  3. arguments := os.Args
  4. if len(arguments) == 1 {
  5. fmt.Println("Using default port number: ", PORT)
  6. }else{
  7. PORT = ":" + arguments[1]
  8. }
  9. http.HandleFunc("/time", timeHandler)
  10. http.HandleFunc("/", myHandler)

http.HandleFunc() 函数把一个URL和一个处理函数关联起来。

www.go 程序的最后一段如下:

  1. err := http.ListenAndServe(PORT, nil)
  2. if err != nil {
  3. fmt.Println(err)
  4. return
  5. }
  6. }

您将在 http.ListenAndServe() 函数的帮助下使用期望的端口号启动 web 服务器。

执行 www.go 并连接 web 服务器将生成如下输出:

  1. $ go run www.go
  2. Using default port number: :8001
  3. Served: localhost:8001
  4. Served: localhost:8001
  5. Served time for: localhost:8001
  6. Served: localhost:8001
  7. Served time for: localhost:8001
  8. Served: localhost:8001
  9. Served time for: localhost:8001
  10. Served: localhost:8001
  11. Served: localhost:8001
  12. Served: localhost:8001

尽管这个程序的输出提供了一些方便的信息,但我想您更愿意用您喜欢的浏览器看到真正的输出。下面的截图显示了我们的 web 服务器的 myhandler() 函数的输出,显示在 Google Chrome:

www.go web 服务器的首页

下面的截图显示 www.go 也能生成动态页面。在这个例子,它是注册在 /time 下的 web 页面,显示当前时间和日期:

从www.go web 服务器获取当前时间和日期

这里真正有趣的是除了 /time 所有的 URL 都由 myHandler() 函数处理,因为它是 / 的第一个参数,匹配所有没有与另一个 handler 匹配的 URL。