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
}
相关推荐
蜗牛hb9 分钟前
VMware Workstation虚拟机网络模式
开发语言·学习·php
汤姆和杰瑞在瑞士吃糯米粑粑24 分钟前
【C++学习篇】AVL树
开发语言·c++·学习
Biomamba生信基地31 分钟前
R语言基础| 功效分析
开发语言·python·r语言·医药
手可摘星河34 分钟前
php中 cli和cgi的区别
开发语言·php
小池先生43 分钟前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
CT随1 小时前
Redis内存碎片详解
java·开发语言
anlog1 小时前
C#在自定义事件里传递数据
开发语言·c#·自定义事件
奶香臭豆腐1 小时前
C++ —— 模板类具体化
开发语言·c++·学习
晚夜微雨问海棠呀1 小时前
长沙景区数据分析项目实现
开发语言·python·信息可视化
graceyun1 小时前
C语言初阶习题【9】数9的个数
c语言·开发语言