Поднимите свою игру Go CLI на новый уровень: поделитесь своим инструментом со всем миром на Homebrew

Введение

В этом простом для понимания сообщении в блоге будут объяснены некоторые основные примеры создания интерфейса командной строки (CLI) с использованием Golang и пакета Cobra. После этого я помогу вам подготовить пакет и опубликовать его на Homebrew для использования другими.

Кобра Либ

Cobra — это популярная библиотека на Golang, которая предоставляет простой интерфейс для создания приложений с интерфейсом командной строки (CLI). Его создал Стив Франсиа, тот же человек, что создал генератор статических сайтов Hugo и библиотеку управления конфигурацией Viper.

Cobra предлагает простой способ создания надежных и хорошо структурированных приложений CLI с поддержкой подкоманд, флагов и анализа аргументов. Это также упрощает создание справочной документации и сценариев автозавершения для различных оболочек.

Некоторые ключевые особенности библиотеки Cobra включают в себя:

  1. Обработка команд: легко определяйте команды, подкоманды и их отдельные действия. Cobra предоставляет иерархическую структуру команд, которая позволяет создавать сложные приложения CLI с прозрачной организацией.
  2. Флаги и аргументы: Cobra имеет встроенную поддержку разбора флагов (опций), а аргументы передаются командам. Он обрабатывает как глобальные, так и локальные флаги, что упрощает управление различными параметрами для разных команд.
  3. Управление конфигурацией: Cobra легко интегрируется с библиотекой Viper, позволяя вам управлять конфигурацией вашего приложения с помощью различных источников, таких как файлы конфигурации, переменные среды и флаги командной строки.
  4. Автоматически генерируемые сообщения справки и использования: Cobra автоматически создает сообщения справки и использования для вашего приложения CLI на основе определенных вами команд, флагов и описаний.
  5. Автозаполнение: Cobra поддерживает создание сценариев автозаполнения оболочки для Bash, Zsh, Fish и PowerShell, упрощая пользователям взаимодействие с вашим приложением CLI.

Давайте начнем

Создание простого интерфейса командной строки hello world

Сначала создайте новый модуль Go.

go mod init mycli

Затем установите библиотеку Cobra:

go get -u github.com/spf13/cobra

Теперь создайте файл с именем main.go и добавьте следующий код:

package main

import (
 "fmt"
 "github.com/spf13/cobra"
 "os"
)

func main() {
 rootCmd := &cobra.Command{
  Use:   "greet",
  Short: "A CLI to demonstrate Cobra usage",
  Long:  `This CLI demonstrates how to create a CLI application with Cobra.`,
  Args:  cobra.MinimumNArgs(1),
  Run: func(cmd *cobra.Command, args []string) {
   fmt.Printf("Greetings, %s!\n", args[1])
  },
 }

 helloCmd := &cobra.Command{
  Use:   "hello",
  Short: "Prints a 'Hello, world!' message",
  Run: func(cmd *cobra.Command, args []string) {
   fmt.Println("Hello, world!")
  },
 }

 rootCmd.AddCommand(helloCmd)

 if err := rootCmd.Execute(); err != nil {
  fmt.Println(err)
  os.Exit(1)
 }
}

В этом коде мы создаем rootCmd с помощью команды greet и helloCmd с помощью команды greet hello. Мы добавляем helloCmd в качестве подкоманды к rootCmd, используя метод AddCommand. Наконец, мы выполняем rootCmd и обрабатываем все ошибки.

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

go build -o mycli                                                                                                                                                                        ░▒▓ ✔  vidispine_cv  
./mycli "Your Name" 
./mycli hello

Первая команда поприветствует вас фразой «Приветствую вас, ваше имя!». Вторая команда напечатает «Hello, world!».

Создание простого интерфейса командной строки для создания файлов и папок

Это приложение имеет единственную команду create, которая принимает два аргумента: имя папки и имя файла.

Во-первых, убедитесь, что вы создали новый модуль Go и установили библиотеку Cobra, как показано в предыдущем примере.

Создайте файл с именем main.go и добавьте следующий код:

package main

import (
 "fmt"
 "github.com/spf13/cobra"
 "io/ioutil"
 "os"
)

