Go*.goGo1.16
Go1.16embed
然而在项目中,以上两种方案我都没用,转而自研了一套方案。
不想听我bb心路历程的,直接跳到 开整 环节看最终实现。
背景
在2021年初,我在参与的项目 go-mod-graph-chart 时,需要把前端资源集成到一个由Go语言构建的 命令行 程序中。
go mod graphgo mod graph
命令输出结果如下:
$ go mod graph
go-learn github.com/antlabs/pcurl@v0.0.7
go-learn github.com/bxcodec/faker/v3@v3.6.0
go-learn github.com/go-sql-driver/mysql@v1.5.0
go-learn github.com/jinzhu/copier@v0.3.5
go-learn github.com/pingcap/parser@v0.0.0-20220118030345-6a854bcbd929
go-learn github.com/smartystreets/goconvey@v1.7.2
go-learn golang.org/x/text@v0.3.7
go-learn moul.io/http2curl@v1.0.0
github.com/antlabs/pcurl@v0.0.7 github.com/gin-contrib/gzip@v0.0.1
github.com/antlabs/pcurl@v0.0.7 github.com/gin-gonic/gin@v1.6.3
github.com/antlabs/pcurl@v0.0.7 github.com/guonaihong/clop@v0.0.9
github.com/antlabs/pcurl@v0.0.7 github.com/guonaihong/gout@v0.0.12
github.com/antlabs/pcurl@v0.0.7 github.com/stretchr/testify@v1.6.1
github.com/pingcap/parser@v0.0.0-20220118030345-6a854bcbd929 github.com/cznic/golex@v0.0.0-20181122101858-9c343928389c
github.com/pingcap/parser@v0.0.0-20220118030345-6a854bcbd929 github.com/cznic/mathutil@v0.0.0-20181122101859-297441e03548
...
而使用 gmchart 这个工具,将其可视化为多级树状结构。
如下图:
graphviz*.go
Go1.16 embedgo-bindataginginhttp
实现思路
*.jsjsjsindex.htmljs
GoGo代码
GolanghttphederContent-Type
main.jsindex.htmlgoGo
package gostatic
var IndexHtml = `<!DOCTYPE html>^M
<html lang="en">^M
</html>
var MainJs = `echo "hello";`
var Favicon = `data:image/ico;base64,AAABAAEAmpsAAAEAIAT...`
开整
项目前端构建用到了 webpack,那就在这上面动动手脚了。
一个 gopher 想要去动 webpack?有点自不量力
webpack
plugingo_static.gomain.jsindex.html
pack-all-in-go-plugin.js
class PackAllInGoPlugin {
apply(compiler) {
// emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well
compiler.hooks.emit.tapAsync('PackAllInGoPlugin', (compilation, callback) => {
// Create a header string for the generated file:
var filelist = '';
var indexHtml, mainJs;
var goCode = `package godist
func GetFile(file string) string {
switch {
case \`index.html\` == file:
return IndexHtml
case \`main.js\` == file:
return MainJs
case \`favicon.ico\` == file:
return Favicon
default:
return ""
}
}
var IndexHtml = \`--index.html--\`
var MainJs = \`--main.js--\`
var Favicon = \`favicon.ico\``
// Loop through all compiled assets,
// adding a new line item for each filename.
for (var filename in compilation.assets) {
if ("main.js" == filename) {
let jsCode = compilation.assets[filename].source()
let jsCodeString = jsCode.slice();
jsCodeString = jsCodeString.replace(/\`/g, "\` + \"\`\" + \`")
goCode = goCode.replace('--main.js--', jsCodeString)
} else if ("index.html") {
let htmlCode = compilation.assets[filename].source()
goCode = goCode.replace('--index.html--', htmlCode)
}
}
// 将这个列表作为一个新的文件资源,插入到 webpack 构建中:
compilation.assets['../godist/static.go'] = {
source: function() {
return goCode;
},
size: function() {
return goCode.length;
}
};
callback();
});
}
}
module.exports = PackAllInGoPlugin;
webpack
/*
* 引入自定义插件
*/
const PackAllInGoPlugin = require('./plugin/pack-all-in-go-plugin');
...
config = {
pulbins: [
...
new PackAllInGoPlugin({options: true})
],
}
npm run buildgo build -o main main.gogo
对了!这个 webpack plugin 没发布到 npm ,你如果要用直接把源码抄过去就行了。中间遇到集成问题,可以看看 https://github.com/PaulXu-cn/... ,这个项目实际有在用。
最后
goGoWebPack
gophergowebpack plugin
我也预见了,这方法也就少数人用用,想试试直接copy代码就行,这个小玩意,就不单独开"坑"了。
gohper