自己搭建网站的步骤,网络服务提供者接到通知后,厦门网站建设平台,云南百度建站苦学golang半年#xff0c;写了一款web服务器 文章目录 苦学golang半年#xff0c;写了一款web服务器example 项目地址#xff1a;https://github.com/fengyuan-liang/jet-web-fasthttp 苦学golang半年#xff0c;写了一款web服务器#xff0c;里面包含笔者各种工程实践写了一款web服务器 文章目录 苦学golang半年写了一款web服务器example 项目地址https://github.com/fengyuan-liang/jet-web-fasthttp 苦学golang半年写了一款web服务器里面包含笔者各种工程实践大佬勿喷
为什么不使用Gin而要自己开发一款web服务器呢其实gin已经非常好了笔者这里主要是想要把自己开发中的工程实践提炼出来打造出更加顺手的兵器️现在还只是个玩具大家看个乐子就行
那么在使用Gin中有哪些痛点呢 繁琐的路由表在Gin中必须写路由表来映射路由再写对应的func(ctx *gin.Context )总感觉多写了一次而且接口一多看着一望无际的路由表总感觉划分的不是很优雅而且不太好找自己想要的接口并且笔者在写springBoot项目时非常喜欢用restful插件来找路由比如输入/v1/xxx/xxx/xxx就能找到对应的路由但是在gin的路由表不是很好找 每个gin的路由都必须要手动获取参数然后校验校验不通过再返回错误像下面那样这部分逻辑感觉完全应该复用完全忍受不了写重复代码。参数就应该交给框架解析或者说有切面或者hook来统一完成这部分的逻辑 // gin
engine.Get(/v1/xxx, xxx)func xxx(ctx *gin.Context) {var (err errorparams xxxx)// Bind your param dataif err ShouldBindQuery(ctx, params); err ! nil {ctx.AbortWithStatusJSON(http.StatusOK, traceId, 400, bad request))return}// validator your paramif err validator.New().Struct(params) ;err ! nil {ctx.AbortWithStatusJSON(http.StatusOK, traceId, 400, bad request))return}// do you codectx.JSON(http.StatusOK, traceId, ok))
}
// 相比之下参数Jet会自动帮你注入到你的参数列表里面并且可以定义Hook统一在参数解析完毕调用我们自己方法之前处理参数校验的逻辑
// Jet
func(YourJetController) GetV1Xxx(ctx jet.Ctx, args *Xxx) (any, error) {// do you codereturn xxx, err
}接下来不是Gin的缺点毕竟Gin只是一个基础的web框架就是笔者更喜欢MVC架构或者DDD模式开发这里面使用到依赖注入管理生命周期是比较合适的笔者也不喜欢用类似wire需要生成代码的方式进行依赖注入所有笔者使用Dig进行依赖注入反射的方式其实也只影响项目启动的时间但是go的启动本身就很快了看不出啥影响 然后就是定义了一些常用的数据结构例如Trie、LinkedHashMap在golang里面其实提供的数据结构挺少的但是像LinkedHashMap用的地方其实很多我们需要O(1)级别的查找和添加又需要有序的集合顺序 func TestLinkedHashMap(t *testing.T) {m : maps.NewLinkedHashMap[string, int]()m.Put(one, 1)m.Put(two, 2)m.Put(three, 3)m.ForEach(func(k string, v int) {t.Logf(%s: %d\n, k, v)})
}$ go test -run TestLinkedHashMap
one: 1
two: 2
three: 3
PASS
ok GoKit/collection/maps 0.166sexample 下面是使用的一个例子 func main() {//jet.Register(DemoController{})xlog.SetOutputLevel(xlog.Ldebug)jet.AddMiddleware(jet.TraceJetMiddleware)jet.Run(:8080)
}// 使用依赖注入的方式注入需要让Jet管理的Controller
func init() {jet.Provide(NewDemoController)
}func NewDemoController() jet.ControllerResult {return jet.NewJetController(DemoController{})
}type BaseController struct {jet.IJetController
}// 对参数进行校验如果不通过会返回reg_err_info中定义的错误
func (BaseController) PostParamsParseHook(param any) error {if err : utils.Struct(param); err ! nil {return errors.New(utils.ProcessErr(param, err))}return nil
}// PostMethodExecuteHook restful 将所有请求以restful方式返回
func (BaseController) PostMethodExecuteHook(param any) (data any, err error) {// restfulreturn utils.ObjToJsonStr(param), nil
}// 上面的两个hook可以直接让controller继承jet.BaseJetController这样就不用写了type DemoController struct {BaseController
}type Person struct {Name string json:name validate:required reg_err_info不能为空 // 校验不通过会返回reg_err_info的内容Age int json:age
}// 路由 get /v1/usage/{id}/week 已经可以访问了
func (j *DemoController) GetV1Usage0Week(ctx jet.Ctx, args *jet.Args) (any, error) {ctx.Logger().Infof(GetV1Usage0Week %v, *args)return map[string]any{request_id: ctx.Logger().GenReqId(), code: 200, data: args}
}$ curl http://localhost:8080/v1/usage/1/week
{request_id:H5OQ4Jg0yBtg,code:200,message:success,data:[1]}正常情况下会打印日志的全路径我们在启动时候加上-trimpath就可以只打印项目的path