Go 1.16的Embed最佳实践,命令行启动一个WEB

共 2698字,需浏览 6分钟

 ·

2021-02-11 08:38

很多文章里介绍了go1.16的embed使用方式,但很少讲怎么把embed运用到项目中,大家在使用这些新功能的感觉就如下图所示:

本文介绍下go1.16的embed新特性,如何运用到实际项目中。

演示命令行启动一个WEB

为了方便大家体验embed新特性,我写了一个demo。该demo,可以通过go install直接安装。安装条件是需要你的Go必须大于等于Go1.16。

go install github.com/gotomicro/embedctl@latest
~ embedctl

访问 http://127.0.0.1:8888 可以看到以下界面可以看到Go可以通过命令行,快速启动一个web,这得益于Go1.16的embed新特性。接下来我们就介绍如何使用embed

Embed简单用法

embed一共有三种数据格式

数据类型说明
[]byte表示数据存储为二进制格式,如果只使用[]byte和string需要以import (_ "embed")的形式引入embed标准库
string表示数据被编码成utf8编码的字符串,因此不要用这个格式嵌入二进制文件比如图片,引入embed的规则同[]byte
embed.FS表示存储多个文件和目录的结构,[]byte和string只能存储单个文件

我们使用一个最简单方式演示下嵌入一个 text 文件

import (
 _ "embed"
)
//go:embed test.txt
var txt string

test.txt文件与embed的go文件同级,我们就可以读取到txt里的字符串内容。

Embed嵌入到Gin框架

要想将Embed投入当实际生产项目,那么我们就需要用到 embed.FS 这个数据类型,它表示存储多个文件和目录的结构。目前gin框架支持的静态文件的代码如下所示

func (group *RouterGroup) StaticFS(relativePath string, fs http.FileSystem) IRoutes

我们主流框架是还未支持embed.FS 数据类型,所以需要做下改造,将embed.FS转换为http.FileSystem

// 嵌入普通的静态资源
type webui struct {
 webuiEmbed embed.FS // 静态资源
 path       string   // 设置embed文件到静态资源的相对路径,也就是embed注释里的路径
}

// 静态资源被访问的核心逻辑
func (w *webui) Open(name string) (http.File, error) {
 if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
  return nil, errors.New("http: invalid character in file path")
 }
 fullName := filepath.Join(w.path, filepath.FromSlash(path.Clean("/"+name)))
 file, err := w.webuiEmbed.Open(fullName)
 wf := &WebuiFile{
  File: file,
 }
 return wf, err
}

type WebuiFile struct {
 io.Seeker
 fs.File
}

func (*WebuiFile) Readdir(count int) ([]fs.FileInfo, error) {
 return nilnil
}

做完转换后,我们就可以使用gin返回embed提供的静态资源。

// 设置简单的演示静态资源
webuiSimpleObj := &webui{
    webuiEmbed: simple.WebUI,
    path:       "webui",
}

// 设置简单的演示静态资源
handler.StaticFS("/webui/", webuiSimpleObj)

访问http://127.0.0.1:8888/webui,可以看到数据

Embed嵌入Ant Desgin

依葫芦画瓢,我们将整个ant design嵌入进来

// 设置ant design的路径,在config.ts里配置
handler.StaticFS("/ant/", webuiAntObj)
// 访问首页跳转到ant design的welcome页面
handler.GET("/"func(ctx *gin.Context) {
    ctx.Redirect(302"/welcome")
    return
})
// Ant Design前端访问,try file到index.html
handler.GET("/welcome"func(context *gin.Context) {
    context.FileFromFS("/welcome", webuiAntIndexObj)
})

在设置前后端分离的项目,我们需要做try file到index.html操作,否则刷新页面,会走到后端,详细操作看https://github.com/gotomicro/embedctl 

1·访问http://127.0.0.1:8888,可以看到ant design页面

Show Me Code

  • 演示代码: https://github.com/gotomicro/embedctl

扩展阅读搭建Go1.16

  • wget https://golang.org/dl/go1.16rc1.darwin-amd64.tar.gz
  • 将二进制下载到/usr/local/目录下
  • 设置go软链接到go1.16,如下所示
image.png

总结Go Embed有什么用处

  • 能够在命令行工具里嵌入WEB
    • go install 快速安装,启动web
    • 该web可以提供生成代码的平台
    • 该web可以提供例如json to struct等数据结构转换
    • 可以大大提高Go的工具链能力
  • 能够将前端资源打包到一个二进制包里,方便部署和安装
  • 静态资源访问没有io操作,速度非常快


浏览 62
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报