Twój pierwszy program wiersza poleceń w Go

Fragment „Zaawansowane aplikacje wiersza poleceń w Go” autorstwa Ricardo Gerardi

Niezależnie od tego, czy chcesz zautomatyzować zadanie, analizować dane, analizować dzienniki, rozmawiać z usługami sieciowymi czy spełniać inne wymagania, napisanie własnego narzędzia wiersza poleceń może być najszybszym — i być może najzabawniejszym — sposobem osiągnięcia celu. Go to nowoczesny język programowania, który łączy w sobie niezawodność języków kompilowanych z łatwością użycia i szybkością języków dynamicznie typowanych. Sprawia, że ​​pisanie wieloplatformowych aplikacji wiersza poleceń jest bardziej przystępne, zapewniając jednocześnie funkcje wymagane do zapewnienia, że ​​te narzędzia są dobrze zaprojektowane i przetestowane.

Zanim zagłębisz się w bardziej złożone programy, które odczytują i zapisują pliki, analizują pliki danych i komunikują się przez sieci, utworzysz program liczący słowa, który podpowie ci, jak zbudować i przetestować aplikację wiersza poleceń za pomocą Go. Zaczniesz od podstawowej implementacji, dodasz kilka funkcji i po drodze będziesz poznawać rozwój oparty na testach. Kiedy skończysz, będziesz mieć funkcjonalny program do liczenia słów i lepsze zrozumienie, jak tworzyć bardziej złożone aplikacje.

W tej książce będziesz rozwijać inne aplikacje CLI, aby poznać bardziej zaawansowane koncepcje.

Budowanie podstawowego licznika słów

Stwórzmy narzędzie, które zlicza liczbę słów lub wierszy podanych jako dane wejściowe przy użyciu połączenia standardowego wejścia(STDIN). Domyślnie to narzędzie zliczy liczbę słów, chyba że otrzyma -l flag, w takim przypadku zamiast tego policzy liczbę wierszy.

Zaczniemy od stworzenia podstawowej implementacji. Ta wersja odczytuje dane z STDIN i wyświetla liczbę słów. Ostatecznie dodamy więcej funkcji, ale ta początkowa wersja pozwoli Ci oswoić się z kodem aplikacji wiersza poleceń opartej na Go.

Zanim zagłębisz się w pisanie kodu licznika słów, skonfigurujmy katalog projektu. W swoim katalogu domowym utwórz podkatalog pragprog.com/rggo/first- Program/wc i przejdź do niego:

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

Programy Go składają się z pakietów. Pakiet składa się z jednego lub większej liczby plików kodu źródłowego Go z kodem, który można połączyć w wykonywalne programy lub biblioteki.

Począwszy od wersji Go 1.11, możesz łączyć jeden lub więcej pakietów w moduły Go. Moduły to nowy standard Go służący do grupowania powiązanych pakietów w jedną jednostkę, którą można razem wersjonować. Moduły umożliwiają spójne zarządzanie zależnościami dla aplikacji Go. Więcej informacji na temat modułów Go można znaleźć na oficjalnej stronie wiki.

Zainicjuj nowy moduł Go dla swojego projektu:

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

Tworzysz program wykonywalny w Go, definiując pakiet o nazwie main, który zawiera funkcję o nazwie main(). Funkcja ta nie przyjmuje żadnych argumentów i nie zwraca żadnych wartości. Służy jako punkt wejścia dla Twojego programu.

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

Chociaż nie jest to wymagane, zgodnie z konwencją, pakiet główny jest zwykle zdefiniowany w pliku o nazwie main.go. Tę konwencję będziesz stosować w całej książce.

Ścieżka pliku przykładowego kodu

Dla zwięzłości przykładowa ścieżka kodu pomija katalog główny $HOME/pragprog.com/rggo. Na przykład w poniższym przykładzie kodu ścieżka kodu zaczyna się od firstProgram/wc.

Utwórz plik main.go za pomocą swojego ulubionego edytora tekstu. Dodaj główną definicję pakietu na górę pliku w następujący sposób:

package main

Następnie dodaj sekcję importu, aby pobrać biblioteki, których będziesz używać do odczytywania danych z STDIN i drukowania wyników.

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

W przypadku tego narzędzia importujesz pakiet bufio do czytania tekstu, pakiet fmt do drukowania sformatowanych wyników, pakiet io udostępniający interfejs io.Reader i pakiet os umożliwiający korzystanie z zasobów systemu operacyjnego.

