Как получить каталог текущего файла?

В nodejs я использую __ dirname. Что эквивалентно этому в Голанге?

У меня есть googled и узнал эту статью http://andrewbrookins.com/tech/golang-get-directory-of-the-current-file/. Где он использует код ниже

_, filename, _, _ := runtime.Caller(1)
f, err := os.Open(path.Join(path.Dir(filename), "data.csv"))

Но это правильный путь или идиоматический способ сделать в Голанге?

Ответ 1

Это должно сделать это:

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)
}

Ответ 2

EDIT: Начиная с версии 1.8 (выпущенный в феврале 2017 года) рекомендуемый способ: os.Executable:

func Executable() (string, error)

Исполняемый файл возвращает имя пути для исполняемого файла, который запустил текущий процесс. Нет никакой гарантии, что путь все еще указывает на правильный исполняемый файл. Если для запуска процесса была использована символическая ссылка, в зависимости от операционной системы результатом может быть символическая ссылка или указатель на нее. Если необходим стабильный результат, может помочь path/filepath.EvalSymlinks.

Чтобы получить только каталог исполняемого файла, вы можете использовать path/filepath.Dir.

Пример:

package main

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

func main() {
    ex, err := os.Executable()
    if err != nil {
        panic(err)
    }
    exPath := filepath.Dir(ex)
    fmt.Println(exPath)
}

СТАРЫЙ ОТВЕТ:

Вы можете использовать os.Getwd

func Getwd() (pwd string, err error)

Getwd возвращает имя корневого пути, соответствующее текущему каталогу. Если текущий каталог может быть достигнут через несколько путей (из-за символических ссылок), Getwd может вернуть любой из них.

Например:

package main

import (
    "fmt"
    "os"
)

func main() {
    pwd, err := os.Getwd()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println(pwd)
}

Ответ 3

Использовать пакет osext

Он предоставляет функцию ExecutableFolder(), которая возвращает абсолютный путь к папке, в которой находится исполняемый исполняемый файл программы (полезен для заданий cron). Это перекрестная платформа.

Онлайн-документация

package main

import (
    "github.com/kardianos/osext"
    "fmt"
    "log"
)

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

Ответ 4

filepath.Abs("./")

Abs возвращает абсолютное представление пути. Если путь не является абсолютным, он будет соединен с текущим рабочим каталогом, чтобы превратить его в абсолютный путь.

Как указано в комментарии, это возвращает каталог, который в настоящее время активен.

Ответ 5

Если вы используете пакет osext по kardianos, и вам необходимо протестировать локально, например, Derek Dowling прокомментировал:

Это отлично работает, пока вы не захотите использовать его с go run main.go для локального развития. Не знаете, как лучше обойти это без каждый раз создавая исполняемый файл.

Решение этого заключается в том, чтобы сделать утилиту gorun.exe вместо использования go run. Утилита gorun.exe скомпилирует проект, используя "go build", а затем запустит его сразу же в обычном каталоге вашего проекта.

У меня была эта проблема с другими компиляторами и я обнаружил, что делаю эти утилиты, так как они не поставляются с компилятором... это особенно тайно с такими инструментами, как C, где вы должны скомпилировать и связать, а затем запустить его (слишком много работы).

Если кому-то понравится моя идея gorun.exe(или эльфа), я, скорее всего, скоро отправлю его в github..

Извините, этот ответ подразумевается как комментарий, но я не могу комментировать из-за того, что у меня недостаточно репутации.

В качестве альтернативы "go run" может быть изменен (если он еще не имеет этой функции), чтобы иметь такой параметр, как "go run -notemp", чтобы не запускать программу во временном каталоге (или что-то подобное). Но я бы предпочел просто набирать горун или "гора", поскольку он короче, чем свернутый параметр. Gorun.exe или gor.exe необходимо будет установить в том же каталоге, что и ваш компилятор go

Реализация gorun.exe(или gor.exe) будет тривиальной, поскольку я сделал это с другими компиляторами всего в нескольких строках кода... (известные последние слова; -)

Ответ 6

если вы используете этот способ:

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

вы получите путь /tmp при запуске программы с использованием некоторой IDE, такой как GoLang, потому что исполняемый файл будет сохраняться и запускаться из /tmp

Я думаю, что лучший способ получить текущий рабочий каталог или "." является:

import(
  "os" 
  "fmt"
  "log"
)

func main() {
  dir, err := os.Getwd()
    if err != nil {
        log.Fatal(err)
    }
  fmt.Println(dir)
}

функция os.Getwd() вернет текущий рабочий каталог.

Ответ 7

os.Executable: https://tip.golang.org/pkg/os/#Executable

filepath.EvalSymlinks: https://golang.org/pkg/path/filepath/#EvalSymlinks

Полная демонстрация:

package main

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

func main() {
    var dirAbsPath string
    ex, err := os.Executable()
    if err == nil {
        dirAbsPath = filepath.Dir(ex)
        fmt.Println(dirAbsPath)
        return
    }

    exReal, err := filepath.EvalSymlinks(ex)
    if err != nil {
        panic(err)
    }
    dirAbsPath = filepath.Dir(exReal)
    fmt.Println(dirAbsPath)
}

Ответ 8

иногда этого достаточно, аргумент firs всегда будет основным путем к файлу

import (
    "fmt"
    "os"
)


func main() {
    fmt.Println(os.Args[0])
}