初学go,跟大佬搭建web框架笔记(一)

40 阅读2分钟

跟着极客兔兔大佬学习go搭建一个简单的web框架 大佬的代码简单易懂,由浅到深,保姆级教程啊。github给个start

Web框架 - Gee

  • DAY1
    • 前置知识点:
      • net/http包中用ListenAndServe监听请求,handle方法注册路由和路由请求函数
      • 实现了Handle接口ServerHTTP方法的实例Engine,作为处理路由和后续操作类。
  1. 了解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)
}

  1. 构建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))
}
  1. 抽离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)
}