How to get current directory in Golang? [SOLVED]


Written By - Tuan Nguyen
Advertisement

In this article, we will walk through some examples of getting the directory of the currently running program. We compile a Go program for various platforms and run it by calling a relative path or just by its name, how every sometimes we need to know where is the executable file. With the help of some built-in packages, we can easily get the source file location or the executable file.

 

Method-1: The os package and Executable() function

Package os provides a platform-independent interface to operating system functionality. The design is Unix-like, although the error handling is Go-like; failing calls return values of type error rather than error numbers. Often, more information is available within the error.

func Executable() (string, error): Executable returns the path name for the executable that started the current process. There is no guarantee that the path is still pointing to the correct executable.

If a symlink was used to start the process, depending on the operating system, the result might be the symlink or the path it pointed to. If a stable result is needed, path/filepath.EvalSymlinks might help. Executable returns an absolute path unless an error occurred. The main use case is finding resources located relative to an executable.

To get the directory of the executable you can use path/filepath.Dir.

Here is an example of printing out the location of the running file with the Executable() function:

package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	ex, err := os.Executable()
	if err != nil {
		panic(err)
	}
	// file executable
	fmt.Println(ex)

	// the executable directory
	exPath := filepath.Dir(ex)
	fmt.Println(exPath)
}

Output:

C:\Users\nguye\AppData\Local\Temp\go-build3009376824\b001\exe\ospath.exe
C:\Users\nguye\AppData\Local\Temp\go-build3009376824\b001\exe

 

Method-2: file/filepath and the Abs() function

Package filepath implements utility routines for manipulating filename paths in a way compatible with the target operating system-defined file paths.

Advertisement

func Abs(path string) (string, error): Abs returns an absolute representation of a path. If the path is not absolute it will be joined with the current working directory to turn it into an absolute path. The absolute path name for a given file is not guaranteed to be unique. Abs calls Clean on the result.

Here is an example of using the Abs() function to get the current Golang executable file:

package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
)

func main() {
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(dir)
}

Output:

C:\Users\nguye\AppData\Local\Temp\go-build2221200443\b001\exe

Explanation: the Args hold the command-line arguments, starting with the program name. A problem with this solution: this usesĀ os.Args which is creating a dependency over os.Args, restricts it from getting the path of files in other modules in the application. The os.Args[0] value are arbitrary and cannot be relied on; os.Args[0] can be "faked".

 

Method-3: Using the osext package

osext is the extension to the "os" package. You can get this package by running the command below:

go get -u github.com/kardianos/osext

The code below shows an easy way to get the executable file's location using the osext package:

package main

import (
	"fmt"
	"log"

	"github.com/kardianos/osext"
)

func main() {
	folderPath, err := osext.ExecutableFolder()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(folderPath)
}

Output:

C:\Users\nguye\AppData\Local\Temp\go-build287942699\b001\exe

 

Method-4: Get the source file location

Sometimes, you do not want to find the location of the executable file, you want to know where the source file is located. To do that, we can use the Abs() function from the path package introduced above:

package main

import (
	"fmt"
	"log"
	"path/filepath"
)

func main() {
	dir, err := filepath.Abs("./")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(dir)
}

Another way to get the current source file location is to use runtime.Caller() function:

func Caller(skip int) (pc uintptr, file string, line int, ok bool): Caller reports file and line number information about function invocations on the calling goroutine's stack. The argument skip is the number of stack frames to ascend, with 0 identifying the caller of Caller. (For historical reasons the meaning of skip differs between Caller and Callers.)
The return values report the program counter, file name, and line number within the file of the corresponding call. The boolean ok is false if it was not possible to recover the information.
You can use the code below to get the current source file location with the runtime.Caller function:

package main

import (
	"fmt"
	"path/filepath"
	"runtime"
)

func main() {
	_, filename, _, ok := runtime.Caller(0)
	if !ok {
		fmt.Println("Unable to get the current filename")
	}
	dirname := filepath.Dir(filename)
	fmt.Println(dirname)
}

Output:

How to get current directory in Golang? [SOLVED]

 

Summary

TheĀ Golang programming language makes it easy to build simple, reliable, and efficient software. You can get the current directory of the source code you are running or the executable file. With the os and file/filepath built-in package, we can simply get this information. We can also use a third-party library (osext) for getting the executable path.

 

References

https://github.com/kardianos/osext
https://pkg.go.dev/os@master#Executable
https://pkg.go.dev/path/filepath#Abs
https://pkg.go.dev/runtime#Callers

 

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment