Ваша первая программа командной строки в Go

Отрывок из Мощные приложения командной строки в Go Рикардо Херарди

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

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

На протяжении всей книги вы будете разрабатывать другие CLI-приложения, чтобы исследовать более продвинутые концепции.

Создание базового счетчика слов

Давайте создадим инструмент, который подсчитывает количество слов или строк, предоставленных в качестве входных данных, используя соединение стандартный ввод(STDIN). По умолчанию этот инструмент подсчитывает количество слов, если только он не получает -l flag, и в этом случае вместо этого он подсчитывает количество строк.

Мы начнем с создания базовой реализации. Эта версия считывает данные из STDIN и отображает количество слов. Со временем мы добавим больше функций, но эта начальная версия позволит вам освоиться с кодом приложения командной строки на основе Go.

Прежде чем вы погрузитесь в написание кода для счетчика слов, давайте настроим каталог проекта. В своем домашнем каталоге создайте подкаталог pragprog.com/rggo/first- Program/wc и перейдите в него:

$ mkdir -p $HOME/pragprog.com/rggo/firstProgram/wc
$ cd $HOME/pragprog.com/rggo/firstProgram/wc

Программы Go состоят из пакетов. Пакет состоит из одного или нескольких файлов исходного кода Go с кодом, который можно объединить в исполняемые программы или библиотеки.

Начиная с Go 1.11, вы можете объединять один или несколько пакетов в модули Go. Модули — это новый стандарт Go для группировки связанных пакетов в единое целое, версии которого можно объединять. Модули обеспечивают согласованное управление зависимостями для ваших приложений Go. Для получения дополнительной информации о модулях Go посетите официальную вики-страницу.

Инициализируйте новый модуль Go для вашего проекта:

$ go mod init pragprog.com/rggo/firstProgram/wc
go: creating new go.mod: module pragprog.com/rggo/firstProgram/wc

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

package main
func main() {
«main contents»
}

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

Путь к файлу примера кода

Для краткости в пути примера кода отсутствует корневой каталог $HOME/pragprog.com/rggo.. Например, в следующем примере кода путь кода начинается с firstProgram/wc.

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

package main

Затем добавьте раздел импорта, чтобы добавить библиотеки, которые вы будете использовать для чтения данных из STDIN и распечатки результатов.

import ( 
  "bufio" 
  "fmt"
  "io"
  "os"
)

Для этого инструмента вы импортируете пакет bufio для чтения текста, пакет fmt для печати форматированного вывода, пакет io, который предоставляет интерфейс io.Reader, и пакет os, чтобы вы могли использовать ресурсы операционной системы.

Ваш счетчик слов будет иметь две функции: main() и count(). Функция main() является отправной точкой программы. Эта функция требуется для всех программ Go, которые будут скомпилированы в исполняемые файлы. Создайте эту функцию, добавив следующий код в файл main.go. Эта функция вызовет функцию count() и распечатает возвращаемое значение этой функции, используя fmt.Println() function:

func main() {
  // Calling the count function to count the number of words
  // received from the Standard Input and printing it out
  fmt.Println(count(os.Stdin))
}

Затем определите функцию count(), которая будет выполнять фактический подсчет слов. Эта функция получает единственный входной аргумент: io.Reader интерфейс. Вы узнаете больше об интерфейсах Go в главе 2, «Взаимодействие с вашими пользователями». На данный момент думайте о io.Reader как о любом типе Go, из которого вы можете считывать данные. В этом случае функция получит содержимое STDIN для обработки.

func count(r io.Reader) int {
  // A scanner is used to read text from a Reader (such as files)
  scanner := bufio.NewScanner(r)

  // Define the scanner split type to words (default is split by lines)
  scanner.Split(bufio.ScanWords)

  // Defining a counter
  wc := 0

  // For every word scanned, increment the counter
  for scanner.Scan() { 
    wc++
  }

  // Return the total
  return wc
}

Функция count() использует функцию NewScanner() из пакета bufio для создания нового сканера. Сканер — это удобный способ чтения данных, разделенных пробелами или новыми строками. По умолчанию сканер считывает строки данных, поэтому мы даем указание сканеру читать слова, установив для функции Split() сканера значение bufio.ScanWords(). Затем мы определяем переменную wc для хранения количества слов и увеличиваем его, перебирая каждый токен с помощью функции scanner.Scan() и каждый раз добавляя 1 к счетчику. Затем мы возвращаем количество слов.

В этом примере для простоты мы игнорируем ошибку, которая может возникнуть во время сканирования. В своем коде всегда проверяйте наличие ошибок. Вы узнаете больше о работе с ошибками в контексте инструмента командной строки в разделе «Создание начального инструмента командной строки To-Do».

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

Тестирование базового счетчика слов

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

Создайте файл с именем main_test.go в том же каталоге, что и ваш файл main.go. Включите следующее содержимое, определяющее функцию тестирования, которая проверяет функцию count(), которую вы уже определили в основной программе:

package main

import ( 
  "bytes" 
  "testing"
)

// TestCountWords tests the count function set to count words

func TestCountWords(t *testing.T) {
  b := bytes.NewBufferString("word1 word2 word3 word4\n")
  exp := 4
  res := count(b)
  if res != exp {
    t.Errorf("Expected %d, got %d instead.\n", exp, res)
  }
}

Этот тестовый файл содержит один тест под названием TestCountWords(). В этом тесте мы создаем новый буфер байтов из строки, содержащей четыре слова, и передаем буфер в функцию count(). Если эта функция возвращает что-либо, кроме 4, тест не проходит, и мы выдаем ошибку, которая показывает, что мы ожидали и что мы вместо этого получили на самом деле.

Чтобы выполнить тест, используйте инструмент go test следующим образом:

$ ls
go.mod main.go main_test.go
$ go test -v
=== RUN TestCountWords
--- PASS: TestCountWords (0.00s) PASS
ok pragprog.com/rggo/firstProgram/wc 0.002s

Тест пройден, поэтому вы можете скомпилировать программу с помощью go build. Вы узнаете больше о различных вариантах, которые можно использовать для создания программ Go, в главе 11 «Распространение вашего инструмента». А пока создайте свой инструмент командной строки следующим образом:

$ go build

Это создает исполняемый файл wc в текущем каталоге:

$ ls
go.mod main.go main_test.go wc

Протестируйте программу, передав ей входную строку:

$ echo "My first command line tool with Go" | ./wc
7

Программа работает как положено. Давайте добавим в этот инструмент возможность считать строки.

Надеемся, вам понравился этот отрывок. Вы можете приобрести книгу прямо на The Pragmatic Bookshelf. Воспользуйтесь нашей весенней распродажей и сэкономьте 50% на электронной книге с кодом TOOLS2023 до полуночи по восточному времени 16 мая 2023 г.