带有必须阅读的捆绑文件的便携式 Go 模块

Portable Go module with bundled files that must be read

我正在尝试创建一个可移植的 Go 模块,它将在许多不同的项目中重复使用。为了运行,该模块需要能够读取作为模块一部分捆绑的非 Go 文件。在这种情况下,它们是一些证书包。选择要加载的文件是动态的,并且基于输入参数。

加载这些文件时指定路径的最佳方法是什么?我似乎找不到任何 Go 函数来获取相对于模块的路径(相对于 using 这个模块的可执行文件)。例如,如果我的模块结构如下所示:

mymodule/
  go.mod
  go.sum
  loadcerts.go
  certs/
    cert_A.pem
    cert_B.pem

我需要做这样的事情:

// loadcerts.go

package mymodule

func LoadCerts(useB bool) error {
    newCertPool := x509.NewCertPool()

    // This is just to show that the selection is dynamic, and since
    // there are many different potential files to load, we can't 
    // embed them all
    bundleName := "cert_A.pem"
    if useB {
        bundleName = "cert_B.pem"
    }
    pem, err := ioutil.ReadFile(fmt.Sprintf("./certs/%s", bundleName))
    if err != nil {
        return err
    }
    if ok := newCertPool.AppendCertsFromPEM(pem); !ok {
        return err
    }
    ...
}

用相对路径 (./certs/cert1.pem) 引用这个文件是行不通的,因为 Go 使用可执行文件的工作目录作为相对路径,而这个导入的模块在某个地方完全不同。

如何加载与便携式模块捆绑在一起的这个 .pem 文件,而不考虑将此模块导入到何处?

Embed作为文件系统的可执行文件中的文件:

//go:embed certs
var f embed.FS

从文件系统读取文件:

pem, err := f.ReadFile(fmt.Sprintf("certs/%s", bundleName))