Go program with the following structure:-
├── app.go
├── bin
│ └── run.go
├── config
│ └── Config.go
└── package1
├── package1_file.go
└── tmpl
└── template.tmpl
Now, in package1_file.go
, I've accessed template.tmpl via relative path like:
t, err := template.ParseFiles("./tmpl/template.tmpl")
When I run tests, tests are able to run successfully because my guess is, Go changes the current working directory when running tests for packages. go tests -v ./...
However, when I run (go build -o app && ./app)
the program from the root folder, I get error complaining that file doesn't exist.
Error compiling template: open ./tmpl/template.tmpl: no such file or directory
It starts working when I change the path to package2/tmpl/template.tmpl
.
The code outside package2
has nothing to do with this template file so I don't want to expose it as a parameter to a function while exposing package2
. What are my options?
What is the right way to target support files like these?
You're operating under some mistaken assumptions here - primarily that the project source code or directory structure are in any way relevant at runtime. They aren't.
A Go program compiles to a single binary file that can be executed anywhere, without the source, without Go installed - just the binary. You need to consider that any time you have any kind of files in your project that you will need at runtime:
go embed static files
turns up not only several libraries, but several articles comparing various libraries)There are some choices you'll have to make as to how you want to handle this but the key takeaway is don't assume the path in your source code will be at all relevant at runtime. Parameterize at least the root path to the resources so that your code will work wherever they may be, and then your tests can pass in an appropriate path to use for testing.
You can use os.Getwd()
to get the path to the root working dir. Then, concat the rest of the path to your template dir. In your case:
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
t, err := template.ParseFiles(wd + "/package1/tmpl/template.tmpl")