官方社群在线客服官方频道防骗查询货币工具

基于 Go 语言开发在线论坛(三):访问论坛首页

2025年01月14日 02:16:51
news.like.tgnews.like.tgnews.like.tgnews.like.tg

LIKE.TG 成立于2020年,总部位于马来西亚,是首家汇集全球互联网产品,提供一站式软件产品解决方案的综合性品牌。唯一官方网站:www.like.tg

1、整体流程

前面两篇教程学院君分别给大家介绍了基于 Go 语言构建在线论坛的整体设计以及数据表的创建、模型类的编写,今天我们来看看如何在服务端处理用户请求。

用户请求的处理流程如下:

  1. 客户端发送请求;
  2. 服务端路由器(multiplexer)将请求分发给指定处理器(handler);
  3. 处理器处理请求,完成对应的业务逻辑;
  4. 处理器调用模板引擎生成 HTML 并将响应返回给客户端。

接下来我们按照这个流程来编写服务端代码。

2、定义路由器

这里我们基于 gorilla/mux 来实现路由器,所以需要安装对应依赖:

代码语言:javascript
复制
go get github.com/gorilla/mux

然后我们遵循仿照 Laravel 框架对 Go 路由处理器代码进行拆分这篇教程介绍的组织架构将路由器定义在 routes 目录下的 router.go 中:

代码语言:javascript
复制
package routes import "github.com/gorilla/mux" // 返回一个 mux.Router 类型指针,从而可以当作处理器使用 func NewRouter() *mux.Router { // 创建 mux.Router 路由器示例 router := mux.NewRouter().StrictSlash(true) // 遍历 web.go 中定义的所有 webRoutes for _, route := range webRoutes { // 将每个 web 路由应用到路由器 router.Methods(route.Method). Path(route.Pattern). Name(route.Name). Handler(route.HandlerFunc) } return route }

将所有路由定义在同一目录的 routes.go 中:

代码语言:javascript
复制
package routes import "net/http" // 定义一个 WebRoute 结构体用于存放单个路由 type WebRoute struct { Name string Method string Pattern string HandlerFunc http.HandlerFunc } // 声明 WebRoutes 切片存放所有 Web 路由 type WebRoutes []WebRoute // 定义所有 Web 路由 var webRoutes = WebRoutes{ }

3、启动 HTTP 服务器

最后在项目根目录下的 main.go 中引入上述路由器来启动 HTTP 服务器:

代码语言:javascript
复制
package main import ( . "github.com/xueyuanjun/chitchat/routes" "log" "net/http" ) func main() { startWebServer("8080") } // 通过指定端口启动 Web 服务器 func startWebServer(port string) { r := NewRouter() http.Handle("/", r) // 通过 router.go 中定义的路由器来分发请求 log.Println("Starting HTTP service at " + port) err := http.ListenAndServe(":" + port, nil) // 启动协程监听请求 if err != nil { log.Println("An error occured starting HTTP listener at port " + port) log.Println("Error: " + err.Error()) } }

具体代码含义已经在注释中介绍清楚了,这里我们指定 HTTP 服务器监听 8080 端口,使用的路由器正是上述 router.go 中 NewRouter 方法返回的 mux.Router 指针类型实例,这里可以看到引用的时候并没有带上包名前缀,之所以可以这么做是因为通过如下这种方式引入的 routes 包:

代码语言:javascript
复制
. "github.com/xueyuanjun/chitchat/routes"

注意到前面的 . 别名,通过这种方式引入的包可以直接调用包中对外可见的变量、方法和结构体,而不需要加上包名前缀。

还有一种方式是通过 _ 别名引入,这样一来只会调用该包里定义的 init 方法,我们在上篇教程引入 go-sql-driver/mysql 包时就是这么做的:

代码语言:javascript
复制
_ "github.com/go-sql-driver/mysql"

4、处理静态资源

在线论坛涉及到前端静态资源文件的处理,我们可以在 startWebServer 方法中新增如下这两行代码:

代码语言:javascript
复制
r := NewRouter() // 通过 router.go 中定义的路由器来分发请求 // 处理静态资源文件 assets := http.FileServer(http.Dir("public")) r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", assets)) http.Handle("/", r) // 应用路由器到 HTTP 服务器 ...

其中 http.FileServer 用于初始化文件服务器和目录为当前目录下的 public 目录。

然后在第二段代码中指定静态资源路由及处理逻辑:将 /static/ 前缀的 URL 请求去除 static 前缀,然后在文件服务器查找指定文件路径是否存在(public 目录下的相对地址)。

比如 URL 请求路径为 http://localhost:8080/static/css/bootstrap.min.css,对应的查找路径是:

代码语言:javascript
复制
<application root>/public/css/bootstrap.min.css

对于静态资源文件直接返回文件内容,不会进行额外处理。

5、编写处理器实现

1)首页处理器方法

做好上述准备工作后,接下来,我们来创建论坛首页的路由处理器,在 handlers 目录下新增一个 index.go 来定义首页的处理器方法:

代码语言:javascript
复制
package handlers import ( "github.com/xueyuanjun/chitchat/models" "html/template" "net/http" ) // 论坛首页路由处理器方法 func Index(w http.ResponseWriter, r *http.Request) { files := []string{"views/layout.html", "views/navbar.html", "views/index.html",} templates := template.Must(template.ParseFiles(files...)) threads, err := models.Threads(); if err == nil { templates.ExecuteTemplate(w, "layout", threads) } }

