在go语言中构建http服务器的核心是使用net/http包,通过定义处理器函数并调用http.listenandserve启动服务,例如用http.handlefunc注册路由后监听指定端口即可运行一个“hello, world!”服务器;其底层依赖http.handler接口、http.servemux多路复用器和http.listenandserve函数协同工作,其中handler处理请求,servemux负责路由分发,而listenandserve启动并监听服务;对于不同http方法的处理可通过r.method判断,并结合r.parseform()解析表单数据,路径参数虽无内置支持但可通过字符串分割简易实现或借助第三方库如gorilla/mux;错误处理应使用http.error返回对应状态码并记录日志,而优雅关停则需利用http.server的shutdown方法配合context和信号监听,在收到中断信号时停止接收新请求并等待正在进行的请求完成,从而确保服务的稳定与可靠。

在Go语言里构建一个HTTP服务器,其实远没有想象中那么复杂。核心就是利用标准库
net/http
要搭建一个最基础的HTTP服务器,你通常会用到
http.HandleFunc
http.ListenAndServe
一个典型的“Hello, World!”服务器代码会是这样:
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"fmt"
"log"
"net/http"
)
// homeHandler 处理根路径 "/" 的请求
func homeHandler(w http.ResponseWriter, r *http.Request) {
// http.ResponseWriter 接口用于构造HTTP响应
// *http.Request 结构体包含了客户端的请求信息
fmt.Fprintf(w, "你好,世界!这是我的第一个Go HTTP服务器。")
log.Printf("收到了来自 %s 的请求,路径是 %s", r.RemoteAddr, r.URL.Path)
}
// aboutHandler 处理 "/about" 路径的请求
func aboutHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "关于我们:一个简单的Go语言HTTP服务示例。")
log.Printf("收到了来自 %s 的请求,路径是 %s", r.RemoteAddr, r.URL.Path)
}
func main() {
// 注册URL路径与对应的处理函数
// 当用户访问 "/" 时,homeHandler会被调用
http.HandleFunc("/", homeHandler)
// 当用户访问 "/about" 时,aboutHandler会被调用
http.HandleFunc("/about", aboutHandler)
// 启动HTTP服务器,监听8080端口
// ListenAndServe会阻塞当前goroutine,直到服务器停止或发生错误
log.Println("服务器正在监听 http://localhost:8080")
err := http.ListenAndServe(":8080", nil) // nil 表示使用默认的ServeMux
if err != nil {
// 如果服务器启动失败(例如端口被占用),会在这里捕获错误
log.Fatalf("服务器启动失败: %v", err)
}
}
这段代码执行后,你就可以在浏览器中访问
http://localhost:8080
http://localhost:8080/about
net/http
当我们谈论Go的
net/http
首先是
http.Handler
ServeHTTP(w http.ResponseWriter, r *http.Request)
http.ResponseWriter
*http.Request
然后是
http.HandleFunc
http.Handler
http.HandleFunc
func(w http.ResponseWriter, r *http.Request)
http.HandlerFunc
http.HandlerFunc
http.Handler
再来是
http.ServeMux
http.Handler
http.HandleFunc
http.ServeMux
http.DefaultServeMux
http.ServeMux
// ... (imports and handlers remain the same)
func main() {
myMux := http.NewServeMux() // 创建一个新的ServeMux实例
myMux.HandleFunc("/", homeHandler)
myMux.HandleFunc("/about", aboutHandler)
log.Println("服务器正在监听 http://localhost:8080")
// 将我们自己的myMux传入ListenAndServe
err := http.ListenAndServe(":8080", myMux)
if err != nil {
log.Fatalf("服务器启动失败: %v", err)
}
}最后是
http.ListenAndServe
:8080
http.Handler
nil
http.DefaultServeMux
这些组件共同协作,构成了Go语言HTTP服务的基础框架。理解它们之间的关系,能帮助我们更好地设计和调试服务。
在实际的Web开发中,我们很少只处理单一的GET请求,而且URL往往包含各种参数。在Go的
net/http
对于不同的HTTP请求方法(GET, POST, PUT, DELETE等),你可以在同一个处理函数内部通过检查
r.Method
package main
import (
"fmt"
"log"
"net/http"
"strings" // 用于字符串操作
)
func itemHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
// 提取路径参数,例如 /items/123 中的 "123"
// 这是一个非常简陋的路径参数提取方式,实际项目中通常会用更强大的路由库
pathSegments := strings.Split(r.URL.Path, "/")
if len(pathSegments) > 2 && pathSegments[1] == "items" {
itemId := pathSegments[2]
fmt.Fprintf(w, "获取商品ID: %s 的信息", itemId)
log.Printf("GET请求:获取商品 %s", itemId)
} else {
fmt.Fprintf(w, "获取所有商品列表")
log.Printf("GET请求:获取所有商品")
}
case http.MethodPost:
// 处理POST请求,通常用于创建资源
// 需要解析请求体
err := r.ParseForm() // 解析表单数据(URL编码或multipart/form-data)
if err != nil {
http.Error(w, "无法解析表单数据", http.StatusBadRequest)
log.Printf("POST请求解析表单失败: %v", err)
return
}
itemName := r.FormValue("name") // 获取表单中的 "name" 字段
fmt.Fprintf(w, "创建新商品: %s", itemName)
log.Printf("POST请求:创建商品 %s", itemName)
case http.MethodPut:
// 处理PUT请求,通常用于更新资源
fmt.Fprintf(w, "更新商品信息")
log.Printf("PUT请求:更新商品")
case http.MethodDelete:
// 处理DELETE请求,通常用于删除资源
fmt.Fprintf(w, "删除商品")
log.Printf("DELETE请求:删除商品")
default:
// 处理其他不支持的方法
http.Error(w, "不支持的HTTP方法", http.StatusMethodNotAllowed)
log.Printf("不支持的请求方法: %s", r.Method)
}
}
func main() {
http.HandleFunc("/items/", itemHandler) // 注意末尾的斜杠,表示匹配 /items/anything
http.HandleFunc("/items", itemHandler) // 也要匹配 /items 本身
log.Println("服务器正在监听 http://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("服务器启动失败: %v", err)
}
}在这个
itemHandler
switch r.Method
net/http
strings.Split
gorilla/mux
至于请求体数据的解析,
r.ParseForm()
application/x-www-form-urlencoded
multipart/form-data
r.FormValue("key")r.Body
这些细节的处理,虽然增加了代码量,但却是构建一个功能完备HTTP服务不可或缺的部分。
一个健壮的服务器不仅仅要能响应请求,更重要的是能妥善处理错误,并在需要停止时能优雅地关闭,避免正在处理的请求中断。
错误处理: 在Go的HTTP处理函数中,错误通常通过
http.Error
http.Error
// ... (itemHandler function snippet)
case http.MethodPost:
err := r.ParseForm()
if err != nil {
http.Error(w, "无法解析表单数据", http.StatusBadRequest) // 发送400 Bad Request
log.Printf("POST请求解析表单失败: %v", err)
return
}
// ...对于内部服务器错误,通常使用
http.StatusInternalServerError
log.Printf
优雅关停:
http.ListenAndServe
Ctrl+C
SIGINT
Go 1.8 引入的
http.Server
Shutdown
context
os
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func homeHandler(w http.ResponseWriter, r *http.Request) {
// 模拟一个需要一些时间才能完成的请求
time.Sleep(5 * time.Second)
fmt.Fprintf(w, "你好,世界!请求已处理完毕。")
log.Printf("收到了来自 %s 的请求,路径是 %s", r.RemoteAddr, r.URL.Path)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", homeHandler)
// 创建一个http.Server实例,而不是直接使用ListenAndServe
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
// 创建一个用于监听系统信号的通道
done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGTERM) // 监听中断信号和终止信号
go func() {
// 在一个独立的goroutine中启动服务器
log.Println("服务器正在监听 http://localhost:8080")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
// 如果不是因为Shutdown导致的错误,则记录为致命错误
log.Fatalf("服务器启动失败: %v", err)
}
}()
// 主goroutine阻塞,直到收到系统信号
<-done
log.Println("收到停止信号,服务器开始优雅关停...")
// 创建一个带超时的上下文,给服务器一个固定时间来完成未完成的请求
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() // 确保上下文被取消,释放资源
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("服务器优雅关停失败: %v", err)
}
log.Println("服务器已成功关停。")
}这段代码做了几件事:它不再直接调用
http.ListenAndServe
http.Server
SIGINT
SIGTERM
server.Shutdown(ctx)
Shutdown
ctx
这些机制,从错误码的返回到服务器的平稳退出,都是构建可靠Web服务不可或缺的考量。
以上就是Golang构建HTTP服务器步骤 使用net/http包基础实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号