Erstellen Sie ein CLI-Programm mit Go

Guanhui
Freigeben: 2020-06-13 09:03:28
nach vorne
3582 Leute haben es durchsucht

Erstellen Sie ein CLI-Programm mit Go

Sie haben vielleicht immer wieder die Go-Syntax geübt, aber wenn Sie nicht selbst eine Anwendung erstellt haben, haben Sie noch nicht das wirkliche Gefühl erlebt, Anwendungen in Go zu schreiben.

In diesem Blog-Beitrag erstellen wir eine CLI-Anwendung in Go, nennen wir sie go-grab-xkcd. Die Anwendung ruft Comics von XKCD ab und stellt sie über Befehlszeilenparameter für Sie bereit.

Wir werden die gesamte Anwendung nur unter Verwendung der Go-Standardbibliothek erstellen, ohne externe Abhängigkeiten zu verwenden.

Die Idee dieser Anwendung mag etwas albern erscheinen, aber der Zweck besteht darin, das Schreiben von Code (sozusagen) auf Produktionsebene zu üben in Go, ohne zu versuchen, von Google erfasst zu werden.

Am Ende gibt es einen Bonus

Hinweis: In diesem Artikel wird davon ausgegangen, dass der Leser bereits mit der Syntax und Terminologie von Go sowie zwischen Anfänger und Fortgeschrittenen vertraut ist .

Lass uns zuerst die App ausführen, bevor wir fortfahren

$ go-grab-xkcd --help
Usage of go-grab-xkcd:
  -n int
        Comic number to fetch (default latest)
  -o string
        Print output in format: text/json (default "text")
  -s    Save image to current directory
  -t int
        Client timeout in seconds (default 30)
$ go-grab-xkcd -n 323
Title: Ballmer Peak
Comic No: 323
Date: 1-10-2007
Description: Apple uses automated schnapps IVs.
Image: https://imgs.xkcd.com/comics/ballmer_peak.png
$ go-grab-xkcd -n 323 -o json
{
  "title": "Ballmer Peak",
  "number": 323,
  "date": "1-10-2007",
  "description": "Apple uses automated schnapps IVs.",
  "image": "https://imgs.xkcd.com/comics/ballmer_peak.png"
}
Nach dem Login kopieren

Sie können andere Optionen ausprobieren, indem Sie die App herunterladen und auf Ihrem Computer ausführen.

Am Ende dieses Tutorials sind Sie wird mit den folgenden Themen vertraut sein:

Befehlszeilenparameter empfangen

Konvertieren zwischen JSON- und Go-Strukturen

API-Aufrufe durchführen

Dateien erstellen (herunterladen und aus dem Netzwerk speichern)

String-Operationen

Das Folgende ist die Projektstruktur

$ tree go-grab-xkcd
go-grab-xkcd
├── client
│   └── xkcd.go
└── model
    └── comic.go
├── main.go
└── go.mod
go.mod - Go Modules file used in Go for package management
main.go - Main entrypoint of the application
comic.go - Go representation of the data as a struct and operations on it
xkcd.go - xkcd client for making HTTP calls to the API, parsing response and saving to disk
Nach dem Login kopieren

1: Initialisieren Sie das Projekt

Erstellen Sie eine go.mod-Datei -

$ go mod init
Nach dem Login kopieren

Dies hilft Ihnen bei der Paketverwaltung (denken Sie an package.json-Dateien in JS).

2: xkcd-API

xkcd ist fantastisch und Sie benötigen keine Registrierung oder Zugriffsschlüssel, um ihre API zu verwenden. Öffnen Sie die xkcd-API „Dokumentation“ und Sie finden zwei Endpunkte –

http://xkcd.com/info.0.json – Holen Sie sich die neuesten Comics

http://xkcd. com/614/info.0.json – Erhalten Sie den angegebenen Comic nach Comic-Nummer

Das Folgende ist die JSON-Antwort für diese Endpunkte –

