最近使用了goframe开发了一个小项目, 开发完总觉得不太对劲(说不上, 可能封装太好了)

于是用gin+gorm重构了项目, 造了点轮子, 最后遇到打包问题 – goframe打包还是很不错的

最后选择了packr将项目里的template和static一起打包成二进制文件, 加上压缩, 完美.

安装 packr v2 项目地址

go get -u github.com/gobuffalo/packr/v2/...

Gin自定义模板引擎

r := gin.Default()
t, err := loadTemplate()
if err != nil {
	panic(err)
}
r.SetHTMLTemplate(t)

目的是可以加载打包资源里的模板文件

// 自定义模板加载
func loadTemplate() (*template.Template, error) {
	t := template.New("")
	t.Funcs(template2.GetFuncMap())
	# ./templates 为项目模板目录
	box := packr.New("Templates Box", "./templates")
	fmt.Printf("%v\n", box)
	for _, path := range box.List() {
		fmt.Println(path)
		s, err := box.FindString(path)
		if err != nil {
			log.Fatal(err)
			return nil, err
		}
		t, err = t.New(path).Parse(s)
		if err != nil {
			log.Fatal(err)
			return nil, err
		}
		fmt.Println("Loading template: ", path)
	}
	return t, nil
}

静态文件 js css image等处理

// 静态打包 ./static为存放 js css的目录
box := packr.New("Static Box", "./static")
r.StaticFS("/static", box)

打包命令

packr2 build -trimpath -ldflags "-s -w" main.go
packr2 clean

# 压缩大小可以使用 upx
upx -9 main

main.go文件看起来应该是:

package main

import (
	"fmt"
	"html/template"
	"log"

	"github.com/gobuffalo/packr/v2"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	// 生产模式 export GIN_MODE=release
	t, err := loadTemplate()
	if err != nil {
		panic(err)
	}

	r.SetHTMLTemplate(t)

	// 静态打包
	box := packr.New("Static Box", "./static")
	r.StaticFS("/static", box)

	r.Run()
}

// 自定义模板加载
func loadTemplate() (*template.Template, error) {
	t := template.New("")
	box := packr.New("Templates Box", "./templates")
	// fmt.Printf("%v\n", box)
	for _, path := range box.List() {
		fmt.Println(path)
		s, err := box.FindString(path)
		if err != nil {
			log.Fatal(err)
			return nil, err
		}
		t, err = t.New(path).Parse(s)
		if err != nil {
			log.Fatal(err)
			return nil, err
		}
		fmt.Println("Load template: ", path)
	}
	return t, nil
}

使用ginview等第三方模板引擎的处理

g := ginview.New(goview.Config{
  Root:      "views",
  Extension: ".html",
  Master:    "layouts/master",
  Partials:  []string{"partials/tab"},
  Funcs: template.FuncMap{
  "default": template2.Default,
},
DisableCache: true,
})

r.HTMLRender = g


if gin.Mode() == gin.ReleaseMode {
	// 生产模式 引入资源库
	box := packr.New("Templates Box", "./views")
		// 生产模式 使用打包资源 export GIN_MODE=release
		g.SetFileHandler(func(config goview.Config, tplFile string) (content string, err error) {
			// Get the absolute path of the root template
			path, err := filepath.Abs(config.Root + string(os.PathSeparator) + tplFile + config.Extension)
			if err != nil {
				return "", fmt.Errorf("ViewEngine path:%v error: %v", path, err)
			}
			fmt.Println("Load Template:", tplFile+config.Extension)
			s, err := box.FindString(tplFile + config.Extension)
			if err != nil {
				return "", fmt.Errorf("ViewEngine render read name:%v, path:%v, error: %v", tplFile, path, err)
			}
			return s, nil
		})
}\