跟着极客兔兔大佬学习go搭建一个简单的web框架 大佬的代码简单易懂,由浅到深,保姆级教程啊。github给个start
- DAY1
- 前置知识点:
- net/http包中用ListenAndServe监听请求,handle方法注册路由和路由请求函数
- 实现了Handle接口ServerHTTP方法的实例Engine,作为处理路由和后续操作类。
- 前置知识点:
- 了解go语言自带net/http包,开启web服务基本步骤。
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler)//域名访问handle函数
http.HandleFunc("/count", counter)
//http.ListenAndServe() 监听8000端口
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
//handle 对应路由请求的函数
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}
- 构建Handle接口ServerHTTP方法的实例Engine,将所有的HTTP请求转向了我们自己的处理逻辑处理方法。此后可在Engine类上实现,动态路由、中间件、鉴权等功能。我们将成功脱离net/http包。
http基础包代码
package http
//engine实现此方法既可
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}
func ListenAndServe(address string, h Handler) error
Engine实现ServeHTTP方法,拦截所有http请求,在内部自行处理,好厉害!在go的net/http包基础上,完成这个操作就可以做自己的web框架了!!!!
package main
import (
"fmt"
"log"
"net/http"
)
//定义一个Engine类型
type Engine struct{}
//实现了ServeHTTP接口
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
switch req.URL.Path {
case "/":
fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
case "/hello":
for k, v := range req.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
default:
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
}
//简单的项目入口代码~~看着就舒服
func main() {
engine := new(Engine)
log.Fatal(http.ListenAndServe(":9999", engine))
}
- 抽离gee包,开启搭建框架第一步
框架代码目录
gee/
|--gee.go
|--go.mod
main.go
go.mod
不知道是go版本原因,还是我本地项目比较多,我搭建后需要构建多一个work.go文件,goland才会识别,最终目录
gee/
|--gee.go
|--go.mod
main.go
go.mod
go.work
go.work内容
go 1.18
use (
.
gee
)
好了,继续学习,gee.go实现Engine类,并暴露GET和POST和Run方法,至此,第一天学习完成。
package gee
import "net/http"
//定义一个HandlerFunc类型,用来处理请求
type HandlerFunc func(w http.ResponseWriter, r *http.Request)
//定义一个Engine类型,实现了ServeHTTP接口
type Engine struct {
router map[string]HandlerFunc
}
//定义一个ServeHTTP方法,实现了http.Handler接口
func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
key := r.Method + "-" + r.URL.Path
if handler, ok := engine.router[key]; ok {
handler(w, r)
} else {
//http.StatusNotFound = 404 定义了一些常用的HTTP状态码
w.WriteHeader(http.StatusNotFound)
_, _ = w.Write([]byte("404 NOT FOUND: " + r.URL.Path))
}
}
func New() *Engine {
return &Engine{router: make(map[string]HandlerFunc)}
}
//定义一个addRoute方法,用来添加路由 基础方法
func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
key := method + "-" + pattern
engine.router[key] = handler
}
func (engine *Engine) GET(pattern string, handler HandlerFunc) {
engine.addRoute("GET", pattern, handler)
}
func (engine *Engine) POST(pattern string, handler HandlerFunc) {
engine.addRoute("POST", pattern, handler)
}
//定义一个Run方法,用来启动一个http服务
func (engine *Engine) Run(addr string) (err error) {
return http.ListenAndServe(addr, engine)
}