3

I've been using this function on osx:

// Shortcut to get the path to the current executable                      
func ExecPath() string {                                                   
  var here = os.Args[0]                                                    
  if !strings.HasPrefix(here, "/") {                                       
    here, _ = exec.LookPath(os.Args[0])                                    
    if !strings.HasPrefix(here, "/") {                                     
      var wd, _ = os.Getwd()                                               
      here = path.Join(wd, here)                                           
    }                                                                      
  } 
  return here                                                              
}

...but its pretty messy, and it doesn't work on windows at all, and certainly not in git-bash on windows.

Is there a way of doing this cross platform?

NB. Specifically that args[0] depends on how the binary is invoked; it is in some cases only the binary itself, eg. "app" or "app.exe"; so you can't just use that.

Doug
  • 32,844
  • 38
  • 166
  • 222

2 Answers2

4

This is the traditional way of doing it which I think will work under any platform.

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

// Shortcut to get the path to the current executable                      
func ExecPath() string {
    var here = os.Args[0]
    here, err := filepath.Abs(here)
    if err != nil {
        fmt.Printf("Weird path: %s\n", err)
    }
    return here
}
Nick Craig-Wood
  • 52,955
  • 12
  • 126
  • 132
0

I don't think there is a cross-platform way to do this.

However, on OS X, there is a better way. dyld provides a function _NSGetExecutablePath() that gives you the path to the executable. You can call this with CGo.

package main

// #import <mach-o/dyld.h>
import "C"

import (
    "fmt"
)

func NSGetExecutablePath() string {
    var buflen C.uint32_t = 1024
    buf := make([]C.char, buflen)

    ret := C._NSGetExecutablePath(&buf[0], &buflen)
    if ret == -1 {
        buf = make([]C.char, buflen)
        C._NSGetExecutablePath(&buf[0], &buflen)
    }
    return C.GoStringN(&buf[0], C.int(buflen))
}

func main() {
    fmt.Println(NSGetExecutablePath())
}
Lily Ballard
  • 182,031
  • 33
  • 381
  • 347