이 글은 Golang1.16에서 embed를 사용하여 정적 파일을 로드하는 방법을 소개하기 위해 go 언어튜토리얼 칼럼에서 작성한 글입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!
임베딩을 해야 하는 이유
과거에는 다른 언어에서 Go 언어로 전환한 많은 친구들이 묻거나 함정을 밟을 것입니다. 그들은 Go에서 패키지한 바이너리 파일이 언어에는 구성 파일 공동 컴파일 및 패키징이 포함됩니다. //go:embed
指令,可以在编译阶段将静态资源文件打包进编译好的程序中,并提供访问这些文件的能力。
为什么需要embed
在以前,很多从其他语言转过来Go语言的小伙伴会问到,或者踩到一个坑:就是以为Go语言所打包的二进制文件中会包含配置文件的联同编译和打包。
结果往往一把二进制文件挪来挪去,就无法把应用程序运行起来了,因为无法读取到静态文件的资源。
无法将静态资源编译打包二进制文件的话,通常会有两种解决方法:
- 第一种是识别这类静态资源,是否需要跟着程序走。
- 第二种就是将其打包进二进制文件中。
第二种情况的话,Go以前是不支持的,大家就会借助各种花式的开源库,例如:go-bindata/go-bindata
来实现。
但是在Go1.16起,Go语言自身正式支持了该项特性。
它有以下优点
-
能够将静态资源打包到二进制包中,部署过程更简单。传统部署要么需要将静态资源与已编译程序打包在一起上传,或者使用
docker
和dockerfile
自动化前者,这是很麻烦的。 - 确保程序的完整性。在运行过程中损坏或丢失静态资源通常会影响程序的正常运行。
- 静态资源访问没有io操作,速度会非常快。
embed基础用法
通过 官方文档 我们知道embed嵌入的三种方式:string、bytes 和 FS(File Systems)。其中string
和[]byte
类型都只能匹配一个文件,如果要匹配多个文件或者一个目录,就要使用embed.FS
类型。
特别注意:embed这个包一定要导入,如果导入不使用的话,使用 _ 导入即可
一、嵌入为字符串
比如当前文件下有个hello.txt的文件,文件内容为hello,world!
。通过go:embed
指令,在编译后下面程序中的s变量的值就变为了hello,world!
。
package mainimport ( _ "embed" "fmt")//go:embed hello.txtvar s stringfunc main() { fmt.Println(s)}
二、嵌入为byte slice
你还可以把单个文件的内容嵌入为slice of byte,也就是一个字节数组。
package mainimport ( _ "embed" "fmt")//go:embed hello.txtvar b []bytefunc main() { fmt.Println(b)}
三、嵌入为fs.FS
甚至你可以嵌入为一个文件系统,这在嵌入多个文件的时候非常有用。
比如嵌入一个文件:
package mainimport ( "embed" "fmt")//go:embed hello.txtvar f embed.FSfunc main() { data, _ := f.ReadFile("hello.txt") fmt.Println(string(data))}
嵌入本地的另外一个文件hello2.txt, 支持同一个变量上多个go:embed
指令(嵌入为string或者byte slice是不能有多个go:embed
指令的):
package mainimport ( "embed" "fmt")//go:embed hello.txt//go:embed hello2.txtvar f embed.FSfunc main() { data, _ := f.ReadFile("hello.txt") fmt.Println(string(data)) data, _ = f.ReadFile("hello2.txt") fmt.Println(string(data))}
当前重复的go:embed
指令嵌入为embed.FS是支持的,相当于一个:
package mainimport ( "embed" "fmt")//go:embed hello.txt//go:embed hello.txtvar f embed.FSfunc main() { data, _ := f.ReadFile("hello.txt") fmt.Println(string(data))}
还可以嵌入子文件夹下的文件:
package mainimport ( "embed" "fmt")//go:embed p/hello.txt//go:embed p/hello2.txtvar f embed.FSfunc main() { data, _ := f.ReadFile("p/hello.txt") fmt.Println(string(data)) data, _ = f.ReadFile("p/hello2.txt") fmt.Println(string(data))}
embed进阶用法
Go1.16 为了对 embed
的支持也添加了一个新包 io/fs
。两者结合起来可以像之前操作普通文件一样。
一、只读
嵌入的内容是只读的。也就是在编译期嵌入文件的内容是什么,那么在运行时的内容也就是什么。
FS文件系统值提供了打开和读取的方法,并没有write的方法,也就是说FS实例是线程安全的,多个goroutine可以并发使用。
embed.FS结构主要有3个对外方法,如下:
// Open 打开要读取的文件,并返回文件的fs.File结构.func (f FS) Open(name string) (fs.File, error)// ReadDir 读取并返回整个命名目录func (f FS) ReadDir(name string) ([]fs.DirEntry, error)// ReadFile 读取并返回name文件的内容.func (f FS) ReadFile(name string) ([]byte, error)
二、嵌入多个文件
package mainimport ( "embed" "fmt")//go:embed hello.txt hello2.txtvar f embed.FSfunc main() { data, _ := f.ReadFile("hello.txt") fmt.Println(string(data)) data, _ = f.ReadFile("hello2.txt") fmt.Println(string(data))}
当然你也可以像前面的例子一样写成多行go:embed
:
package mainimport ( "embed" "fmt")//go:embed hello.txt//go:embed hello2.txtvar f embed.FSfunc main() { data, _ := f.ReadFile("hello.txt") fmt.Println(string(data)) data, _ = f.ReadFile("hello2.txt") fmt.Println(string(data))}
三、支持文件夹
文件夹分隔符采用正斜杠/
- 첫 번째는 이러한 유형의 정적 리소스를 식별하고 프로그램을 따라야 하는지 여부를 확인하는 것입니다.
- 두 번째는 바이너리 파일로 패키징하는 것입니다.
go-bindata/go-bindata
와 같은 다양하고 멋진 오픈 소스 라이브러리를 사용하여 달성할 것입니다. . 🎜🎜하지만 Go 1.16부터 Go 언어 자체에서 이 기능을 공식적으로 지원합니다. 🎜🎜다음과 같은 장점이 있습니다🎜- 🎜정적 리소스를 바이너리 패키지로 패키징할 수 있어 배포 프로세스가 더 간단해집니다🎜. 기존 배포에서는 컴파일된 프로그램과 함께 정적 리소스를 패키징하고 업로드하거나
docker
및dockerfile
을 사용하여 전자를 자동화해야 하는데 이는 번거롭습니다. - 🎜프로그램 무결성을 보장하세요🎜. 작동 중 정적 리소스의 손상이나 손실은 일반적으로 프로그램의 정상적인 작동에 영향을 미칩니다.
- 🎜정적 리소스 액세스에는 io 작업이 필요하지 않으며 매우 빠릅니다🎜.
🎜🎜embed의 기본 사용법
🎜공식 문서를 통해 우리는 문자열, 바이트 및 FS(파일 시스템)의 세 가지 삽입 방법을 알고 있습니다. 그 중string
및 []byte
유형은 하나의 파일만 일치할 수 있습니다. 여러 파일이나 디렉터리를 일치시키려면 embed.FS를 사용해야 합니다.
입력하세요. 🎜🎜특별 참고 사항: 임베드 패키지를 가져와야 합니다. 가져오기를 사용하지 않으면 _를 사용하여 가져옵니다.🎜
🎜🎜1. > 🎜예를 들어 현재 파일 아래에 hello.txt 파일이 있고 파일 내용은 hello, world!
입니다. go:embed
지시문을 통해 다음 프로그램의 s 변수 값은 컴파일 후 hello, world!
가 됩니다. 🎜package mainimport (
"embed"
"fmt")//go:embed pvar f embed.FSfunc main() {
data, _ := f.ReadFile("p/hello.txt")
fmt.Println(string(data))
data, _ = f.ReadFile("p/hello2.txt")
fmt.Println(string(data))}
🎜🎜2. 바이트 슬라이스로 삽입
🎜 단일 파일의 콘텐츠를 바이트 배열인 바이트 슬라이스로 삽입할 수도 있습니다. 🎜//go:embed ".env" "v1d0/.env"var FS embed.FSfunc main(){
setting.InitSetting(FS)
manager.InitManager()
cron.InitCron()
routersInit := routers.InitRouter()
readTimeout := setting.ServerSetting.ReadTimeout
writeTimeout := setting.ServerSetting.WriteTimeout
endPoint := fmt.Sprintf(":%d", setting.ServerSetting.HttpPort)
maxHeaderBytes := 1 <h4 id="fs-FS로-포함">🎜🎜3. fs.FS로 포함</h4><hr>🎜파일 시스템으로 포함할 수도 있는데, 이는 여러 파일을 포함할 때 매우 유용합니다. 🎜🎜예를 들어 파일 삽입: 🎜<pre class="brush:php;toolbar:false">func InitSetting(FS embed.FS) {
// 总配置处理
var err error
data, err := FS.ReadFile(".env")
if err != nil {
log.Fatalf("Fail to parse '.env': %v", err)
}
cfg, err = ini.Load(data)
if err != nil {
log.Fatal(err)
}
mapTo("server", ServerSetting)
ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second
ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second // 分版本配置引入
v1d0Setting.InitSetting(FS)}
🎜다른 로컬 파일 hello2.txt 삽입, 동일한 변수에 대한 여러 go:embed
명령 지원(문자열 또는 바이트 슬라이스로 삽입되면 여러 를 가질 수 없음) go:embed
명령어):🎜rrreee🎜현재 반복되는 go:embed
명령어는 embed.FS로 지원되며, 이는 a:🎜rrreee🎜다음에 포함된 파일일 수도 있습니다. 하위 폴더: 🎜rrreee🎜🎜embed 고급 사용
🎜Go1.16은 또한 embed
를 지원하는 새로운 패키지 io/fs를 추가합니다. 두 가지를 결합하면 이전에는 일반 파일처럼 작동할 수 있습니다. 🎜<h4 id="읽기-전용">🎜🎜1. 읽기 전용</h4>🎜삽입된 콘텐츠는 읽기 전용입니다. 즉, 컴파일 타임에 포함된 파일의 내용은 무엇이며 런타임의 내용은 무엇입니까? 🎜🎜FS 파일 시스템 값은 열기 및 읽기 방법을 제공하며 쓰기 방법이 없습니다. 이는 FS 인스턴스가 스레드로부터 안전하고 여러 고루틴을 동시에 사용할 수 있음을 의미합니다. 🎜🎜embed.FS 구조에는 주로 다음과 같은 3가지 외부 메소드가 있습니다. 🎜rrreee<h4 id="여러-파일-삽입">🎜🎜2. 여러 파일 삽입</h4>
<hr>rrreee🎜물론 이전 예제처럼 여러 줄을 작성할 수도 있습니다. <code>go:embed
:🎜rrreee🎜🎜3. 지원 폴더
🎜폴더 구분 기호는 Windows 시스템에서도 슬래시 /
를 사용합니다. 도 이 모델을 사용합니다. 🎜package mainimport (
"embed"
"fmt")//go:embed pvar f embed.FSfunc main() {
data, _ := f.ReadFile("p/hello.txt")
fmt.Println(string(data))
data, _ = f.ReadFile("p/hello2.txt")
fmt.Println(string(data))}
应用
在我们的项目中,是将应用的常用的一些配置写在了.env的一个文件上,所以我们在这里就可以使用go:embed
指令。
main.go
文件:
//go:embed ".env" "v1d0/.env"var FS embed.FSfunc main(){ setting.InitSetting(FS) manager.InitManager() cron.InitCron() routersInit := routers.InitRouter() readTimeout := setting.ServerSetting.ReadTimeout writeTimeout := setting.ServerSetting.WriteTimeout endPoint := fmt.Sprintf(":%d", setting.ServerSetting.HttpPort) maxHeaderBytes := 1 <p><code>setting.go</code>文件:</p><pre class="brush:php;toolbar:false">func InitSetting(FS embed.FS) { // 总配置处理 var err error data, err := FS.ReadFile(".env") if err != nil { log.Fatalf("Fail to parse '.env': %v", err) } cfg, err = ini.Load(data) if err != nil { log.Fatal(err) } mapTo("server", ServerSetting) ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second // 分版本配置引入 v1d0Setting.InitSetting(FS)}
위 내용은 삽입이란 무엇입니까? Go는 정적 파일을 로드하기 위해 이를 어떻게 사용하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

