j

jaryue

V1

2023/03/30阅读:17主题:默认主题

gowebday6 and day7

  1. 实现静态资源服务(Static Resource)。
  2. 支持HTML模板渲染。
  3. 实现错误处理机制。

gee6.go新增

  1. 重构engine节点新增
type Engine struct {
 *RouterGroup                     //分组
 Router        *Rrouter           //路由的映射
 Groups        []*RouterGroup     // 储存所有的分组
 htmlTemplates *template.Template // 将所有的模板加载进内存
 funcMap       template.FuncMap   // 所有的自定义模板渲染函数
}
  1. 定义createStaticHandler() 函数与Static() 函数
    createStaticHandler() 函数创建了一个处理静态文件请求的 HandlerFunc。它接收两个参数:相对路径 relativePath 和文件系统 fs。该函数返回另一个 HandlerFunc,该函数负责检查请求的文件是否存在并且是否可以访问,如果可以访问,就使用 http.FileServer 将文件传输给客户端。
    Static() 函数是将静态文件服务器注册到路由中的函数。它接收两个参数:相对路径 relativePath 和静态文件的根目录 root。它调用 createStaticHandler() 函数创建一个 HandlerFunc,并将其注册到路由器中,以便在请求 URL 匹配特定模式时调用。
// createStaticHandler() 函数创建了一个处理静态文件请求的 HandlerFunc。
// 它接收两个参数:相对路径 relativePath 和文件系统 fs。该函数返回另一个 HandlerFunc,该函数负责检查请求的文件是否存在并且是否可以访问
// ,如果可以访问,就使用 http.FileServer 将文件传输给客户端。
func (group *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc {
 absolutePath := path.Join(group.Prefix, relativePath)
 fileServer := http.StripPrefix(absolutePath, http.FileServer(fs))
 return func(c *Context) {
  file := c.Param("filepath")
  if _, err := fs.Open(file); err != nil {
   c.Status(http.StatusNotFound)
   return
  }

  fileServer.ServeHTTP(c.Writer, c.Req)
 }
}

// Static() 函数是将静态文件服务器注册到路由中的函数。
// 它接收两个参数:相对路径 relativePath 和静态文件的根目录 root。它调用 createStaticHandler() 函数创建一个 HandlerFunc,并将其注册到路由器中,以便在请求 URL 匹配特定模式时调用。
func (group *RouterGroup) Static(relativePath string, root string) {
 handler := group.createStaticHandler(relativePath, http.Dir(root))
 urlPattern := path.Join(relativePath, "/*filepath")
 group.GET(urlPattern, handler)
}
  1. 定义setfuncmap函数,将设置 HTML 模板中使用的函数,接收一个 template.FuncMap 类型的参数,将其存储到 engine.funcMap 中。
// 设置 HTML 模板中使用的函数,接收一个 template.FuncMap 类型的参数,将其存储到 engine.funcMap 中。
func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
 engine.funcMap = funcMap
}
  1. 定义LoadHTMLGlob函数,用于加载 HTML 模板文件,接收一个字符串类型的参数 pattern,表示要加载的模板文件的路径。该方法首先通过 template.New("") 创建了一个空的模板,然后通过 engine.funcMap 将模板中使用的函数添加到模板中,最后调用 template.ParseGlob(pattern) 加载指定路径下的所有模板文件,并通过 template.Must() 将加载的模板文件包装成一个不可变的 template.Template 类型,并将其存储到 engine.htmlTemplates 中。这样,在程序运行过程中,就可以通过 engine.htmlTemplates 调用 HTML 模板了。
// 用于加载 HTML 模板文件,接收一个字符串类型的参数 pattern,表示要加载的模板文件的路径。
// 该方法首先通过 template.New("") 创建了一个空的模板,然后通过 engine.funcMap 将模板中使用的函数添加到模板中,
// 最后调用 template.ParseGlob(pattern) 加载指定路径下的所有模板文件,并通过 template.Must() 将加载的模板文件包装成一个不可变的 template.Template 类型,
// 并将其存储到 engine.htmlTemplates 中。这样,在程序运行过程中,就可以通过 engine.htmlTemplates 调用 HTML 模板了。
func (engine *Engine) LoadHTMLGlob(pattern string) {
 engine.htmlTemplates = template.Must(template.New("").Funcs(engine.funcMap).ParseGlob(pattern))
}

context6.go新增

  1. 结构体context ,新增engine属性,为了能够通过 Context 访问 Engine 中的 HTML 模板。实例化 Context 时,还需要给 c.engine 赋值。
type Context struct {
 Writer http.ResponseWriter //Writer: 一个 http.ResponseWriter 类型的对象,用于将响应内容写入 HTTP 响应体。
 Req    *http.Request       //Req: 一个 *http.Request 类型的指针,表示客户端发起的 HTTP 请求。
 Path   string            //一个字符串,表示请求的 URL 路径。
 Method string            //一个字符串,表示请求的 HTTP 方法。get/post...
 Params map[string]string //一个字符串到字符串的映射,表示 URL 查询参数或表单数据。
 StatusCode int //一个整数,表示 HTTP 响应状态码。
 Handlers []HandlerFunc //handlers: 一个 HandlerFunc 类型的切片,表示当前请求需要经过的中间件函数列表。
 Index    int           //index: 一个整数,表示当前执行到的中间件函数在 handlers 中的下标。可以理解为handers的下标
 engine   *Engine      //新增能够通过 Context 访问 Engine 中的 HTML 模板。实例化 Context 时,还需要给 c.engine 赋值。
}

错误处理

新增中间件\

  1. 定义trace 函数:用于获取当前的调用栈信息,并格式化为一个字符串返回。首先通过 runtime.Callers 获取当前调用栈信息,然后通过 runtime.FuncForPC 和 fmt.Sprintf 函数将每个调用栈的函数名、文件名和行号信息格式化为字符串。该函数可以帮助开发人员快速定位程序错误的来源。
func trace(message string) string {
 var pcs [32]uintptr
 n := runtime.Callers(3, pcs[:]) // skip first 3 caller

 var str strings.Builder
 str.WriteString(message + "\nTraceback:")
 for _, pc := range pcs[:n] {
  fn := runtime.FuncForPC(pc)
  file, line := fn.FileLine(pc)
  str.WriteString(fmt.Sprintf("\n\t%s:%d", file, line))
 }
 return str.String()
}

  1. 定义Recovery 函数:返回一个 HandlerFunc 类型的函数,即 HTTP 处理器函数。该函数会在 Web 框架处理请求时被调用。在该函数内部,首先使用 defer 关键字将捕获 panic 的代码块延迟执行,然后执行下一步操作(调用 c.Next())。如果执行过程中出现 panic,则捕获该 panic 并执行 defer 代码块中的代码。在 defer 代码块中,将 panic 的信息格式化为字符串并传递给 trace 函数,然后使用 log.Printf 打印出错信息和调用栈。最后向客户端发送 "404 NOT FOUND" 和请求的 URL。
func Recovery() HandlerFunc {
 return func(c *Context) {
  defer func() {
   if err := recover(); err != nil {
    message := fmt.Sprintf("%s", err)
    log.Printf("%s\n\n", trace(message))
    // c.Fail(http.StatusInternalServerError, "Internal Server Error")
    fmt.Fprintf(c.Writer, "404 NOT FOUND: %s\n", c.Req.URL)
   }
  }()

  c.Next()
 }
}

分类:

后端

标签:

Golang

作者介绍

j
jaryue
V1