I'm trying to create a portable Go module that will be re-used in many different projects. This module, in order to function, needs to be able to read non-Go files that are bundled as part of the module. In this case, they're some certificate bundles. The selection of which file to load is dynamic and based on input arguments.
What is the best way to specify the path to these files when loading them? I can't seem to find any Go functions to get a path relative to the module (vs. relative to the executable that is using this module). For example, if my module structure looks like this:
mymodule/
go.mod
go.sum
loadcerts.go
certs/
cert_A.pem
cert_B.pem
And I need to do something like this:
// 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
}
...
}
Referencing this file with a relative path (./certs/cert1.pem
) doesn't work, since Go uses the executable's working directory for relative paths, and this imported module is somewhere entirely different.
How can I load this .pem
file that is bundled with the portable module, regardless of where this module is being imported to?
Embed the files in the executable as a file system:
//go:embed certs
var f embed.FS
Read the files from the file system:
pem, err := f.ReadFile(fmt.Sprintf("certs/%s", bundleName))