func main() {
 rootCmd := &cobra.Command{
  Use:   "create",
  Short: "A CLI to create a folder and a text file within it",
  Long: `This CLI demonstrates how to create a CLI application with Cobra
that creates a folder and a text file within that folder.`,
  Args: cobra.ExactArgs(2),
  Run: func(cmd *cobra.Command, args []string) {
   folderName := args[0]
   fileName := args[1]

   err := os.MkdirAll(folderName, 0755)
   if err != nil {
    fmt.Printf("Error creating folder: %v\n", err)
    os.Exit(1)
   }

   filePath := fmt.Sprintf("%s/%s", folderName, fileName)
   err = ioutil.WriteFile(filePath, []byte("Hello, world!\n"), 0644)
   if err != nil {
    fmt.Printf("Error creating file: %v\n", err)
    os.Exit(1)
   }

   fmt.Printf("Created folder '%s' and file '%s' within it\n", folderName, fileName)
  },
 }

 if err := rootCmd.Execute(); err != nil {
  fmt.Println(err)
  os.Exit(1)
 }
}

В этом коде мы создаем rootCmd с помощью команды create. Функция Run принимает два аргумента: имя папки и имя файла. Он создает папку, используя os.MkdirAll, и пишет «Hello, world!» сообщение в указанный файл с помощью ioutil.WriteFile.

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

go build -o foldercreator
./foldercreator "myfolder" "myfile.txt"

Эта команда создаст папку с именем myfolder и файл с именем myfile.txt внутри нее, содержащий сообщение «Привет, мир!».

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

Чтобы создать интерфейс командной строки с Golang и Cobra, в котором перечисляются службы, потребляющие больше всего памяти, вы можете использовать команду ps в системах на базе Unix (Linux и macOS), чтобы получить список процессов, а затем проанализировать выходные данные, чтобы найти службы с наибольшим потреблением памяти. использование памяти.

Обратите внимание, что этот пример будет работать только в системах на базе Unix (Linux и macOS), а не в Windows.

Во-первых, убедитесь, что вы создали новый модуль Go и установили библиотеку Cobra, как показано в предыдущих примерах.

Создайте файл с именем main.go и добавьте следующий код:

package main

import (
 "fmt"
 "github.com/spf13/cobra"
 "os"
 "os/exec"
 "sort"
 "strconv"
 "strings"
)

type Process struct {
 PID  int
 Comm string
 RSS  int
}

func main() {
 rootCmd := &cobra.Command{
  Use:   "memtop",
  Short: "A CLI to list the most memory-consuming services",
  Long: `This CLI demonstrates how to create a CLI application with Cobra
that lists the most memory-consuming services on Unix-based systems.`,
  Run: func(cmd *cobra.Command, args []string) {
   psCmd := exec.Command("ps", "-eo", "pid,comm,rss")
   output, err := psCmd.Output()
   if err != nil {
    fmt.Printf("Error executing ps command: %v\n", err)
    os.Exit(1)
   }

   processes := parsePsOutput(string(output))
   sort.Slice(processes, func(i, j int) bool {
    return processes[i].RSS > processes[j].RSS
   })

   fmt.Printf("%-10s %-30s %s\n", "PID", "Command", "RSS (KB)")
   for _, p := range processes {
    fmt.Printf("%-10d %-30s %d\n", p.PID, p.Comm, p.RSS)
   }
  },
 }

 if err := rootCmd.Execute(); err != nil {
  fmt.Println(err)
  os.Exit(1)
 }
}

func parsePsOutput(output string) []Process {
 lines := strings.Split(output, "\n")
 processes := make([]Process, 0, len(lines)-1)

 for i, line := range lines {
  if i == 0 {
   continue // Skip header line
  }

  fields := strings.Fields(line)
  if len(fields) != 3 {
   continue
  }

  pid, _ := strconv.Atoi(fields[0])
  rss, _ := strconv.Atoi(fields[2])

  processes = append(processes, Process{
   PID:  pid,
   Comm: fields[1],
   RSS:  rss,
  })
 }

 return processes
}

В этом коде мы создаем rootCmd с помощью команды memtop. Функция Run выполняет команду ps с определенными флагами, чтобы получить список процессов с PID, командой и RSS (размер резидентного набора). Затем выходные данные анализируются и сортируются по использованию памяти в порядке убывания.

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

go build -o memtop
./memtop

Эта команда отобразит наиболее потребляющие память службы в вашей системе на базе Unix.

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

Создание настраиваемого интерфейса командной строки повторителя строк с флагами

package main

import (
 "fmt"
 "github.com/spf13/cobra"
 "os"
 "strings"
)

