这是『快速入门』一章最后一个话题,很快我们就能完成第一个章节,正式打开 Go 语言的大门,怎么样?等不及了吧,那就开始吧。

1. 目标

前面我们使用了 http 包的 Get 函数,它相当于是 http 的客户端。现在我们需要一个 http 服务器。我们的目标是在端口 8001 上启动一个服务器,使用浏览器访问此服务器后网页上显示 “Hello, world!”.


014-HttpServer_go


图1 使用浏览器访问我们的服务器


2. 程序

程序路径:​​gopl/tutorial/httpserver/server1.go​

2.1 代码

// server1.go
package main

import (
"fmt"
"net/http"
"os"
)

func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Hello, world!</h1>") // 因为 w 有 Write 方法,可以这样用。
}
func main() {
http.HandleFunc("/hello", hello)
err := http.ListenAndServe(":8001", nil)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
}
}

连同注释,一共 19 行。如果用 c/c++ 在不使用第三方库的情况下,写出这样的程序可能要上百行才能搞定。(大神请忽略这句话。)

2.2 分析

先来看几个函数定义。

  • ​http.HandleFunc​
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

这个函数表示注册一个回调函数到路由 ​​pattern​​​ 上。比如在上面的程序里,我们使用了 ​​http.HandleFunc("/hello", hello)​​​,它的意思是如果访问路由 ​​/hello​​​,就会执行函数 ​​hello​​.

​ResponseWriter​​ 是在 http 包中定义的一个接口,其定义如下:

type ResponseWriter interface {
Header() Header
Write([]byte) (int, error)
WriteHeader(int)

​Request​​ 在 http 包中被定义为一个复合类型,类似 c 中的结构体。

  • ​ListenAndServe​
func ListenAndServe(addr string, handler Handler) error

此函数主要是启动服务程序,第二个参数我们暂传 nil.

3. 总结

  • 学会使用 http 编写最简单的 http 服务器

练习:

  1. 修改本节的程序,使其可以打印路由。比如在浏览器里输入​​http://mars:8001/hello/world​​​,在浏览器显示​​/hello/world​​​,输入​​http://mars:8001/go/da/fa/hao​​​,在浏览器显示​​/go/da/fa/hao​​. (提示:查阅 Request 结构体。答案在 server2.go 中,图 2 是输出的截图)


014-HttpServer_服务器_02


图2 打印路由