golangisidealferperperferferferferformance-criticalapplications 및 concurrentprogramming, whilepythonexcelsindatascience, 빠른 프로토 타입, 및 범위

Golang은 Goroutine 및 Channel을 통해 효율적인 동시성을 달성합니다. 1. Goroutine은 가벼운 스레드이며 GO 키워드로 시작합니다. 2. 채널은 경주 조건을 피하기 위해 고루틴 간의 안전한 통신에 사용됩니다. 3. 사용 예제는 기본 및 고급 사용법을 보여줍니다. 4. 일반적인 오류에는 교착 상태와 데이터 경쟁이 포함되며 Gorun-Race가 감지 할 수 있습니다. 5. 성능 최적화는 채널 사용을 줄이고, 고 루틴 수를 합리적으로 설정하고, sync.pool을 사용하여 메모리를 관리하는 것을 제안합니다.

Golang은 시스템 프로그래밍 및 높은 동시성 응용 프로그램에 더 적합한 반면 Python은 데이터 과학 및 빠른 개발에 더 적합합니다. 1) Golang은 Google에 의해 개발되어 정적으로 입력하여 단순성과 효율성을 강조하며 동시성 시나리오에 적합합니다. 2) Python은 Guidovan Rossum, 동적으로 입력, 간결한 구문, 광범위한 응용 프로그램, 초보자 및 데이터 처리에 적합합니다.

