Golang 从入门到放弃 -0x0E
用 net/http 写最小 Web 服务,处理参数、返回 JSON,并组织基本路由。
铺垫了这么多章,终于可以写点像样的服务了。别急着上 gin、gorm、各种脚手架,这一章我们先用 Go 自带的 net/http 搭一个最小可用的 Web 服务。先把原理摸清,后面你用什么框架都不至于一脸懵。
一个最简单的 HTTP 服务
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello golang")
}
func main() {
http.HandleFunc("/hello", helloHandler)
fmt.Println("server running at :8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println(err)
}
}跑起来后,浏览器访问 http://127.0.0.1:8080/hello,就能看到输出。
这里有两个核心点:
http.HandleFunc注册路由http.ListenAndServe启动服务
处理请求参数
假设我们想从查询字符串里拿一个名字。
func helloHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "anonymous"
}
fmt.Fprintf(w, "hello, %s\n", name)
}这时访问:
http://127.0.0.1:8080/hello?name=Raymond就会得到:
hello, Raymond返回 JSON
后端更常见的工作不是吐一行文本,而是返回 JSON。这个时候就轮到前一章的知识上场了。
package main
import (
"encoding/json"
"net/http"
)
type Resp struct {
Message string `json:"message"`
Code int `json:"code"`
}
func pingHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
resp := Resp{
Message: "pong",
Code: 0,
}
json.NewEncoder(w).Encode(resp)
}这里我用了 json.NewEncoder(w).Encode(resp),因为它很适合直接把对象写进响应体里。
根据请求方法区分逻辑
很多接口会区分 GET、POST 等方法。你完全可以自己判断。
func userHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
w.Write([]byte("user list"))
}http.Error 是个挺顺手的小工具,能顺便帮你把状态码和错误文本一起回出去。
完整一点的示例
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Response struct {
Message string `json:"message"`
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "guest"
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(Response{
Message: "hello, " + name,
})
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/hello", helloHandler)
fmt.Println("server running at :8080")
if err := http.ListenAndServe(":8080", mux); err != nil {
fmt.Println(err)
}
}这时候你用 curl 测一下:
curl "http://127.0.0.1:8080/hello?name=go"返回大概会是:
{"message":"hello, go"}小结
到这里,你已经能用 Go 写出一个最基础的 HTTP 服务了。虽然离生产环境还很远,但轮子已经开始滚起来了。
HandleFunc注册处理函数。ListenAndServe启动服务。- 请求参数从
r里拿,响应通过w写回去。 - 返回 JSON 时,
json.NewEncoder很顺手。
如果这个系列继续往后写,下一步差不多就是数据库、测试、日志、配置、部署这些工程化内容了。到那时,你写出来的东西就不只是“能跑”,而是开始有一点“能上线”的味道了。