4

I'm trying to understand a relative path building in Go. Here is my problem: I have a folders tree:

-root
--main
---utils
---certs
--tests

Having my certificates uploaded into certs folder and connectivity util.go file uploaded into utils, I have relative paths hard coded in the file.

Problem: Having paths specified in utils/util.go, they work fine once called from main/main.go and throw exception (file not found) when called from tests/test.go.

What's the way out?

Zoe
  • 27,060
  • 21
  • 118
  • 148
ArkadyB
  • 1,265
  • 1
  • 19
  • 37
  • 3
    Possible duplicate of [how to reference a relative file from code and tests](http://stackoverflow.com/questions/31059023/how-to-reference-a-relative-file-from-code-and-tests) – icza Apr 25 '16 at 14:29
  • No it does not look to be duplicate. There topicstarter uses some revel framework, when for me it fails for base golang functionality... – ArkadyB Apr 25 '16 at 14:36
  • Please read the [answer I gave there](http://stackoverflow.com/a/31059125/1705598) and don't get blocked by the word "revel". – icza Apr 25 '16 at 14:37
  • Hmm im not sure what exactly do u suggest.. A base path for the cert files is exactly same. The difference in the caller path. Having known my basepath how would i use it in golang to restore fullpath? – ArkadyB Apr 25 '16 at 14:40
  • You may use [`path.Join()`](https://golang.org/pkg/path/#Join) or [`filepath.Join()`](https://golang.org/pkg/path/filepath/#Join) to get the full path. I edited [my answer](http://stackoverflow.com/a/31059125/1705598) to show an example of it. – icza Apr 25 '16 at 14:47
  • Well, not exactly what i meant. path.Join simply combines two paths, it has no idea whether the path is correct. I need somethin like MapPath from .NET framework - https://msdn.microsoft.com/en-us/library/system.web.httpserverutility.mappath(v=vs.100).aspx to build absolute path for given relative. In golang Join i need to know a callers path in order to build absolute for given(known) base path. – ArkadyB Apr 25 '16 at 14:55
  • Ok, i stopped looking for an answer assuming GOPATH is the root directory for every file in my project i build absolute path from there... – ArkadyB Apr 25 '16 at 15:49
  • Now what happens when you delpoy your program to the target system where there's no `GOPATH`? – kostix Apr 25 '16 at 16:51
  • Ah, now that you've mentioned `MapPath()`, I see where you're leading to. The problem is that that function is supposed to work in the context of IIS, which makes the .NET handler running your code know where is the base path of the deployed application. Go does not (yet) provide an ISAPI handler and so your Go application is "free standing" in the sense it's not coupled with a web server (or is quite loosly so -- if it's a CGI or FastCGI handler). Hence I'm with @icza on this: make your "base path" configurable. – kostix Apr 25 '16 at 16:56
  • In the simplest case you might default your base path to be just ".", but then make sure your program actually calls `os.Chdir(".")` somewhere early at startup -- to make the value of the current directory predictable. All-in-all, the most sensible approach does really depend on how you intend to start your program on the target system. – kostix Apr 25 '16 at 16:58
  • @kostix, well in case my GOPATH is not set app not gonna work.. This might be any different global variable setting root path for the app. Having it configurable would mean to have it saved in some configuration file placed somewhere in the project, but in this case ill need to load it in the app once again which in turn pushes me back to the same problem. Having global variables looks to be sufficient in Golang work to be used for setting up an apps. – ArkadyB Apr 26 '16 at 07:39

1 Answers1

3

Use the go/build package to find the absolute path of a package in a Go workspace:

importPath := "github.com/user/root/main" // modify to match import path of main
p, err := build.Default.Import(importPath, "", build.FindOnly)
if err != nil {
    // handle error
}
certsDir := filepath.Join(p.Dir, "certs")

This only works when run in the context of a Go workspace (the source code is available and GOPATH is set).

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242