One place for hosting & domains

      систем

      Использование модуля pathlib для манипуляции путями файловых систем в Python 3


      Автор выбрал COVID-19 Relief Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      Python 3 включает модуль pathlib для манипуляции путями файловых систем независимо от операционной системы. pathlib похож на модуль os.path, но pathlib предлагает более развитый и удобный интерфейс по сравнению с os.path.

      Мы можем идентифицировать файлы на компьютере с помощью иерархических путей. Например, мы можем идентифицировать файл wave.txt на компьютере с помощью этого пути: /Users/sammy/ocean/wave.txt. Операционные системы представляют пути несколько по-разному. Windows может представлять путь к файлу wave.txt как C:Userssammyoceanwave.txt.

      Модуль pathlib может быть полезен, если в программе Python вы создаете или перемещаете файлы в файловой системе, указывая все файлы в файловой системе, совпадающие с данным расширением или шаблоном, или создаете пути файла, соответствующие файловой системе на основе наборов неформатированных строк. Хотя вы можете использовать другие инструменты, например модуль os.path, для выполнения большей части этих задач, модуль pathlib позволяет выполнять эти операции с большей степенью читаемости и минимальным количеством кодов.

      В этом обучающем модуле мы рассмотрим некоторые способы использования модуля pathlib для представления и манипуляции путями файловых систем.

      Предварительные требования

      Чтобы получить максимум знаний из этого обучающего модуля, рекомендуется иметь небольшое представление о программировании на Python 3. Дополнительную информацию можно найти в следующих обучающих руководствах:

      Построение экземпляров Path

      Модуль pathlib предоставляет несколько классов, но одним из наиболее важных является класс Path. Экземпляры класса Path представляют путь к файлу или каталогу в файловой системе вашего компьютера.

      Например, следующий код инстанциирует экземпляр Path, который представляет часть пути к файлу wave.txt:

      from pathlib import Path
      
      wave = Path("ocean", "wave.txt")
      print(wave)
      

      Если запустить этот код, результат будет выглядеть следующим образом:

      Output

      ocean/wave.txt

      from pathlib import Path делает класс Path доступным для нашей программы. Затем Path("ocean", "wave.txt") инстанциирует новый экземпляр Path. Вывод отображает, что Python добавил соответствующий разделитель оперативной системы / между двумя заданными нами компонентами пути "ocean" и "wave.txt".

      Примечание. В зависимости от операционной системы вывод может немного отличаться от примеров, приведенных в данном руководстве. Если вы работаете в Windows, например, ваш вывод для этого первого примера может выглядеть как oceanwave.txt.

      В настоящее время объект Path, назначенный на переменную wave, содержит относительный путь. Другими словами, ocean/wave.txt может существовать в нескольких местах в нашей файловой системе. В качестве примера он может существовать в /Users/user_1/ocean/wave.txt или /Users/user_2/research/ocean/wave.txt, но мы не указали к какому из них конкретно мы обращаемся. Абсолютный путь, напротив, однозначно четко указывает на расположение в файловой системе.

      Вы можете использовать Path.home() для получения абсолютного пути к домашнему каталогу текущего пользователя:

      home = Path.home()
      wave_absolute = Path(home, "ocean", "wave.txt")
      print(home)
      print(wave_absolute)
      

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

      Output

      /Users/sammy /Users/sammy/ocean/wave.txt

      Примечание. Как упоминалось ранее, вывод будет зависеть от операционной системы. Ваш домашний каталог также будет отличаться от /Users/sammy.

      Path.home() возвращает экземпляр Path с абсолютным путем в домашний каталог текущего пользователя. Затем мы передадим этот экземпляр Path и строки "ocean" и "wave.txt" в другой конструктор Path, чтобы создать абсолютный путь к файлу wave.txt. Вывод показывает, что первая строка — это домашний каталог, а вторая строка — домашний каталог плюс ocean/wave.txt.

      Этот пример также иллюстрирует важную функцию класса Path: конструктор Path принимает обе строки и ранее существовавшие объекты Path.

      Давайте более детально рассмотрим поддержку строк и объектов Path в конструкторе Path:

      shark = Path(Path.home(), "ocean", "animals", Path("fish", "shark.txt"))
      print(shark)
      

      Если запустить этот код Python, результат будет выглядеть следующим образом:

      Output

      /Users/sammy/ocean/animals/fish/shark.txt

      shark — это Path к файлу, который мы создали с помощью объектов Path (Path.home() и Path("fish", "shark.txt") и строк "ocean" и "animals"). Конструктор Path интеллектуально обрабатывает оба типа объектов и аккуратно соединяет их с помощью соответствующего разделителя операционной системы, в данном случае /.

      Доступ к атрибутам файла

      Теперь, когда мы узнали, как создать экземпляры Path, давайте рассмотрим, как можно использовать эти экземпляры для доступа к информации о файле.

      Мы можем использовать атрибуты name и suffix для доступа к именам и расширениям файлов:

      wave = Path("ocean", "wave.txt")
      print(wave)
      print(wave.name)
      print(wave.suffix)
      

      Запустив этот код, мы получим вывод, аналогичный следующему:

      Output

      /Users/sammy/ocean/wave.txt wave.txt .txt

      Этот вывод показывает, что имя файла в конце нашего пути — wave.txt, а расширение файла — .txt.

      Экземпляры Path также предлагают функцию with_name, позволяющую беспрепятственно создавать новый объект Path с другим именем:

      wave = Path("ocean", "wave.txt")
      tides = wave.with_name("tides.txt")
      print(wave)
      print(tides)
      

      Если запустить его, результат будет выглядеть следующим образом:

      ocean/wave.txt
      ocean/tides.txt
      

      Код сначала создает экземпляр Path, указывающий на файл с именем wave.txt. Затем мы вызовем метод with_name в wave, чтобы вернуть второй экземпляр Path, указывающий на новый файл с именем tides.txt. Часть каталога ocean/ остается неизмененной и оставляет финальный путь в виде ocean/tides.txt

      Доступ к предшествующим объектам

      Иногда полезно получить доступ к каталогам, содержащим определенный путь. Давайте рассмотрим пример:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      print(shark)
      print(shark.parent)
      

      Если запустить этот код, результат будет выглядеть следующим образом:

      Output

      ocean/animals/fish/shark.txt ocean/animals/fish

      Атрибут parent в экземпляре Path возвращает ближайшего предшественника пути данного файла. В этом случае он возвращает каталог с файлом shark.txt: ocean/animals/fish.

      Мы можем получать доступ к атрибуту parent несколько раз в строке, чтобы пройти вверх по корневому дереву данного файла:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      print(shark)
      print(shark.parent.parent)
      

      Если мы выполним этот код, мы увидим следующие результаты:

      Output

      ocean/animals/fish/shark.txt ocean/animals

      Вывод будет похож на предыдущий вывод, но теперь мы перешли на уровень выше, получив доступ к .parent во второй раз. Два каталога от shark.txt — это каталог ocean/animals.

      Использование шаблона поиска для списка файлов

      Также можно использовать класс Path для списка файлов с помощью метода glob.

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

      └── ocean
          ├── animals
          │   └── fish
          │       └── shark.txt
          ├── tides.txt
          └── wave.txt
      

      Каталог ocean содержит файлы tides.txt и wave.txt. У нас есть файл с именем shark.txt, вложенный в каталог ocean, каталог animals и каталог fish: ocean/animals/fish.

      Чтобы перечислить все файлы .txt в каталоге ocean, можно сказать:

      for txt_path in Path("ocean").glob("*.txt"):
          print(txt_path)
      

      Этот код произведет следующий вывод:

      Output

      ocean/wave.txt ocean/tides.txt

      Шаблон поиска "*.txt" находит все файлы, заканчивающиеся на .txt. Поскольку пример кода выполняет этот поиск в каталоге ocean, он возвращает два файла .txt в каталоге ocean: wave.txt и tides.txt.

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

      Также мы можем использовать метод glob рекурсивно. Чтобы перечислить все файлы .txt в каталоге ocean и все его подкаталоги, мы можем сказать:

      for txt_path in Path("ocean").glob("**/*.txt"):
          print(txt_path)
      

      Если запустить этот код, результат будет выглядеть следующим образом:

      Output

      ocean/wave.txt ocean/tides.txt ocean/animals/fish/shark.txt

      Часть ** шаблона поиска будет соответствовать этому каталогу и всем каталогам под ним рекурсивно. Поэтому в выводе у нас будут не только файлы wave.txt и tides.txt, но также мы получим файл shark.txt, вложенный в ocean/animals/fish.

      Вычисление относительных путей

      Мы можем использовать метод Path.relative_to для вычисления путей, относящихся друг к другу. Метод relative_to полезен, если, например, вы хотите получить часть длинного пути файла.

      Рассмотрите следующий код:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      below_ocean = shark.relative_to(Path("ocean"))
      below_animals = shark.relative_to(Path("ocean", "animals"))
      print(shark)
      print(below_ocean)
      print(below_animals)
      

      Если запустить его, результат будет выглядеть следующим образом:

      Output

      ocean/animals/fish/shark.txt animals/fish/shark.txt fish/shark.txt

      Метод relative_to возвращает новый объект Path, относящийся к данному аргументу. В нашем примере мы вычислим Path к shark.txt, относящийся к каталогу ocean, а затем относящийся к обоим каталогам ocean и animals.

      Если relative_to не сможет вычислить ответ, поскольку мы даем ему не связанный путь, он выдаст ValueError:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      shark.relative_to(Path("unrelated", "path"))
      

      Мы получим исключение ValueError, возникшее из этого кода, которое будет выглядеть следующим образом:

      Output

      Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/Python3.8/pathlib.py", line 899, in relative_to raise ValueError("{!r} does not start with {!r}" ValueError: 'ocean/animals/fish/shark.txt' does not start with 'unrelated/path'

      unrelated/path не является частью ocean/animals/fish/shark.txt, поэтому Python не сможет вычислить относительный путь.

      Заключение

      Модуль pathlib — это мощная часть стандартной библиотеки Python, которая позволяет нам быстро манипулировать путями файловых систем в любой операционной системе. В этом обучающем модуле мы научились использовать некоторые ключевые утилиты pathlib для доступа к атрибутам файла, спискам файлов с помощью шаблонов поиска и переходить к родительским файлам и каталогам.

      Модуль pathlib представляет дополнительные классы и утилиты, которые мы не охватили в данном руководстве. После получения базового уровня вы можете использовать документацию модуля pathlib для получения дополнительной информации о других имеющихся классов и утилитах.

      Если вас интересуют другие библиотеки Python, ознакомьтесь со следующими обучающими модулями:



      Source link

      Создание приложений Go для различных операционных систем и разной архитектуры


      При разработке программного обеспечения очень важно учитывать операционную систему и архитектуру процессора, для которого вы будете компилировать ваш бинарный файл. Поскольку часто бывает очень трудно или просто невозможно запустить один бинарный файл на разных ОС/архитектурах, довольно распространенной практикой является сборка итогового бинарного файла для набора различных платформ для максимального увеличения аудитории вашей программы. Однако это может оказаться затруднительным, когда платформа, которую вы используете для разработки, отличается от платформы, где вы хотите развернуть вашу программу. В прошлом, например, при разработке программы на Windows и ее последующем развертывании на компьютере с Linux или macOS могла требоваться настройка инструмента для сборки для каждой среды, где вам требуется бинарный файл. Кроме того, вам нужно поддерживать ваш инструментарий в синхронизированном состоянии, а также учитывать другие моменты, что будет приводить к росту издержек и затруднит совместное тестирование и распространение.

      Go решает эту проблему посредством поддержки различных платформ напрямую в инструменте go build, а также в остальной цепочке инструментов Go. Используя переменные среды и теги сборки, вы можете контролировать, для какой ОС и архитектуры предназначен ваш бинарный файл, а также реализовать рабочий процесс, который позволит быстро добавлять предназначенный для конкретной платформы код без внесения изменений в базу вашего кода.

      В этом руководстве вы создадите пример приложения, которое будет соединять строки в путь файла, создадите и будете избирательно включать предназначенные для конкретной платформы сниппеты кода, а также выполните сборку бинарных файлов для различных операционных систем и архитектур в вашей собственной системе, что позволит вам понять, как использовать этот мощный функционал языка программирования Go.

      Предварительные требования

      Для выполнения примера из этой статьи вам потребуется следующее:

      Возможные платформы GOOS и GOARCH

      Прежде чем продемонстрировать, как вы можете контролировать процесс сборки бинарных файлов для различных платформ, давайте узнаем, для каких платформ Go в состоянии выполнять сборку, а также как Go ссылается на эти платформы, используя переменные среды GOOS и GOARCH.

      Инструменты Go имеют команду, которая может вывести список поддерживаемых Go платформ для сборки. Этот список может меняться с каждым новым релизом Go, так что описанные здесь комбинации могут быть иными в другой версии Go. На момент написания настоящего руководства текущая версия Go — 1.13.

      Чтобы просмотреть список поддерживаемых платформ, запустите следующую команду:

      Вы получите примерно следующий результат:

      Output

      aix/ppc64 freebsd/amd64 linux/mipsle openbsd/386 android/386 freebsd/arm linux/ppc64 openbsd/amd64 android/amd64 illumos/amd64 linux/ppc64le openbsd/arm android/arm js/wasm linux/s390x openbsd/arm64 android/arm64 linux/386 nacl/386 plan9/386 darwin/386 linux/amd64 nacl/amd64p32 plan9/amd64 darwin/amd64 linux/arm nacl/arm plan9/arm darwin/arm linux/arm64 netbsd/386 solaris/amd64 darwin/arm64 linux/mips netbsd/amd64 windows/386 dragonfly/amd64 linux/mips64 netbsd/arm windows/amd64 freebsd/386 linux/mips64le netbsd/arm64 windows/arm

      Данный вывод — это набор пар ключ-значение, разделенных /. Первая часть комбинации перед символом / — это операционная система. В Go эти операционные системы — это возможные значения для переменной среды GOOS, произносится “goose”, название которой означает операционная система Go. Вторая часть, идущая после /, — это архитектура. Как и в случае с операционной системой, это все возможные значения для переменной среды: GOARCH. Это сокращение произносится “gore-ch” и означает архитектура Go.

      Давайте разберем одну из этих комбинаций, чтобы понять, что это означает и как работает, воспользовавшись linux/386 в качестве примера. Пара ключ-значение начинается с переменной GOOS, которая в этом случае будет linux, то есть ОС Linux. Для GOARCH здесь указано значение 386, что означает микропроцессор Intel 80386.

      Существует множество доступных для команды go build платформ, но в большинстве случаев вы будете использовать linux, windows или darwin в качестве значения для GOOS. Это позволяет покрыть три важнейшие платформы OS: Linux, Windows и macOS, которая основана на операционной системе Darwin и поэтому называется darwin. Однако Go позволяет охватить и менее популярные платформы, например nacl, т. е. Native Client от Google.

      Когда вы запускаете команду, например go build​​​, Go использует GOOS и GOARCH для определения способа сборки бинарного файла. Чтобы узнать, какая конфигурация у вашей платформы, вы можете использовать команду go env и передать GOOS и GOARCH в качестве аргументов:

      При тестировании этого примера мы запускаем эту команду в macOS на компьютере с архитектурой AMD64, поэтому мы получим следующее:

      Output

      darwin amd64

      Здесь вывод команды указывает нам, что в нашей системе GOOS=darwin и GOARCH=amd64.

      Теперь вы знаете, что такое GOOS и GOARCH в Go, а также их возможные значения. Далее вы выполните сборку программы для использования в качестве примера использования этих переменных среды и меток сборки для получения бинарных файлов для других платформ.

      Написание платформо-зависимой программы с помощью filepath.Join()

      Прежде чем начать сборку бинарных файлов для других платформ, мы создадим пример программы. Для этой задачи отлично подходит функция Join в пакете path/filepath в стандартной библиотеке Go. Эта функция получает ряд строк и возвращает одну строку, к которой добавлен соответствующий разделитель пути файла.

      Это отличный пример программы, поскольку работа программы зависит от того, в какой ОС она запущена. Для Windows разделитель пути файла — это обратный слэш ​​​, а в системах Unix используется прямой слэш /.

      Давайте начнем сборку приложения, которое использует filepath.Join(), а затем вы напишете свою собственную реализацию функции Join(), которая настраивает код в соответствии с платформой.

      Во-первых, создайте папку в директории src с именем вашего приложения:

      Перейдите в эту директорию:

      Далее создайте новый файл в текстовом редакторе по вашему выбору с именем main.go. В этом обучающем руководстве мы будем использовать Nano:

      После открытия файла добавьте следующий код:

      src/app/main.go

      package main
      
      import (
        "fmt"
        "path/filepath"
      )
      
      func main() {
        s := filepath.Join("a", "b", "c")
        fmt.Println(s)
      }
      

      Функция main() в этом файле использует filepath.Join() для конкатенации трех строк вместе с правильным платформо-зависимым разделителем пути.

      Сохраните и закройте файл, а затем запустите программу:

      При запуске этой программы вы получите разный вывод в зависимости от того, какую платформу вы используете. В Windows вы увидите, что строки будут разделены :

      Output

      abc

      В системах Unix, в том числе macOS и Linux, вы получите следующее:

      Output

      a/b/c

      Это означает, что из-за разных протоколов файловой системы, используемых в этих операционных системах, программа должна будет выполнять разный код для различных платформ. Однако поскольку в ней уже используется разный разделитель пути файла в зависимости от операционной системы, мы знаем, что filepath.Join() уже учитывает различие в платформе. Это вызвано тем, что цепь инструментов Go автоматически определяет GOOS и GOARCH на вашем компьютере и использует эту информацию для применения сниппета кода с правильными маркерами сборки и разделителем файла.

      Давайте рассмотрим, откуда функция filepath.Join() получает нужный разделитель. Запустите следующую команду для просмотра соответствующего сниппета из стандартной библиотеки Go:

      • less /usr/local/go/src/os/path_unix.go

      В результате вы увидите содержимое path_unix.go. Найдите следующую часть файла:

      /usr/local/go/os/path_unix.go

      . . .
      // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
      
      package os
      
      const (
        PathSeparator     = '/' // OS-specific path separator
        PathListSeparator = ':' // OS-specific path list separator
      )
      . . .
      

      В этом разделе определяется PathSeparator для всех разновидностей Unix-систем, которые поддерживает Go. Обратите внимание на все маркеры сборки сверху, каждый из которых является одним из возможных значений платформ Unix для GOOS. Когда GOOS соответствует этим терминам, ваша программа будет выводить разделитель файла в стиле Unix.

      Нажмите q для возврата к командной строке.

      Далее откройте файл, который определяет поведение filepath.Join() при использовании в Windows:

      • less /usr/local/go/src/os/path_windows.go

      Вы увидите следующее:

      /usr/local/go/os/path_unix.go

      . . .
      package os
      
      const (
              PathSeparator     = '\' // OS-specific path separator
              PathListSeparator = ';'  // OS-specific path list separator
      )
      . . .
      

      Хотя здесь значение PathSeparator будет \, код будет отображать отдельный обратный слэш (), необходимый для путей файлов в Windows, поскольку первый обратный слэш требуется только в качестве символа перехода.

      Обратите внимание, что в отличие от файла Unix, сверху нет меток сборки. Это объясняется тем, что GOOS и GOARCH также могут быть переданы команде go build, добавив нижнее подчеркивание (_) и значение переменной среды в качестве суффикса для имени файла. Мы обсудим это подробнее в разделе Использование суффиксов имен файлов GOOS и GOARCH. Здесь часть _windows названия имени path_windows.go заставляет файл вести себя так, будто у него есть маркер сборки // +build windows в верхней части файла. В связи с этим, когда ваша программа запускается в Windows, она будет использовать константы PathSeparator и PathListSeparator из сниппета кода path_windows.go.

      Чтобы вернуться к командной строке, выйдите из less, нажав q.

      На этом шаге вы создали программу, показывающую, как Go автоматически преобразовывает GOOS и GOARCH в маркеры сборки. Держа это в уме, вы можете обновить вашу программу и написать свою собственную реализацию filepath.Join(), используя маркеры сборки, чтобы вручную задать правильный PathSeparator для платформ Windows и Unix.

      Реализация платформенно-зависимой функции

      Теперь, когда вы знаете, как стандартная библиотека Go имплементирует специфичный для платформы код, вы можете использовать маркеры сборки, чтобы сделать это в вашей собственной программе app. Для этого вам нужно будет написать свою собственную реализацию filepath.Join().

      Откройте ваш файл main.go:

      Замените содержимое main.go на следующее, используя свою собственную функцию с именем Join():

      src/app/main.go

      package main
      
      import (
        "fmt"
        "strings"
      )
      
      func Join(parts ...string) string {
        return strings.Join(parts, PathSeparator)
      }
      
      func main() {
        s := Join("a", "b", "c")
        fmt.Println(s)
      }
      

      Функция Join получает ряд частей и объединяет их вместе с помощью метода strings.Join() из пакета strings для конкатенации частей, используя PathSeparator.

      Вы еще не определили PathSeparator, поэтому давайте сделаем это в другом файле. Сохраните и выйдите из main.go, откройте ваш любимый редактор и создайте новый файл с именем path.go:

      nano path.go
      

      Определите PathSeparator и установите его равным разделителю пути файла Unix /:

      src/app/path.go

      package main
      
      const PathSeparator = "/"
      

      Скомпилируйте и запустите приложение:

      Вывод должен выглядеть следующим образом:

      Output

      a/b/c

      Это значит, что программа успешно запускается для получения пути файла в стиле Unix. Однако это еще не то, что нам нужно: вывод всегда будет a/b/c, вне зависимости от того, на какой платформе программа запущена. Чтобы добавить функционал создания пути файла в стиле Windows, вам нужно добавить версию PathSeparator для Windows и указать команде go build, какую версию следует использовать. В следующем разделе вы сможете воспользоваться маркерами сборки, чтобы выполнить эту задачу.

      Использование маркеров GOOS или GOARCH

      Чтобы учитывать платформы Windows, вы создадите альтернативный файл для path.go и будете использовать маркеры сборки, чтобы убедиться, что сниппеты кода запускаются, только когда GOOS и GOARCH принадлежат к соответствующей платформе.

      Однако сначала нужно добавить маркер сборки в path.go, чтобы указать ему на необходимость выполнять сборку для любых платформ, кроме Windows. Откройте файл:

      Добавьте в файл выделенный маркер сборки:

      src/app/path.go

      // +build !windows
      
      package main
      
      const PathSeparator = "/"
      

      Маркеры сборки Go позволяют использовать инвертирование, что означает, что вы можете указать Go выполнить сборку этого файла для любой платформы, кроме Windows. Чтобы инвертировать маркер доступа, добавьте ! перед маркером.

      Сохраните и закройте файл.

      Теперь, если бы вы захотели запустить эту программу в Windows, то получили бы следующую ошибку:

      Output

      ./main.go:9:29: undefined: PathSeparator

      В данном случае Go не сможет включить path.go для определения переменной PathSeparator.

      Теперь, когда вы убедились, что path.go не будет запускаться, когда для GOOS используется значение Windows, добавьте новый файл, windows.go:

      В файле windows.go необходимо определить PathSeparator для Windows, а также маркер сборки, чтобы команда go build смогла понимать, что это реализация для Windows:

      src/app/windows.go

      // +build windows
      
      package main
      
      const PathSeparator = "\"
      

      Сохраните файл и выйдите из текстового редактора. Теперь приложение может компилироваться одним образом для Windows, а другим образом для всех остальных платформ.

      Хотя теперь сборка бинарных файлов будет выполняться корректно для соответствующих платформ, есть и другие изменения, которые нужно внести для выполнения компиляции для платформы, к которой у вас нет доступа. Для этого на следующем шаге нам нужно будет изменить локальные переменные GOOS и GOARCH.

      Использование ваших локальных переменных среды GOOS и GOARCH

      Ранее вы запускали команду go env GOOS GOARCH для получения информации о том, в какой ОС и с какой архитектурой вы работаете. При запуске команды go env выполняется поиск двух переменных среды GOOS и GOARCH; если их удалось найти, будут использоваться их значения, но если они не были найдены, Go будет использовать для них информацию для текущей платформы. Это означает, что вы можете изменить значения GOOS или GOARCH, чтобы они не совпадали по умолчанию с данными локальной операционной системы и архитектуры.

      Команда go build ведет себя примерно так же, как и команда go env. Вы можете задать для переменных среды GOOS или GOARCH значение для получения сборки для другой платформы с помощью команды go build.

      Если вы не используете систему Windows, создайте бинарный файл windows для app, установив для переменной среды GOOS значение windows при запуске команды go build:

      Теперь вы можете вывести файлы в вашей текущей директории:

      Вывод списка файлов в директории теперь показывает, что в директории проекта есть исполняемый файл app.exe для Windows:

      Output

      app app.exe main.go path.go windows.go

      Используя команду file, вы можете получить дополнительную информацию об этом файле, подтвердив его сборку:

      Вы получите следующий результат:

      Output

      app.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows

      Также вы можете задать значение для одной или обеих переменных среды во время сборки. Запустите следующую команду:

      • GOOS=linux GOARCH=ppc64 go build

      Теперь ваш исполняемый файл app будет заменен файлом для другой архитектуры. Запустите команду file для этого бинарного файла:

      Вывод будет выглядеть следующим образом:

      app: ELF 64-bit MSB executable, 64-bit PowerPC or cisco 7500, version 1 (SYSV), statically linked, not stripped
      

      Задав значения для ваших локальных переменных среды GOOS и GOARCH, вы можете выполнить сборку бинарных файлов для любой из совместимых с Go платформ без сложной конфигурации или настройки. Далее вы будете использовать соглашения для имен файлов, чтобы четко организовать ваши файлы, и выполнять сборку для конкретных платформ автоматически без маркеров для сборки.

      Использование суффиксов файлов имен GOOS и GOARCH

      Как вы уже видели ранее, в стандартной библиотеке Go активно используются маркеры сборки для упрощения кода, что позволяет разделять реализации для разных платформ в разных файлах. Когда вы открывали файл os/path_unix.go, там был маркер сборки, который содержал список всех возможных комбинаций, рассматриваемых в качестве Unix-платформ. Однако в файле os/path_windows.go отсутствуют маркеры для сборки, поскольку суффикса в имени файла достаточно, чтобы Go мог понять, для какой платформы предназначен этот файл.

      Давайте рассмотрим синтаксис этого элемента. При присвоении имени файла .go вы можете добавить GOOS и GOARCH в качестве суффиксов к имени файла в этом порядке, отделяя значения нижним подчеркиванием (_). Если у вас есть файл Go с именем filename.go, вы можете указать ОС и архитектуру, изменив имя файла на filename_GOOS_GOARCH.go. Например, если вы хотите скомпилировать его для Windows с 64-битной архитектурой ARM, вы должны использовать имя файла filename_windows_arm64.go. Такое соглашение о наименованиях помогает поддерживать код в организованном виде.

      Обновите вашу программу для использования суффиксов имени файла вместо маркеров сборки. Во-первых, переименуйте файл path.go и windows.go для использования соглашения, используемого в пакете os:

      • mv path.go path_unix.go
      • mv windows.go path_windows.go

      После изменения имен двух файлов вы можете удалить маркер сборки, который вы добавили в path_windows.go:

      Удалите // +build windows, чтобы ваш файл выглядел следующим образом:

      path_windows.go

      package main
      
      const PathSeparator = "\"
      

      Сохраните и закройте файл.

      Поскольку unix — это недействительное значение для GOOS, суффикс _unix.go не будет иметь значение для компилятора Go. Однако он передает предполагаемое назначение файла. Как и в файле os/path_unix.go, ваш файл path_unix.go все еще требует использования маркеров для сборки, поэтому этот файл будет сохранен без изменений.

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

      Заключение

      Возможность генерации бинарных файлов для различных платформ, не требующих зависимостей, является очень ценной функцией цепочки инструментов Go. В этом обучающем руководстве вы использовали эту возможность, добавляя маркеры сборки и суффиксы для имен файлов, чтобы пометить определенные сниппеты кода, которые будут компилироваться только для определенных архитектур. Вы создали собственную платформо-зависимую программу, а затем выполняли манипуляции с переменными среды GOOS и GOARCH для получения бинарных файлов для других платформ, помимо вашей текущей платформы. Это очень ценная возможность, поскольку очень часто используется процесс непрерывной интеграции, который автоматически запускается с помощью этих переменных среды для сборки бинарных файлов для всех платформ.

      Для дальнейшего знакомства с go build вы можете ознакомиться с нашим руководством по настройке бинарных файлов в Go с помощью маркеров сборки. Если вы хотите узнать больше о языке программирования Go в целом, ознакомьтесь с нашей серией статей о программировании на языке Go.



      Source link