五步用golang封装自己web框架httper:第一步,封装httper结构体,实现路由基础API

前言

学习了极客兔兔的7天用Go从零实现Web框架Gee教程后,感觉很受用,因此写下如下文章。

  • 一是为了学习go的基础知识和http框架。
  • 二是在使用gin框架时,觉得处理麻烦,不符合自己工作逻辑,干脆自己写一个框架,同时通过go interface简单封装实现gin的相关功能,在实现基本功能的同时保持go内置库http的高扩展性。
  • 三是课程比较简单,不涉及算法和高复杂度操作,自认为比较适合golang初学者,本人也是个初学者,有什么讲不到位的请留言交流。

源码在此:github.com/golangpoke/httper

首先根据go1.22标准库中新增的http.ServerMux路由复用器封装基本GET/POST/PUT/DELETE方法

http.go

package httper
import (
    "fmt"
    "net/http"
)
type serveMux struct {
    mux *http.ServeMux
}
func New() *serveMux {
    return &serveMux{
        mux: http.NewServeMux(),
    }
}
func (sm *serveMux) GET(router string, handler http.Handler) {
    sm.registerRouter(http.MethodGet, router, handler)
}
func (sm *serveMux) POST(router string, handler http.Handler) {
    sm.registerRouter(http.MethodPost, router, handler)
}
func (sm *serveMux) PUT(router string, handler http.Handler) {
    sm.registerRouter(http.MethodPut, router, handler)
}
func (sm *serveMux) DELETE(router string, handler http.Handler) {
    sm.registerRouter(http.MethodDelete, router, handler)
}
func (sm *serveMux) registerRouter(method string, router string, handler http.Handler) {
    router = fmt.Sprintf("%s %s", method, router)
    sm.mux.Handle(router, handler)
}
func (sm *serveMux) Start(addr string) error {
    return http.ListenAndServe(addr, sm.mux)
}

测试

http_test.go

package httper_test
import (
    "fmt"
    "github.com/golangpoke/httper"
    "net/http"
    "testing"
)
func TestServeMux_Run(t *testing.T) {
    mux := httper.New()
    mux.POST("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        _, err := w.Write([]byte(fmt.Sprintf("url: %s", r.URL.Path)))
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    }))
    mux.POST("/api/v1/{value}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        value := r.PathValue("value")
        if value == "" {
            http.Error(w, "value is empty", http.StatusBadRequest)
            return
        }
        _, err := w.Write([]byte(fmt.Sprintf("path value: %s", value)))
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    }))
    t.Fatal(mux.Start(":8000"))
}

测试结果

POST 127.0.0.1:8000/api/v1/test

path value: test
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!