首页
学习
活动
专区
圈层
工具
发布
16 篇文章
1
Go 语言 Web 编程系列(一)—— 快速入门:创建第一个 Web 应用
2
Go 语言 Web 编程系列(二)—— HTTP 请求处理的底层运行机制
3
Go 语言 Web 编程系列(三)—— 基于官方标准库自定义路由处理器
4
Go 语言 Web 编程系列(四)—— 基于 gorilla/mux 包实现路由定义:基本使用篇
5
Go 语言 Web 编程系列(五)—— 基于 gorilla/mux 包实现路由匹配:进阶使用篇
6
Go 语言 Web 编程系列(六)—— 基于 gorilla/mux 包实现路由匹配:路由中间件
7
Go 语言 Web 编程系列(七)—— 基于 gorilla/mux 包实现路由匹配:处理静态资源响应
8
Go 语言 Web 编程系列(八)—— 基于 gorilla/mux 包实现路由匹配:服务 SPA 应用
9
Go 语言 Web 编程系列(九)—— 基于 gorilla/mux 包实现路由匹配:通过 CORS 处理跨域请求
10
Go 语言 Web 编程系列(十)—— 基于 gorilla/mux 包实现路由匹配:健康检查与接口测试
11
Go 语言 Web 编程系列(十一)—— 仿照 Laravel 框架对 Go 路由代码进行拆分
12
Go 语言 Web 编程系列(十二)—— 通过 Request 读取 HTTP 请求报文
13
Go 语言 Web 编程系列(十三)—— 获取用户请求数据(上)
14
Go 语言 Web 编程系列(十四)—— 获取用户请求数据(下)
15
Go 语言 Web 编程系列(十五)—— 通过 ResponseWriter 接口创建 HTTP 响应
16
Go 语言 Web 编程系列(十六)—— 设置、读取和删除 Cookie

Go 语言 Web 编程系列(八)—— 基于 gorilla/mux 包实现路由匹配:服务 SPA 应用

随着前后端分离的大势所趋,后端应用为前端单页面应用(SPA,通常由 Vue、React 等前端框架构建)提供包含数据的 API 接口,然后由前端代码负责路由跳转和渲染变得越来越流行,gorilla/mux 包也对此功能特性提供了开箱支持。

要演示完整的前后端分离单页面应用,需要先初始化前端应用,以基于 Vue.js 构建前端应用为例,使用 Vue CLI 初始化一个名为 gospa 的 Vue 应用,可以在任意目录下创建(需要安装过 Vue CLI 才能执行以下初始化命令):

代码语言:javascript
复制
vue create gospa
cd gospa
yarn serve
代码语言:javascript
复制

启动应用后,可以按照提示在浏览器通过 http://localhost:8080/ 访问应用首页:

接下来,我们通过 Go 后端实现 HTTP 服务器来托管前端应用和资源访问。

对于单页面应用,只需在首次访问时请求后端入口路由初始化前端资源,后续交互都是通过前端代码调用后端 API 接口完成数据渲染,从用户角度来说,页面不会刷新,所以看起来就像只有一个单页面。因此,我们只需要在后端入口处定义一个返回初始化前端资源的 HTML 模板视图即可(这个 HTML 文档中引入了前端应用入口 JavaScript 文件以及必要的 CSS 文件),在 gospa 应用根目录下新建一个 server.go,并编写后端实现代码如下:

代码语言:javascript
复制
代码语言:javascript
复制
package main

import (
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "os"
    "path/filepath"
    "time"
)

// spaHandler 实现了 http.Handler 接口,所以可以用来处理 HTTP 请求
// 其中 staticPath 用于定义前端静态资源目录(包含js、css 文件)
// indexPath 用于定义入口视图模板文件,通常是 index.html
type spaHandler struct {
    staticPath string
    indexPath  string
}

// 处理 SPA 应用请求(主要是首次访问时入口 HTML 文档和相关静态资源文件,暂不涉及 API 接口)
func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // 获取 URL 路径的绝对路径
    path, err := filepath.Abs(r.URL.Path)
    if err != nil {
        // 如果获取失败,返回 400 响应
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // 在 URL 路径前加上静态资源根目录
    path = filepath.Join(h.staticPath, path)

    // 检查对应资源文件是否存在
    _, err = os.Stat(path)
    if os.IsNotExist(err) {
        // 文件不存在返回入口 HTML 文档内容作为响应
        http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
        return
    } else if err != nil {
        // 如果期间报错,返回 500 响应
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // 一切顺利,则使用 http.FileServer 处理静态资源请求
    http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
}

func main()  {
    router := mux.NewRouter()

    spa := spaHandler{staticPath: "dist", indexPath: "index.html"}
    router.PathPrefix("/").Handler(spa)

    srv := &http.Server{
        Handler: router,
        Addr:    "127.0.0.1:8000",
        // 最佳实践:为服务器读写设置超时时间
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

    log.Fatal(srv.ListenAndServe())
}

具体的业务逻辑都已经写在注释里了。接下来,我们通过 Go Module 管理 Go 依赖:

代码语言:javascript
复制
代码语言:javascript
复制
go mod init gospa
go mod tidy

然后启动这个基于 Go 实现的 HTTP 服务器:

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

修改 gospa/src/App.Vue 中传入 HelloWorld 组件的 msg 属性如下:

代码语言:javascript
复制
代码语言:javascript
复制
<HelloWorld msg="Welcome to Your Vue.js + Golang SPA App"/>

gospa 根目录下运行 yarn build,将前端资源编译到 dist 目录下,至此我们的项目目录结构如下所示:

第一个红框区域对应的目录就是编译后的前端静态资源和 HTML 视图模板所在目录,也是我们在 Go 代码中指定的静态资源目录。

然后在浏览器中访问 http://127.0.0.1:8000,即可看到如下效果:

可以看到之前对 msg 变量值的修改已经生效,并且基于 Go 实现的 HTTP 服务器可以成功服务 SPA 应用。

下一篇
举报
领券