func main() {
 var count int
 var separator string

 rootCmd := &cobra.Command{
  Use:   "repeat",
  Short: "A CLI to repeat a string",
  Long: `This CLI demonstrates how to create a CLI application with Cobra
that takes a string and repeats it a specified number of times.`,
  Args: cobra.ExactArgs(1),
  Run: func(cmd *cobra.Command, args []string) {
   input := args[0]
   result := strings.Join(make([]string, count), input)
   if count > 0 {
    result = input + separator + result
   }
   fmt.Println(result)
  },
 }

 rootCmd.Flags().IntVarP(&count, "count", "c", 1, "number of times to repeat the string")
 rootCmd.Flags().StringVarP(&separator, "separator", "s", "", "separator between repeated strings")

 if err := rootCmd.Execute(); err != nil {
  fmt.Println(err)
  os.Exit(1)
 }
}

В этом коде мы создаем rootCmd с помощью команды repeat. Функция Run берет строку и повторяет ее на основе предоставленного флага count. Мы также добавляем флаг separator, чтобы указать разделитель между повторяющимися строками.

Создайте и запустите приложение CLI

go build -o repeatcli
./repeatcli --help

Эта команда отобразит текст справки для CLI!

./repeatcli "Hello, world!" --count 3 --separator ", "

Эта команда повторит входную строку «Hello, world!» три раза с запятой и пробелом в качестве разделителя, что приводит к следующему результату:

Hello, world!, Hello, world!, Hello, world!

Сделайте ваш CLI доступным для других

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

  1. Здание
  2. Распространение

Создание CLI-приложения

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

  1. Сборка бинарника:

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

Например, для сборки для macOS (amd64), Windows (amd64) и Linux (amd64) можно использовать следующие команды:

# macOS (amd64)
GOOS=darwin GOARCH=amd64 go build -o mycli-mac

# Windows (amd64)
GOOS=windows GOARCH=amd64 go build -o mycli-windows.exe

# Linux (amd64)
GOOS=linux GOARCH=amd64 go build -o mycli-linux

Эти команды создадут три отдельных бинарных файла для macOS, Windows и Linux.

Распространение приложения CLI

Чтобы опубликовать пакет в Homebrew, вы должны создать формулу Homebrew и отправить ее на кран Homebrew. Краны Homebrew — это репозитории, содержащие формулы, которые пользователи могут установить с помощью команды brew tap. Вы можете добавить свою формулу в основной репозиторий Homebrew или создать свой собственный кран.

Вот пошаговое руководство о том, как создать и опубликовать пакет в Homebrew, используя собственный кран:

  1. Создайте новый репозиторий GitHub с именем homebrew-tap: замените tap на описательное имя для вашего крана, например homebrew-mytools для коллекции ваших инструментов.
  2. Создайте новый файл в репозитории: Назовите файл в формате your-tool.rb, где your-tool — это имя вашего приложения CLI. Этот файл представляет собой формулу, описывающую, как установить ваше приложение с помощью Homebrew.
  3. Добавьте содержимое формулы: напишите формулу для своего приложения CLI. Вот пример шаблона:
class YourTool < Formula
  desc "A short description of your CLI application"
  homepage "https://github.com/YOUR_USERNAME/your-tool"
  url "https://github.com/YOUR_USERNAME/your-tool/releases/download/v1.0.0/your-tool-mac.tar.gz"
  sha256 "YOUR_MAC_BINARY_SHA256"
  version "1.0.0"
  license "MIT"

  def install
    bin.install "your-tool"
  end

  test do
    system "#{bin}/your-tool", "--version"
  end
end

Замените YourTool, YOUR_USERNAME и другие заполнители соответствующими значениями для вашего приложения CLI. Обновите url, чтобы он указывал на двоичный файл macOS в вашем выпуске, и замените его YOUR_MAC_BINARY_SHA256 хэшем SHA256 двоичного файла macOS. Вычислить хэш можно с помощью команды shasum:

shasum -a 256 your-tool-mac.tar.gz

4. Зафиксируйте и отправьте изменения: сохраните файл формулы и отправьте его в репозиторий GitHub.

5. Сообщите пользователям, как установить ваше приложение CLI: теперь пользователи могут установить ваше приложение CLI с помощью Homebrew, выполнив:

brew tap YOUR_USERNAME/tap
brew install your-tool

Замените YOUR_USERNAME и your-tool своим именем пользователя GitHub и именем вашего приложения CLI соответственно.

Следуя этим шагам, вы создадите кран Homebrew и опубликуете в нем свой пакет, что упростит пользователям установку и обновление вашего приложения CLI в macOS.

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