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.
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 usesos.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:
Summary
TheGolang 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

![How to get current directory in Golang? [SOLVED]](/golang-get-current-directory/golang-get-current-directory.jpg)