Golang은 성능과 확장 성 측면에서 Python보다 낫습니다. 1) Golang의 컴파일 유형 특성과 효율적인 동시성 모델은 높은 동시성 시나리오에서 잘 수행합니다. 2) 해석 된 언어로서 파이썬은 천천히 실행되지만 Cython과 같은 도구를 통해 성능을 최적화 할 수 있습니다.

Go Language는 동시 프로그래밍, 성능, 학습 곡선 등의 고유 한 장점을 가지고 있습니다. 1. 동시 프로그래밍은 가볍고 효율적인 Goroutine 및 채널을 통해 실현됩니다. 2. 컴파일 속도는 빠르며 작동 속도는 작동 성능이 C 언어의 성능에 가깝습니다. 3. 문법은 간결하고 학습 곡선은 매끄럽고 생태계는 풍부합니다.

Golang과 Python의 주요 차이점은 동시성 모델, 유형 시스템, 성능 및 실행 속도입니다. 1. Golang은 동시 작업에 적합한 CSP 모델을 사용합니다. Python은 I/O 집약적 인 작업에 적합한 멀티 스레딩 및 Gil에 의존합니다. 2. Golang은 정적 유형이며 Python은 동적 유형입니다. 3. Golang 컴파일 된 언어 실행 속도는 빠르며 파이썬 해석 언어 개발은 빠릅니다.

Golang은 일반적으로 C보다 느리지 만 Golang은 동시 프로그래밍 및 개발 효율에 더 많은 장점이 있습니다. 1) Golang의 쓰레기 수집 및 동시성 모델은 높은 동시 시나리오에서 잘 수행합니다. 2) C는 수동 메모리 관리 및 하드웨어 최적화를 통해 더 높은 성능을 얻지 만 개발 복잡성이 높습니다.

Golang은 클라우드 컴퓨팅 및 DevOps에서 널리 사용되며 장점은 단순성, 효율성 및 동시 프로그래밍 기능에 있습니다. 1) 클라우드 컴퓨팅에서 Golang은 Goroutine 및 채널 메커니즘을 통해 동시 요청을 효율적으로 처리합니다. 2) DevOps에서 Golang의 빠른 편집 및 크로스 플랫폼 기능이 자동화 도구의 첫 번째 선택입니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

Dreamweaver Mac版
시각적 웹 개발 도구

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.