{
  "num": 2311,
  "month": "5",
  "day": "25",
  "year": "2020",
  "title": "Confidence Interval",
  "alt": "The worst part is that's the millisigma interval.",
  "img": "https://imgs.xkcd.com/comics/confidence_interval.png",
  "safe_title": "Confidence Interval",
  "link": "",
  "news": "",
  "transcript": ""
}
Nach dem Login kopieren

Artikelbezogener xkcd

2 : für Comic-Erstellungsmodell

Gemäß der obigen JSON-Antwort erstellen wir eine Struktur namens ComicResponse in comic.go im Modellpaket

type ComicResponse struct {
    Month      string `json:"month"`
    Num        int    `json:"num"`
    Link       string `json:"link"`
    Year       string `json:"year"`
    News       string `json:"news"`
    SafeTitle  string `json:"safe_title"`
    Transcript string `json:"transcript"`
    Alt        string `json:"alt"`
    Img        string `json:"img"`
    Title      string `json:"title"`
    Day        string `json:"day"`
}
Nach dem Login kopieren

Sie können dazu das JSON-to-Go-Tool verwenden Generieren Sie es automatisch aus der JSON-Struktur.

Erstellen Sie übrigens eine weitere Struktur, die zur Ausgabe von Daten aus unserer Anwendung verwendet wird.

type Comic struct {
    Title       string `json:"title"`
    Number      int    `json:"number"`
    Date        string `json:"date"`
    Description string `json:"description"`
    Image       string `json:"image"`
}
Nach dem Login kopieren

Fügen Sie die folgenden zwei Methoden zur ComicResponse-Struktur hinzu

// FormattedDate 函数将格式化日期元素为一个字符串
func (cr ComicResponse) FormattedDate() string {
    return fmt.Sprintf("%s-%s-%s", cr.Day, cr.Month, cr.Year)
}
// Comic 函数将从 API 接收到的 ComicResponse 转换为应用程序的输出格式, Comic 结构体
func (cr ComicResponse) Comic() Comic {
    return Comic{
        Title:       cr.Title,
        Number:      cr.Num,
        Date:        cr.FormattedDate(),
        Description: cr.Alt,
        Image:       cr.Img,
    }
}
Nach dem Login kopieren

Fügen Sie dann die folgenden zwei Methoden zur Comic-Struktur hinzu

// PrettyString 函数创建一个漂亮的 Comic 字符串并用于输出
func (c Comic) PrettyString() string {
    p := fmt.Sprintf(
        "Title: %s\nComic No: %d\nDate: %s\nDescription: %s\nImage: %s\n",
        c.Title, c.Number, c.Date, c.Description, c.Image)
    return p
}
// JSON 函数将 Comic 结构体转换为 JSON, 我们将使用 JSON 字符串作为输出内容
func (c Comic) JSON() string {
    cJSON, err := json.Marshal(c)
    if err != nil {
        return ""
    }
    return string(cJSON)
}
Nach dem Login kopieren

3: Richten Sie den xkcd-Client so ein, dass er eine Anfrage initiiert, die Antwort analysiert und auf der Festplatte speichert

Erstellen Sie xkcd im Client-Paket. go-Datei.

Definieren Sie zunächst einen benutzerdefinierten Typ namens ComicNumber, der Datentyp ist int

Typ ComicNumber int

Konstanten definieren

const (
    // xkcd 的 BaseURL
    BaseURL string = "https://xkcd.com"
    // DefaultClientTimeout 是取消请求之前要等待的时间
    DefaultClientTimeout time.Duration = 30 * time.Second
    // 根据 xkcd API, LatestComic 是最新的漫画编号
    LatestComic ComicNumber = 0
)
Nach dem Login kopieren

Erstellen eine Struktur XKCDClient, die verwendet wird, um Anfragen an die API zu stellen.

// XKCDClient 是 XKCD 的客户端结构体
type XKCDClient struct {
    client  *http.Client
    baseURL string
}
// NewXKCDClient 创建一个新的 XKCDClient
func NewXKCDClient() *XKCDClient {
    return &XKCDClient{
        client: &http.Client{
            Timeout: DefaultClientTimeout,
        },
        baseURL: BaseURL,
    }
}
Nach dem Login kopieren