2)创建视图模板

这里我们使用 Go 自带的 html/template 作为模板引擎,需要传入位于 views 目录下的视图模板文件,这里传入了多个模板文件,包括主布局文件 layout.html:

代码语言:javascript
复制
{{ define "layout" }} <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=9"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ChitChat</title> <link href="/static/css/bootstrap.min.css" rel="stylesheet"> <link href="/static/css/font-awesome.min.css" rel="stylesheet"> </head> <body> {{ template "navbar" . }} <div class="container"> {{ template "content" . }} </div> <!-- /container --> <script src="/static/js/jquery-2.1.1.min.js"></script> <script src="/static/js/bootstrap.min.js"></script> </body> </html> {{ end }}

顶部导航模板 navbar.html:

代码语言:javascript
复制
{{ define "navbar" }} <div class="navbar navbar-default navbar-static-top" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> <i class="fa fa-comments-o"></i> ChitChat </a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="/login">Login</a></li> </ul> </div> </div> </div> {{ end }}

以及首页视图模板 index.html:

代码语言:javascript
复制
{{ define "content" }} <p class="lead"> <a href="/thread/new">Start a thread</a> or join one below! </p> {{ range . }} <div class="panel panel-default"> <div class="panel-heading"> <span class="lead"> <i class="fa fa-comment-o"></i> {{ .Topic }}</span> </div> <div class="panel-body"> Started by {{ .User.Name }} - {{ .CreatedAtDate }} - {{ .NumReplies }} posts. <div class="pull-right"> <a href="/thread/read?id={{.Uuid }}">Read more</a> </div> </div> </div> {{ end }} {{ end }}

引入多个视图模板是为了提高模板代码的复用性,因为对于同一个应用的不同页面来说,可能基本布局、页面顶部导航和页面底部组件都是一样的,关于视图模板的细节,我们在后面视图模板部分会详细介绍,这里简单了解下即可。

3)渲染视图模板

我们可以从数据库查询群组数据并将该数据传递到模板文件,最后将模板视图渲染出来,对应代码如下:

代码语言:javascript
复制
threads, err := models.Threads(); if err == nil { templates.ExecuteTemplate(w, "layout", threads) }

编译多个视图模板时,默认以第一个模板名作为最终视图模板名,所以这里第二个参数传入的是 layout,第三个参数传入要渲染的数据 threads,对应的渲染逻辑位于 views/index.html 中:

代码语言:javascript
复制
{{ range . }} <div class="panel panel-default"> <div class="panel-heading"> <span class="lead"> <i class="fa fa-comment-o"></i> {{ .Topic }}</span> </div> <div class="panel-body"> Started by {{ .User.Name }} - {{ .CreatedAtDate }} - {{ .NumReplies }} posts. <div class="pull-right"> <a href="/thread/read?id={{.Uuid }}">Read more</a> </div> </div> </div> {{ end }}

其中 {{ range . }} 表示将处理器方法传入的变量,这里是 threads 进行循环。

4)注册首页路由

最好,我们在 routes/routes.go 中注册首页路由及对应的处理器方法 Index:

代码语言:javascript
复制
import "github.com/xueyuanjun/chitchat/handlers" // 定义所有 Web 路由 var webRoutes = WebRoutes{ { "home", "GET", "/", handlers.Index, }, }

6、访问论坛首页

访问论坛首页之前,我们将相应的前端资源文件拷贝到 public 目录下,此时项目整体目录结构如下:

注:对应的前端资源可以从项目的 Github 仓库获取:https://github.com/nonfu/chitchat.git。

然后我们在项目根目录下运行如下代码启动 HTTP 服务器:

代码语言:javascript
复制
go run main.go

然后我们在浏览器访问论坛首页 http://localhost:8080:

一切与预期一致,下篇教程,我们将基于 Cookie + Session 实现用户认证并创建群组和主题。

现在关注【LIKE.TG出海指南频道】【LIKE.TG大客户服务频道】,即可免费领取【WhatsApp、LINE、Telegram、Twitter、ZALO云控】等获客工具试用、【住宅IP、号段筛选】等免费资源,机会难得,快来解锁更多资源,助力您的业务飞速成长!点击【联系客服】

本文由LIKE.TG编辑部转载自互联网并编辑,如有侵权影响,请联系官方客服,将为您妥善处理。

This article is republished from public internet and edited by the LIKE.TG editorial department. If there is any infringement, please contact our official customer service for proper handling.


Server deployment全球论坛人工智能论坛全球峰会发展论坛战略论坛开放论坛程序员论坛互联网峰会科技峰会
加入like.tg生态圈,即可获利、结识全球供应商、拥抱全球软件生态圈加入like.tg生态圈,即可获利、结识全球供应商、拥抱全球软件生态圈加入like.tg生态圈,即可获利、结识全球供应商、拥抱全球软件生态圈
加入like.tg生态圈,即可获利、结识全球供应商、拥抱全球软件生态圈加入like.tg生态圈,即可获利、结识全球供应商、拥抱全球软件生态圈加入like.tg生态圈,即可获利、结识全球供应商、拥抱全球软件生态圈