Недавно я создал порт на языке Go для инструмента cli jo.



Команда jo - это инструмент для простого создания JSON. Он может быть вложенным и использоваться для тела запроса команды curl. На самом деле я помню день, когда он был опубликован, и удивился, почему никому не пришла в голову эта идея раньше. Я заглянул в код и отправил несколько небольших запросов на включение, но почему-то не использовал их несколько лет. Я хотел бы выразить уважение к оригинальному инструменту jo и идее автора, за то, что он стал доступным для различных операционных систем.



Недавно заинтересовался портированием полезных cli-инструментов на язык Go. Я думаю, что в наши дни язык - лучший выбор для создания инструментов cli. Популярность по-прежнему быстро растет, поэтому мы можем ожидать, что многие разработчики установят с нуля и внесут свой вклад в сообщество OSS (честно говоря, я люблю Rust за его безопасность памяти и особенности. Но трудно ожидать такого большого количества разработчиков. Я выбираю Rust или Haskell, если язык подходит для достижения того, что я хочу).

 $ gojo foo=bar qux=quux
{"foo":"bar","qux":"quux"}
 $ gojo -p foo=bar qux=quux
{
  "foo": "bar",
  "qux": "quux"
}
 $ gojo -a foo bar baz
["foo","bar","baz"]
 $ seq 10 | gojo -a
[1,2,3,4,5,6,7,8,9,10]
 $ gojo -p foo=$(gojo bar=$(gojo baz=100))
{
  "foo": {
    "bar": {
      "baz": 100
    }
  }
}
 $ gojo -p res[foo][][id]=10 res[foo][][id]=20 res[cnt]=2
{
  "res": {
    "foo": [
      {
        "id": 10
      },
      {
        "id": 20
      }
    ],
    "cnt": 2
  }
}

Я реализовал gojo, используя тестовые примеры jo в качестве справки. Особенно мне понравилось реализовывать глубоко вложенные ключи с помощью рекурсий. Другой язык ведет к другой красивой структуре кода, поэтому всегда интересно реализовать хорошо известный инструмент на другом языке.

В исходном инструменте jo есть много опций, позволяющих изменить поведение при угадывании типов. Я еще не реализовал многие из них, потому что до сих пор не понимаю, что для этого инструмента требуется так много опций. Мне не понравился синтаксис чтения содержимого файлов; jo [email protected], потому что это может противоречить философии UNIX. Но я наконец реализовал синтаксис в последней версии, потому что gojo [email protected], безусловно, легче набирать, чем gojo foo="$(<sample.txt)", и на самом деле трудно написать правильную соответствующую команду, когда целевой файл является двоичным файлом.

Я использую язык Go более четырех лет и создал множество небольших cli-инструментов. Я сделал много ошибок в своем опыте работы с языком Go. Непроверяемый код, инструмент cli только с основным пакетом, меньшая тестируемость из-за отсутствия макетов клиента api и т. Д.

Когда я создаю инструмент cli с помощью Go, я с самого начала создаю повторно используемый пакет в верхнем каталоге репозитория. Этот пакет не должен зависеть от флагов командной строки (т. Е. os.Args) и потоков вывода / ввода (т. Е. os.Stdout, os.Stderr и os.Stdin). При тщательном создании пакет может быть импортирован и достаточно настраиваемым для вывода в любые файлы или использования в качестве ответа HTTP-сервера. Затем я создаю каталог cli, который анализирует флаги командной строки и вводит потоки. Я определяю одну экспортируемую функцию cli.Run, которая возвращает код выхода. Пакет cli может зависеть от os.Args и потоков, но он по-прежнему должен быть тестируемым (тестовые флаги, потоки и код выхода), и я никогда не вызываю os.Exit в этом пакете. Код основного пакета func main() { os.Exit(cli.Run()) } и все.

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