Go语言内置net/http库,封装HTTP编程的基础接口,启动HTTP特别简单
标准库启动web
创建一个main文件
package main
import (
"net/http"
)
func main(){
http.HandleFunc("/",indexHandler)
http.ListenAndServe("",nil)
}
func indexHandler(w http.ResponseWriter, r *http.Request){
w.Write([]byte("hello go web"))
}
运行代码在打开浏览器,查看
我们只设置了一个路由 “/” ,绑定了indexHandler,匹配路由调用函数。
http.ListenAndServe()函数有两个参数,第一个为监听地址,第二个为Handler,如果为nil那么调用默认Handler,我们也可以自定义handler,启动web服务。
实现自定义Handler
GO语言net/http库中
package http
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
func ListenAndServe(addr string, handler Handler) error
Handler为一个接口类型,那么新建一个结构体,实现ServeHTTP()方法就创建了一个Handler,试一下吧!
package main
import (
"net/http"
)
//新建一个结构体
type Engine struct {}
//实现ServeHTTP方法
func(engie *Engine)ServeHTTP(w http.ResponseWriter, r *http.Request){
switch r.URL.Path {
case "/":
w.Write([]byte("hello go web"))
case "/red":
w.Write([]byte("hello b ge"))
}
}
func main(){
//创建结构体实例
engine := &Engine{}
//启动服务
http.ListenAndServe("",engine)
}
浏览器验证:
我们定义了一个空的结构体Engine,实现了ServeHTTP方法,这个方法有2个参数,第二个参数是 Request ,该对象包含了该HTTP请求的所有的信息,比如请求地址、Header和Body等信息;第一个参数是 ResponseWriter ,利用 ResponseWriter 可以构造针对该请求的响应。
在 main 函数中,我们给 ListenAndServe 方法的第二个参数传入了刚才创建的engine实例。至此,我们走出了实现Web框架的第一步,即,将所有的HTTP请求转向了我们自己的处理逻辑,代码的运行结果与之前的是一致的。
框架雏形
目录说明
.
└── go-user
├── README.md
├── go.mod
├── go.sum
├── main.go
└── red
└── red.go
go.mod
module go-user
go 1.14
main.go
package main
import (
"go-user/red"
"net/http"
)
func main() {
r := red.New()
r.GET("/red", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello b ge"))
})
r.Run(":8080")
}
端口地址定义为“8080”
red.go
package red
import (
"fmt"
"net/http"
)
//定义函数为HandlerFunc类型
type HandlerFunc func(http.ResponseWriter, *http.Request)
//定义Engine结构体
type Engine struct {
route map[string]HandlerFunc
}
//实现ServeHTTP方法 根据请求的方法及路径来匹配Handler
func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
key := r.Method + "-" + r.URL.Path
if handler, ok := engine.route[key]; ok {
handler(w, r)
} else {
fmt.Fprintf(w, "404 NOT FOUND %s ", r.URL.Path)
}
}
//外部调用框架入口
func New() *Engine {
return &Engine{make(map[string]HandlerFunc)}
}
//框架新增路由
func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
key := method + "-" + pattern
engine.route[key] = handler
}
//匹配get方法
func (engine *Engine) GET(pattern string, handler HandlerFunc) {
engine.addRoute("GET", pattern, handler)
}
//匹配post方法
func (engine *Engine) POST(pattern string, handler HandlerFunc) {
engine.addRoute("POST", pattern, handler)
}
//启动服务
func (engine *Engine) Run(addr string) (err error) {
return http.ListenAndServe(addr, engine)
}
我们重点介绍一下这部分的实现。
首先定义了类型HandlerFunc,这是提供给框架用户的,用来定义路由映射的处理方法。我们在Engine中,添加了一张路由映射表router,key 由请求方法和静态路由地址构成,例如GET-/、GET-/hello、POST-/hello,这样针对相同的路由,如果请求方法不同,可以映射不同的处理方法(Handler),value 是用户映射的处理方法。
当用户调用(*Engine).GET()方法时,会将路由和处理方法注册到映射表 router 中,(*Engine).Run()方法,是 ListenAndServe 的包装。
Engine实现的 ServeHTTP 方法的作用就是,解析请求的路径,查找路由映射表,如果查到,就执行注册的处理方法。如果查不到,就返回 404 NOT FOUND 。
执行go run main.go,
启动浏览器验证:
至此,框架原型出来了,慢慢完善!