go-embedx

go embed 的功能扩展
授权协议 Apache
开发语言 Google Go
所属分类 程序开发、 其他开发相关
软件类型 开源软件
地区 不详
投 递 者 单于善
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

go1.16 //go:embed 的功能扩展。

简介:

go1.16 官方推出了go:embed 这个非常有意思的功能,可以嵌入静态文件到一个可执行文件中,发布软件时,只需要发布软件的可执行程序就可以了,不需要另外发布那些静态文件。之前这部分功能需要三方脚手架处理,比如go-bindata,go1.16开始,直接在go的工具链中提供了go:embed支持完成相同的工作,使用体验非常的nice。

具体使用示例可以参考tl-explorer:

%> git clone --recursive https://github.com/alimy/tl-explorer
%> cd tl-explorer && pwd
go/src/github.com/alimy/tl-explorer

%> tree -L 2
.
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── assets
│   ├── assets.go
│   └── schema.tl
├── go.mod
├── go.sum
├── main.go
└── scripts
    ├── launchd
    └── systemd

该项目需要的静态文件存放在assets/schema.tl 目录中,需要把这个目录的所有文件都嵌入到最终的可执行程序中,可以这样做(assets/assets.go):

// Copyright 2020 Michael Li <alimy@gility.net>. All rights reserved.
// Use of this source code is governed by Apache License 2.0 that
// can be found in the LICENSE file.

package assets

import (
	"embed"
	"net/http"

	"github.com/alimy/embedx"
)

// NewFileSystem get an assets http.FileSystem instance
func NewFileSystem() http.FileSystem {
	//go:embed schema.tl
	var content embed.FS

	embedFS := embedx.ChangeRoot(content, "schema.tl")
	return http.FS(embedFS)
}

声明需要嵌入的那些文件,然后在程序中就可以通过embed.FS访问这些文件,如例子中:

	//go:embed schema.tl
	var content embed.FS

通过embed.FS访问schema.tl中的文件。

我们这里通过http server访问schema.tl目录中的静态文件(main.go):

// Copyright 2020 Michael Li <alimy@gility.net>. All rights reserved.
// Use of this source code is governed by Apache License 2.0 that
// can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/alimy/tl-explorer/assets"
)

var (
	host        string
	port        uint
	showVersion bool

	version = "v0.2.0"
)

func init() {
	flag.StringVar(&host, "host", "", "listening host")
	flag.UintVar(&port, "port", 8080, "listening port")
	flag.BoolVar(&showVersion, "v", false, "show version")
}

func main() {
	flag.Parse()

	if showVersion {
		fmt.Println(version)
		return
	}
	addr := fmt.Sprintf("%s:%d", host, port)
	if host == "" {
		host = "localhost"
	}
	fmt.Printf("listening in [%s]. Please open http://%s:%d in browser to enjoy yourself.\n", addr, host, port)

	http.Handle("/", http.FileServer(assets.NewFileSystem()))
	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatal(err)
	}
}

官方的go:embed使用体验非常好,那有没有其他限制呢?有的,比如上面例子,我们嵌入了schema.tl目录,那么通过embed.FS 访问schema.tl目录下的文件比如index.html时,需要这样访问:

//go:embed schema.tl
var content embed.FS

indexContent, _ := content.ReadFile("schema.tl/index.html")

我其实是想把schema.tl目录作为根目录,访问目录下的文件时,就如当前就在根目录下访问文件,不需要加schema.tl目录名前缀:

//go:embed schema.tl
var content embed.FS

// 预想schema.tl为根目录, 访问shema.tl/index.html, 只给定文件名index.html即可
// indexContent, _ := content.ReadFile("index.html")

go-embedx提供这样的辅助功能特性,这里可以使用辅助库的 ‘改变root目录’ 功能,使用如下:

//go:embed schema.tl
var content embed.FS

// 改变根目录为shema.tl目录
embedFS := embedx.ChangeRoot(content, "schema.tl")

