go语言内置预编译 //go:embed xxx 使用详解

在go语言里面,我们可以使用一个"类注释"的语法来来让编译器帮助我们在编译的时候将一些文件或者目录读取到指定的变量中来供我们使用。

go:embed语法:

//go:embed****文件或者目录路径

var****变量名 变量类型

说明:

文件或者目录路径可以是相对路径,也可以是绝对路径,路径中可以使用通配符*来指定要加载的文件类型,这个的用法和 filepath.Glob(pattern string)函数的用法是一样的.

变量类型这里只支持2种变量类型 string 或者 embed.FS , 这个embed.FS是一个结构体,专门用来接收文件集合的,注意是只读文件集合

使用示例

在下面的示例中我们定义了2个全局变量: MyAbc用来接收abc.txt中的内容; MyStaticFs用来接收statics文件夹下的html文件信息。 在 fs_test.go文件中,我们演示了如何使用我们定义的预编译变量,和如何将 embed.FS类型转换为 http.FileSystem 以及创建一个简单的静态服务示例。

假设我们的文件目录结构如下

bash 复制代码
├── abc.txt
├── fs.go
├── main.go
└── statics
    └── index.html

abc.txt 的文件内容

html 复制代码
abc123

fs.go 这个是我们的**//go:embed的预编译定义**

Go 复制代码
package main

import (
	"embed"
)

//go:embed abc.txt
var MyAbc string

//go:embed statics/*.html
var MyStaticFs embed.FS

fs_test.go使用示例

Go 复制代码
package main

import (
	"fmt"
	"net/http"
	"testing"
)

func TestDemo(t *testing.T) {
	abc := MyAbc
	// 使用预编译的变量
	fmt.Println("预编译变量MyAbc的内容为:", abc) // abc123

	// 这里我们就可以直接使用我们定义的预编译变量了, 他的类型是 embed.FS
	statics := MyStaticFs

	// 创建一个静态文件服务的handler  注意这里使用的是FileServerFS
	// handler := http.FileServerFS(statics)

	// 如果要是哟共 FileServer 则需要将类型embed.FS转换为http.FileSystem
	staticsFs := http.FS(statics)
	handler := http.FileServer(staticsFs)

	http.ListenAndServe(":8000", handler)
}

运行内存图解和总结

通过上面的图示,我们可以看到,编译器将文件abc.txt的内容读取并赋值给了我们定义的变量MyAbc, 将文件夹 statics 中的html文件和文件夹自己放入到了我们定义的 embed.FS 类型变量 MyStaticFs里面, 在这个变量里面包含了我们定义的文件的名称完整内容和文件hash等信息,可见go是吧我们指定的文件夹下面的所有文件内容都读取到了FS变量里面了,所以这个地方建议只放小文件,大文件千万别用这种模式来操作!!!

embed.FS只读文件集合结构体定义参考:

这个里面详情阐述了FS结构体的用法和 文件模式的用法。

Go 复制代码
// An FS is a read-only collection of files, usually initialized with a //go:embed directive.
// When declared without a //go:embed directive, an FS is an empty file system.
//
// An FS is a read-only value, so it is safe to use from multiple goroutines
// simultaneously and also safe to assign values of type FS to each other.
//
// FS implements fs.FS, so it can be used with any package that understands
// file system interfaces, including net/http, text/template, and html/template.
//
// See the package documentation for more details about initializing an FS.
type FS struct {
	// The compiler knows the layout of this struct.
	// See cmd/compile/internal/staticdata's WriteEmbed.
	//
	// The files list is sorted by name but not by simple string comparison.
	// Instead, each file's name takes the form "dir/elem" or "dir/elem/".
	// The optional trailing slash indicates that the file is itself a directory.
	// The files list is sorted first by dir (if dir is missing, it is taken to be ".")
	// and then by base, so this list of files:
	//
	//	p
	//	q/
	//	q/r
	//	q/s/
	//	q/s/t
	//	q/s/u
	//	q/v
	//	w
	//
	// is actually sorted as:
	//
	//	p       # dir=.    elem=p
	//	q/      # dir=.    elem=q
	//	w/      # dir=.    elem=w
	//	q/r     # dir=q    elem=r
	//	q/s/    # dir=q    elem=s
	//	q/v     # dir=q    elem=v
	//	q/s/t   # dir=q/s  elem=t
	//	q/s/u   # dir=q/s  elem=u
	//
	// This order brings directory contents together in contiguous sections
	// of the list, allowing a directory read to use binary search to find
	// the relevant sequence of entries.
	files *[]file
}
相关推荐
Swift社区18 分钟前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht20 分钟前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht23 分钟前
Swift闭包的本质
开发语言·ios·swift
wjs202425 分钟前
Swift 数组
开发语言
stm 学习ing1 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
Estar.Lee1 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
湫ccc2 小时前
《Python基础》之字符串格式化输出
开发语言·python
mqiqe3 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin3 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python