Twój licznik słów będzie miał dwie funkcje: main() i count(). Funkcja main() jest punktem startowym programu. Wszystkie programy Go, które zostaną skompilowane do plików wykonywalnych, wymagają tej funkcji. Utwórz tę funkcję, dodając następujący kod do pliku main.go. Ta funkcja wywoła funkcję count() i wydrukuje wartość zwracaną przez tę funkcję za pomocą 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))
}

Następnie zdefiniuj funkcję count(), która wykona faktyczne zliczenie słów. Ta funkcja otrzymuje pojedynczy argument wejściowy: io.Reader interfejs. Więcej o interfejsach Go dowiesz się w Rozdziale 2, „Interakcja z użytkownikami”. Na razie pomyśl o io.Reader jak o dowolnym typie Go, z którego możesz odczytać dane. W tym wypadku funkcja otrzyma do przetworzenia zawartość 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
}

Funkcja count() wykorzystuje funkcję NewScanner() z pakietu bufio do utworzenia nowego skanera. Skaner to wygodny sposób odczytywania danych rozdzielonych spacjami lub nowymi liniami. Domyślnie skaner odczytuje linie danych, dlatego instruujemy skaner, aby zamiast tego czytał słowa, ustawiając funkcję Split() skanera na bufio.ScanWords(). Następnie definiujemy zmienną wc, która przechowuje liczbę słów i zwiększa ją, przeglądając każdy token za pomocą funkcji scanner.Scan() i za każdym razem dodając 1 do licznika. Następnie zwracamy liczbę słów.

W tym przykładzie dla uproszczenia ignorujemy błąd, który może zostać wygenerowany podczas skanowania. W swoim kodzie zawsze sprawdzaj błędy. Więcej informacji na temat postępowania z błędami w kontekście narzędzia wiersza poleceń można znaleźć w artykule „Tworzenie narzędzia wiersza poleceń do wykonania”.

Zakończyłeś podstawową implementację narzędzia do liczenia słów. Zapisz plik main.go ze swoimi zmianami. Następnie napiszesz testy, aby upewnić się, że implementacja działa tak, jak tego oczekujesz.

Testowanie podstawowego licznika słów

Go umożliwia automatyczne testowanie kodu bez konieczności stosowania zewnętrznych narzędzi i frameworków. Z całej książki dowiesz się więcej o tym, jak testować aplikacje wiersza poleceń. W tej chwili napiszmy podstawowy test licznika słów, aby upewnić się, że poprawnie zlicza on słowa na podanych danych wejściowych.

Utwórz plik o nazwie main_test.go w tym samym katalogu, w którym znajduje się plik main.go. Dołącz następującą treść, która definiuje funkcję testującą, która testuje funkcję count(), którą już zdefiniowałeś w programie głównym:

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)
  }
}

Ten plik testowy zawiera pojedynczy test o nazwie TestCountWords(). W tym teście tworzymy nowy bufor bajtów z ciągu zawierającego cztery słowa i przekazujemy bufor do funkcji count(). Jeśli ta funkcja zwróci cokolwiek innego niż 4, test nie zakończy się pomyślnie i zgłosimy błąd, który pokaże, czego się spodziewaliśmy i co faktycznie otrzymaliśmy.

Aby wykonać test, użyj narzędzia go test w następujący sposób:

$ 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

Test kończy się pomyślnie, więc możesz skompilować program za pomocą go build. Więcej informacji na temat różnych opcji, których możesz użyć do tworzenia programów w Go, znajdziesz w rozdziale 11, „Dystrybucja narzędzia”. Na razie zbuduj narzędzie wiersza poleceń w następujący sposób:

$ go build

Spowoduje to utworzenie pliku wykonywalnego wc w bieżącym katalogu:

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

Przetestuj program, przekazując mu ciąg wejściowy:

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

Program działa zgodnie z oczekiwaniami. Dodajmy do tego narzędzia możliwość zliczania linii.

Mamy nadzieję, że podobał Ci się ten fragment. Możesz kupić książkę bezpośrednio w The Pragmatic Bookshelf. Skorzystaj z naszej wiosennej wyprzedaży i zaoszczędź 50 procent na e-booku z kodem TOOLS2023 do północy czasu wschodniego, 16 maja 2023 r.