Fügen Sie die folgenden 4 Methoden zu XKCDClient hinzu

SetTimeout()

// SetTimeout 重写了默认的 ClientTimeout
func (hc *XKCDClient) SetTimeout(d time.Duration) {
    hc.client.Timeout = d
}
Nach dem Login kopieren

Fetch()

// Fetch 根据提供的漫画编号检索漫画
func (hc *XKCDClient) Fetch(n ComicNumber, save bool) (model.Comic, error) {
    resp, err := hc.client.Get(hc.buildURL(n))
    if err != nil {
        return model.Comic{}, err
    }
    defer resp.Body.Close()
    var comicResp model.ComicResponse
    if err := json.NewDecoder(resp.Body).Decode(&comicResp); err != nil {
        return model.Comic{}, err
    }
    if save {
        if err := hc.SaveToDisk(comicResp.Img, "."); err != nil {
            fmt.Println("Failed to save image!")
        }
    }
    return comicResp.Comic(), nil
}
Nach dem Login kopieren

SaveToDisk()

// SaveToDisk 下载并保存漫画到本地磁盘
func (hc *XKCDClient) SaveToDisk(url, savePath string) error {
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    absSavePath, _ := filepath.Abs(savePath)
    filePath := fmt.Sprintf("%s/%s", absSavePath, path.Base(url))
    file, err := os.Create(filePath)
    if err != nil {
        return err
    }
    defer file.Close()
    _, err = io.Copy(file, resp.Body)
    if err != nil {
        return err
    }
    return nil
}
Nach dem Login kopieren

buildURL()

func (hc *XKCDClient) buildURL(n ComicNumber) string {
    var finalURL string
    if n == LatestComic {
        finalURL = fmt.Sprintf("%s/info.0.json", hc.baseURL)
    } else {
        finalURL = fmt.Sprintf("%s/%d/info.0.json", hc.baseURL, n)
    }
    return finalURL
}
Nach dem Login kopieren

4: Alle verbinden

Innerhalb der main()-Funktion verlinken wir alle Inhalte

Befehlszeilenparameter lesen

XKCDClient instanziieren

XKCDClient verwenden, um Daten von der API abzurufen

Ausgabe

Befehlszeilenparameter lesen

comicNo := flag.Int(
    "n", int(client.LatestComic), "Comic number to fetch (default latest)",
)
clientTimeout := flag.Int64(
    "t", int64(client.DefaultClientTimeout.Seconds()), "Client timeout in seconds",
)
saveImage := flag.Bool(
    "s", false, "Save image to current directory",
)
outputType := flag.String(
    "o", "text", "Print output in format: text/json",
)
Nach dem Login kopieren

flag.Parse()

instanziieren

Oder erstellen Sie es als binäre ausführbare Datei auf Ihrem Laptop und führen Sie es aus

xkcdClient := client.NewXKCDClient()
xkcdClient.SetTimeout(time.Duration(*clientTimeout) * time.Second)
Nach dem Login kopieren

Der vollständige Quellcode finden Sie in diesem Github-Repo – go-grab- xkcd

Extra-Bonus

Mit diesem einfachen Shell-Zaubertool können Sie mehrere Comics nacheinander herunterladen

comic, err := xkcdClient.Fetch(client.ComicNumber(*comicNo), *saveImage)
if err != nil {
    log.Println(err)
}
Nach dem Login kopieren
Der obige Shell-Code ruft einfach go- auf. grab-xkcd in einem for-Schleifenbefehl, da xkcd Sequenz-Ganzzahlen verwendet, ersetzen Sie den i-Wert durch die Comic-Nummer als Comic-Nummer/ID.

Empfohlene Tutorials: "PHP

" "

Go Tutorial

"

Das obige ist der detaillierte Inhalt vonErstellen Sie ein CLI-Programm mit Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:learnku.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!