SoFunction
Updated on 2025-03-04

Question about Golang getting the absolute path of the current project

Introduction

Since Golang is a compiled language (non-scripted language), it will be a very painful thing if you want to get the current execution directory in a Golang program. In the past, the most compromise solution was to manually pass the path to the program by starting parameter transfer or environment variables. Today, I discovered a new solution when I was looking at the log library.
Two different ways of execution of Go programs

There are two ways to execute programs written in Go, go run and go build

The usual practice is that go run is used for local development, and it is really convenient to quickly test the code in one command; when deploying a production environment, we will build a binary file through go build and upload it to the server before executing.

What problems will arise between the two startup methods?

So what problems will arise when obtaining the current execution path under the two startup methods?

Without further ado, let's just upload the code

We write a method to get the path to the current executable file

package main

import (
"fmt"
"log"
"os"
"path/filepath"
)
func main() {
("getCurrentAbPathByExecutable = ", getCurrentAbPathByExecutable())
}
// Get the absolute path where the current executor is locatedfunc getCurrentAbPathByExecutable() string {
exePath, err := ()
if err != nil {
(err)
res, _ := ((exePath))
return res

First start with go run

D:\Projects\demo>go run 
getCurrentAbPathByExecutable = C:\Users\XXX\AppData\Local\Temp\go-build216571510\b001\exe

Try go build execution again

D:\Projects\demo>go build & 
getCurrentAbPathByExecutable = D:\Projects\demo

By comparing the execution results, we found that we obtained different paths in two execution methods. And it is obvious that the path obtained by go run is wrong.

Reason: This is because go run will compile the source code into the system TEMP or TMP environment variable directory and start execution; go build will only compile the executable file in the current directory and will not be automatically executed.

We can simply understand that go run is equivalent to go build & ./main

Although both execution methods are ultimately the same process: source code -> compilation -> executable file -> execution output, their execution directories are completely different.
A new plan is born

This is something I suddenly realized when I was checking the service log (zap library) today. For example, the following is a simple log, and the service is started through go run, but the log library prints out my correct program path D:/Projects/te-server/modules/es/:139.

2021-03-26 17:47:06 D:/Projects/te-server/modules/es/:139 update es index {"index": "tags", "data": "[200 OK] {"acknowledged":true}"}

So I immediately looked through the zap source code and found that it was implemented through (). In fact, all Golang log libraries will have this call ().

I was happy to think that I had found the final answer, and then I wrote the code and tried it:

package main

import (
"fmt"
"path"
"runtime"
)
func main() {
("getCurrentAbPathByCaller = ", getCurrentAbPathByCaller())
}
// Get the absolute path of the current execution file (go run)func getCurrentAbPathByCaller() string {
var abPath string
_, filename, _, ok := (0)
if ok {
abPath = (filename)
return abPath

First try go run and go build under Windows

D:\Projects\demo>go run 
getCurrentAbPathByCaller = D:/Projects/demo

D:\Projects\demo>go build & 
getCurrentAbPathByCaller = D:/Projects/demo

Well~~ The result is completely correct!

Then I threw the built program into linux and ran it, and it printed out the path to my windows --!

[root@server app]# chmod +x demo
[root@server app]# ./demo
getCurrentAbPathByCaller = D:/Projects/demo

I didn't expect to be happy for nothing. At this time, I was thinking that since you can get the correct result through () when go run, you can also get the correct path through () when go build;

Then if I can determine whether the current program is executed through go run or go build and choose a different path to obtain it, will all the problems be solved?
Distinguish whether the program is go run or go build execution

Go does not provide an interface to distinguish whether the program is go run or go build execution, but we can implement it in another way:

According to the execution principle of go run, we learned that it will compile the source code into the system TEMP or TMP environment variable directory and start execution;

Then we can directly compare whether the path obtained by () is the same as the path set by the environment variable TEMP. If the same, it means that it is started through go run because the current execution path is in the TEMP directory; if it is different, it is naturally the way to start go build.

Here is the complete code:

package main

import (
"fmt"
"log"
"os"
"path"
"path/filepath"
"runtime"
"strings"
)
func main() {
("getTmpDir(Current system temporary directory) = ", getTmpDir())
("getCurrentAbPathByExecutable(Supported onlygo build) = ", getCurrentAbPathByExecutable())
("getCurrentAbPathByCaller(Supported onlygo run) = ", getCurrentAbPathByCaller())
("getCurrentAbPath(Final plan-Fully compatible) = ", getCurrentAbPath())
}
// Final solution - fully compatiblefunc getCurrentAbPath() string {
dir := getCurrentAbPathByExecutable()
if (dir,getTmpDir()) {
return getCurrentAbPathByCaller()
return dir
// Get the system temporary directory, compatible with go runfunc getTmpDir() string {
dir := ("TEMP")
if dir == "" {
dir = ("TMP")
res, _ := (dir)
return res
// Get the absolute path of the current execution filefunc getCurrentAbPathByExecutable() string {
exePath, err := ()
if err != nil {
(err)
res, _ := ((exePath))
// Get the absolute path of the current execution file (go run)func getCurrentAbPathByCaller() string {
var abPath string
_, filename, _, ok := (0)
if ok {
abPath = (filename)
return abPath

Execute in windows

D:\Projects\demo>go run 
getTmpDir(Current system temporary directory) = C:\Users\XXX\AppData\Local\Temp
getCurrentAbPathByExecutable(Supported onlygo build) = C:\Users\XXX\AppData\Local\Temp\go-build456189690\b001\exe
getCurrentAbPathByCaller(Supported onlygo run) = D:/Projects/demo
getCurrentAbPath(Final plan-Fully compatible) = D:/Projects/demo
D:\Projects\demo>go build & 
getTmpDir(Current system temporary directory) = C:\Users\XXX\AppData\Local\Temp
getCurrentAbPathByExecutable(Supported onlygo build) = D:\Projects\demo
getCurrentAbPathByCaller(Supported onlygo run) = D:/Projects/demo
getCurrentAbPath(Final plan-Fully compatible) = D:\Projects\demo

Upload to Linux after compilation

[root@server app]# pwd
/data/app
[root@server app]# ./demo
getTmpDir(Current system temporary directory) = .
getCurrentAbPathByExecutable(Supported onlygo build) = /data/app
getCurrentAbPathByCaller(Supported onlygo run) = D:/Projects/demo
getCurrentAbPath(Final plan-Fully compatible) = /data/app

Comparing the results, we can see that in different systems, different execution methods, the correct results we encapsulated getCurrentAbPath method ultimately outputs, perfect!

This is the article about Golang getting the absolute path of the current project. For more information about Golang, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!