как ссылаться на относительный файл из кода и тестов

Мне нужно сослаться на patients.json из patients.go, вот структура папок:

введите описание изображения здесь

If I do:

filepath.Abs("../../conf/patients.json")

он работает для go test ./..., но не работает для revel run

If I do:

filepath.Abs("conf/patients.json")

происходит прямо противоположное (веселье - это хорошо, но тесты не проходят).

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


person Pablo Fernandez    schedule 25.06.2015    source источник


Ответы (3)


Относительные пути всегда интерпретируются / разрешаются как базовый путь: текущий или рабочий каталог - поэтому он всегда будет иметь свои ограничения.

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

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

Рекомендуемые способы переопределения базового пути, по которому разрешаются ваши «относительные» пути:

  1. Флаг командной строки (см. Пакет flag)
  2. Переменная среды (см. os.Getenv())
  3. (Исправить имя) Файл конфигурации в домашнем каталоге пользователя (см. os/user/User и _ 4_)

Когда у вас есть базовый путь, вы можете получить полный путь, соединив базовый путь и относительный путь. Вы можете использовать path.Join() или _ 6_, например:

// Get base path, from any or from the combination of the above mentioned solutions
base := "/var/myapp"

// Relative path, resource to read/write from:
relf := "conf/patients.json"

// Full path that identifies the resource:
full := filepath.Join(base, relf) // full will be "/var/myapp/conf/patients.json"
person icza    schedule 25.06.2015
comment
есть ли способ узнать путь к файлу .go? - person Pablo Fernandez; 25.06.2015
comment
@PabloFernandez Если он скомпилирован в исполняемый двоичный файл, нет даже .go файла ... - person icza; 25.06.2015
comment
Я бы упомянул еще одну возможность: 1) иметь глобальную переменную, определяющую префикс базового каталога для ресурсов, скажем, main.AssetsDir; 2) разрешить последующим упаковщикам переопределять его во время сборки, используя способность компоновщика переопределять строковые значения, например: go build -ldflags="-X main.AssetsDir=/usr/share/cool_app/assets". ОП может получить больше информации об этом, изучив выходные данные go help build и go tool link -h. - person kostix; 25.04.2016
comment
@kostix Хорошая идея, но это ограничивает возможности настройки разработчиками. Пользователи, не обладающие знаниями в области программирования, найдут флаги командной строки намного удобнее и проще в использовании, чем флаги сборки. - person icza; 25.04.2016

Сам я никогда не использовал Revel, но мне показались полезными следующие моменты:

http://revel.github.io/docs/godoc/revel.html

  • revel.BasePath
  • revel.AppPath
person alediaferia    schedule 25.06.2015
comment
Не знаю почему, но оба BasePath и AppPath возвращают пустую строку: / - person Pablo Fernandez; 25.06.2015
comment
@PabloFernandez тебе понравилось .Init ()? - person alediaferia; 25.06.2015
comment
Ссылка мертвая. Новый выглядит https://revel.github.io/. - person Matt3o12; 05.07.2017

Это не проблема пути, а проблема вашего дизайна.

Вам следует более тщательно разрабатывать свой код.

Насколько я могу судить, вы используете один и тот же путь в своем тестовом файле и показываете run. Я предполагаю, что, возможно, вы жестко запрограммируете свой json путь в своем пакете модели, который не предлагается.

Лучший способ

  • Пакет модели получает путь json из глобальной конфигурации или модель инициализации с путем json, например model := NewModel(config_path). так что вы можете запустить модель инициализации с любым json, который вы хотите.
  • жесткий код "../../conf/patients.json" в вашем xxxx_testing.go
person Billy Yuan    schedule 16.01.2019