// 访问schema.tl目录下的index.html,可以这样做
indexContent, _ := embedFS.ReadFile("index.html")
fmt.Println(indexContent)

go-embedx还提供其他辅助功能,比如为embed.FS 附加一个虚拟根目录等。

使用实例:

%> cd demo # change to your golang project root directory; cd <your-project-dir>
%> go get github.com/alimy/embedx
%> tree
 |- public
    |- ...
    |- index.html
    |- ...
 |- conf
    |- app.ini
    |- ...
    |- conf.go
 |- ...
 |- main.go
 |- go.mod
 |- ...


%> cat conf/conf.go
// file: conf/conf.go

package conf

import (
	"embed"
	
	"github.com/alimy/embedx"
)

func NewConfigFS() embedx.EmbedFS {
	//go:embed app.ini
	var content embed.FS

	// attach a root to conf dir then access files in this returned FS will
	// need add  'conf' prefix. eg: access app.ini need FS.ReadFile("conf/app.ini").
	return embedx.AttachRoot(content, "conf")
}


%> cat main.go
// file: main.go

package main

import (
	"embed"
	
	"github.com/alimy/embedx"
)

func newPublicFS() embedx.EmbedFS {
	//go:embed public
	var content embed.FS
	
	// change the root to public dir then access files in this returned FS will
	// not need  'public' prefix. eg: access public/index.html just need FS.ReadFile("index.html").
	return embedx.ChangeRoot(content, "public")
}
```

 

  •        报错: embed: package embed is not in GOROOT (/usr/local/go/src/embed) 解决:embed 为 golang1.6 的新的内置函数,用于静态资源内嵌。 升级 go 版本 

  • 路由设置 什么是路由设置呢?前面介绍的 MVC 结构执行时,介绍过 beego 存在三种方式的路由:固定路由、正则路由、自动路由,接下来详细的讲解如何使用这三种路由。 基础路由 从 beego 1.2 版本开始支持了基本的 RESTful 函数式路由,应用中的大多数路由都会定义在 routers/router.go 文件中。最简单的 beego 路由由 URI 和闭包函数组成。 基本 GET 路由

  • Go的bytes.Buffer 一、bytes.Buffer 的基础知识 与strings.Builder一样,bytes.Buffer也是开箱即用的。 bytes.Buffer类型的用途主要是作为字节序列的缓冲区。 在内部,bytes.Buffer类型使用字节切片作为内容容器,并有一个int类型的字段作为已读计数,这个已读计数无法通过bytes.Buffer提供的方法计算出来。 var buf

  • 今天在安装beego的时候,为了方便的生成框架,输入go get -u -v github.com/beego/bee,如下图,报错信息如下: go get: module github.com/beego/bee: Get "https://proxy.golang.org/github.com/beego/bee/@v/list": dial tcp 142.251.42.241:443: c

  • 生命不止,继续 go go go !!! 介绍了encoding/json包的使用,就没有理由不介绍encoding/xml包。 xml vs json xml和json都是文本表示的数据格式: 跨平台 跨系统交换数据 但是,XML更适合标记文档,JSON更适合数据交互。 两者最大的不同在于,XML是一个完整的标记语言,而JSON不是。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在

  • 生命不止,继续 go go go !!! 为了让某个数据结构能够在网络上传输或能够保存至文件,它必须被编码然后再解码。当然,已经有许多可用的编码方式了:JSON,XML,Google 的 protocol buffers,等等。而现在,又多了一种,由 Go 的 gob 包提供的方式。 gob是Golang包自带的一个数据结构序列化的编码/解码工具。 编码使用Encoder,解码使用Decoder。

  • 1 介绍 Beego是一个开源的基于Golang的MVC框架,主要用于Golang Web开发。Beego可以用来快速开发API、Web、后端服务等各种应用。 个人开发 api类:gin 团队大项目:Beego Github:https://github.com/astaxie/beego 官网:https://beego.vip/ 2 安装 运行 下载安装 https://github.com/

  • //Golang中encoding的用法 package main import ( "bytes" "encoding/binary" "encoding/hex" "encoding/xml" "fmt" "os" ) func goxml() { type Address struct {

  • 视频来源:B站《golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]》 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! 附上汇总贴:Go语言自学系列 | 汇总_COCOgsta的博客-CSDN博客_go语言自学 xml包实现xml解析 核心的两个函数 func Marshal(v interface{}) ([]byte, er

  •        golang嵌入静态文件的方式很多,但是1.16版开始官方也出台了方案。自带了go:embed标签来完成,但是在使用时会有很多的不方便,我们来看一下。         1、文件不是utf8编码时,输出内容为中文会乱码。         2、嵌入文件只能为源码文件同级目录和子目录下的文件。         尤其是第2项是很不方便的,一般的静态文件会单独放在根及目录下,而嵌入的文件则可能

 相关资料
  • 实现点击工具栏中“+”号扩展区域内添加自定义事件,比如添加“最近订单”、“最近商品”: 注:图片需要添加到SDK中对应bundle资源文件中 /** @return 扩展内容 例如: @[@{@"picName": @"图片-(1)",@"highLightPicName": @"图片hover",@"name": @"图片1"}, @{@"picName": @"图片-(1)",@"highLi

  • SDK对外开放了一个可自定义的协议NtalkerChatDelegate,如果客户想进行自定义实现接口,必须遵守此协议,初始化小能类的时候设置其delagate为实现代理接口方法的类,然后实现相应的接口。其中提供了以下几个接口: 深度自定义控件接口,详细调用细节,请参照demo。 一、自定义消息发送 二、查询历史咨询列表 三、设置超媒体自定义参数 四、+号功能区的扩展功能 五、商品条自定义 六、设

  • 一、发送文本消息到聊窗内 二、返回按钮的点击监听 三、结束会话按钮的点击监听 四、超媒体点击事件的监听 五、+号功能区的扩展功能 六、商品条自定义 七、导航栏自定义

  • QueyList是完全模块化的设计,拥有强大的可扩展性。 使用bind()方法绑定一个功能函数到QueryList对象,实现轻量级的功能扩展。bind()方法的第一个参数是绑定的函数名,第二个参数是一个匿名的功能函数,这个功能函数的$this对象指向的是当前的QueryList实例对象,所以在这个功能函数中可以直接通过$this来调用QueryList的方法。 例子 注册一个自定义的http网络操

  • 自定义引擎各个阶段 可以在测试脚本中或者基类中重写 ActsTestBase 提供的 API。 重写 prepare,execute,check,clear 等。可以通过在 super.prepare() 之前或者之后进行某些操作。 重写 process 方法,在 super.process() 之前或之后进行操作。可将整个脚本重新编排,例如在现有的清理 -> 准备 -> 执行 -> 校验流程中增

  • Weex 提供了扩展机制,可以根据自己的业务进行定制自己的功能。 主要分为两类扩展: Module 扩展 非 UI 的特定功能。例如 sendHttp、openURL 等。 Component 扩展 实现特别功能的 Native 控件。例如:RichTextview,RefreshListview 等。 Adapter 扩展 Weex 对一些基础功能实现了统一的接口,可实现这些接口来定制自己的业务

  • 注意:Weex 所有暴露给 JS 的内置 module 或 component API 都是安全和可控的,它们不会去访问系统的私有 API,也不会去做任何 runtime 上的 hack 更不会去改变应用原有的功能定位。 如果需要扩展自定义的 module 或者 component ,一定注意不要将 OC 的 runtime 暴露给 JS ,不要将一些诸如 dlopen(), dlsym(), r

  • 4.+号功能区的扩展功能 +号功能区的扩展是指在点击+号之后显示的功能区加入自定义功能。 /** * @param functionName 添加功能的名字 * @param functionIcon 添加功能的图标 */ Ntalker.getInstance().addPlusFunction(String functionName, int functionIcon); 例如要添加最近订单