一个简单的Go Web程序
在Go中,搭建一个http server简单到令人难以置信。只需要引入net/http包,写几行代码,一个http服务器就可以正常运行并接受访问请求。因此,在正式开启项目开发之前,先来看一段简短的代码。
1 | package main |
很显然,这段代码就能够构成一个Web程序,其中最为主要的内容基本上都与一个包有关—— net/http
,那就先学习一下有关这个包的内容吧。
初识net/http
在net/http源代码中,我们可以深深体会到Go语言的结构体(以及自定义类型)、接口、方法简单组合的设计哲学。这个包最主要的文件有4个,分别是: client.go
server.go
request.go
response.go
。
这四个文件也分别代表了HTTP中最重要的4个部分,http Request
请求、 http Response
响应、http Client
客户端和http Server
服务端,所以我们先从这四个方面来了解net/http
包:
Request
http Request
请求是由客户端发出的消息, 用来使服务器执行动作.发出的消息包括起始行, Headers, Body。
一般使用 http.NewRequest
来构造一个http Request
请求,可能包括http Headers
信息,cookies
信息等,然后发给服务端。
Response
http Response
响应是由http Server
服务端发出的消息,用来响应http Client
端发出的http Request
请求。发出的消息包括起始行, Headers, Body。
Client
http Client
客户端主要用来发送http Request
请求给http Server
服务端,比如以Do
方法,Get
方法以及Post
或PostForm
方法发送http Request
请求。
http.NewRequest
可以灵活的对http Request
进行配置,然后再使用http.Client
的Do
方法发送这个http Request
请求。
- 如果使用
Post
或者PostForm
方法,是不能使用http.NewRequest
配置请求的,只有Do
方法可以定制http.NewRequest
。
Server
http Server
服务端用来接收并响应http Client
端发出的http Request
请求,是net/http
包中非常重要和关键的一个功能。我们在Go语言中简单就能搭建HTTP
服务器,就是因为它的存在。
关于以上四部分的详细内容,可以看这篇文章,里面有更加详细的函数解释。
程序分析
大概了解关于net/http
包之后,我们再回头看开篇的那段代码,或许已经能看懂个大概了。
http.ListenAndServe
http.ListenAndServe
用以监听本地 3000 端口以提供服务,标准的 HTTP 端口是 80 端口,如 baidu.com:80
,另一个 Web 常用是 HTTPS 的 443 端口,如 baidu.com:443
。
当我们监听本地端口时,可使用 localhost
加上端口号来访问。运行上面的程序,可以通过localhost:3000/ 进行访问。
http.HandleFunc
http.HandleFunc
用以指定处理 HTTP 请求的函数,此函数允许我们只写一个 handler,请求会通过参数传递进来,使用者只需与 http.Request
和 http.ResponseWriter
两个对象交互即可。
在实例代码中,我们利用 fmt.Fprint
将 <h1>Hello, 这里是 goblog</h1>
子串写入 http.ResponseWriter
,即可响应用户请求。
http.Request
http.Request
是用户的请求信息,一般用 r
作为简写。
一些常见的操作如:
r.URL.Query()
获取用户参数- 获取客户端信息
r.Header.Get("User-Agent")
http.ResponseWriter
http.ResponseWriter
是返回用户的响应,一般用 w
作为简写。
常见操作如:
- 返回 500 状态码
w.WriteHeader(http.StatusInternalServerError)
- 设置返回标头
w.Header().Set("name", "my name is smallsoup")
总结
至此,关于Web程序我们就完成了简单的了解。我们通过http.ListenAndServe
来对本地的端口进行监听,等待用户的操作。使用http.HandleFunc
来完成当用户做出指定操作时的动作。handlerFunc
函数则是我们自己定义的一系列动作,等待HandleFunc
调用。