Go語言CLI程式

2022-05-05 07:06:08 字數 3375 閱讀 8610

此文件用於說明go語言的cli程式的完成過程以及相關測試, 接下來我將按照寫程式的順序來依次介紹每個部分的過程。

寫這個cli程式的過程中,需要用到的包有下面這些,在**注釋中,我對這些包進行了詳細的解釋:

import (

"bufio" // 標準輸入流和資料之間的互動 //

"fmt" // 引用io.eof 來判斷錯誤是否是檔案尾導致,同時它還包含有格式化i/o函式,具有輸入輸出功能 //

"io" // 用於將錯誤資訊寫入到標準錯誤流,io包提供了對i/o原語的基本介面 //

"log" // 書寫錯誤資訊 //

"os" // 用於開啟檔案和異常退出時傳送狀態碼 //

"os/exec" // 開啟lp子程序 //

"strings" // 劃分、拼接字串 //

flag "github.com/spf13/pflag" // 獲取程式執行時使用者輸入的引數和標識 //

)

你可以把對包的引用看作是c++裡面對函式庫的引用,它位於乙個程式的開頭。然後接下來就開始書寫我們的程式了

先貼上初始化的有關**

type selpgargs struct 

startnum := flag.intp("startpage", "s", 0, "page to start")

endnum := flag.intp("endpage", "e", 0, "page to end")

linenum := flag.intp("linenumber", "1", 72, "a page will consist of a fixed number of lines")

dstprinter := flag.stringp("destination", "d", "", "choose a printer to accept the result as a task")

l := log.new(os.stderr, "", 0)

bytes := make(byte,65535)

var data string

var resultdata string

flag.parse()

我們來逐一的解釋一下上面這些有關初始化的**。首先是從startnum到dstprinter這五個變數的宣告和初始化,這些變數的含義和它們變數名表面的意思一樣,是我們對於 pflag 中各個標識的設定和變數繫結。

然後接著分別是對報錯輸入輸出流的繫結,緩衝區的建立以及讀入資料變數和結果資料變數的建立。最後一句,flag.parse()是用來解析上面初始化的變數的。

if *startnumber == 0 || *endnumber == 0 

if(*startnumber > *endnumber) || *startnumber < 0 || *endnumber < 0 || *linenumber <= 0

if *linenumber != 72 && *forcepage

if flag.narg() > 1

這一段檢測合法性的**可以分為四段,這四段分別檢測了以下四個方面的合法性:

-s和-e是否有被設定

**上體現為判斷s和e的值是否為0.因為s和

e在初始化的時候,值是被初始化為0了,所以通過判斷它們的值是否為0就可以判斷出它們是否有被設定

標識的值是否合法

如果起始頁的數字大於結束頁的數字或者和頁有關的引數小於零的話,都是不合法的

命令中是否同時出現乙個引數位上的兩個引數

這裡主要就檢測換行符和換頁符引數是否有同時出現

引數數量是否太多

pflag裡的narg方法,檢測未預定義引數的個數

如果這一段**有檢測到任何不符合要求的引數值或者不合理的邏輯的話,程式就會通過上面初始化的標準錯誤流輸出對應的錯誤資訊,列印正確的使用方法並退出程式。

if flag.narg() == 0 

// error

if err != io.eof

} else

// 讀取整個檔案

size, err := file.read(bytes)

for size != 0 && err == nil

if err != io.eof

}

這裡我們的目標有兩個,第乙個是判斷輸入的方式,第二個是將資料讀入到上面我們所建立的資料變數data中。

輸入的方式有兩種,一種是標準輸入的模式,一種是檔案輸入的方式。

對於標準輸入的模式來說,是沒有額外的引數的。bufio.newreader(os.stdin)建立了乙個reader並繫結到了標準輸入流上面,我們讓這個reader去讀取緩衝區bytes的資料,並將讀入的資料轉換成string再傳到資料變數data裡面。當然,如果這個環節出現了錯誤的話,程式會報出相關的錯誤資訊,並輸出相應的錯誤狀態。

對於檔案輸入的模式來說,攜帶了乙個額外的引數,使用os.open()開啟檔案,正常情況下,我們就通過file.read()迭代的讀出所有的檔案內容。

這個過程正常結束之後,我們就把要讀取的內容全部儲存在data裡面了

writer := bufio.newwriter(os.stdout) // 建立乙個writer

// stdout or printer? //

if *destinationprinter == "" else

go func() ()

out, err := cmd.combinedoutput()

if err != nil

_, err = writer.write(out)

if err != nil

}

根據輸出方式的不同輸出可分為兩類:直接輸出到標準輸出流的和將資料傳送給 lp 進行列印工作的.

我的測試檔案input_file是乙個一行只有乙個數字的txt檔案,然後每一行的數字都是遞增的,從1到10000.

命令輸入:

$ go run selpg.go -s10 -e20 input_file
結束頁為20頁,那就是結束行是1440

讀取標準輸入,輸入被重定向到input_file

結果同樣也是輸出到1440行

go語言cli命令列互動

預先準備 go get github.com spf13 cobra 執行rootcmd命令,在main被呼叫 func execute var cfgfile string func init func initconfig else 在home資料夾中搜尋以 yaml 為名稱的config co...

Go語言小程式

1 演示全域性變數的使用 2 init函式先於main函式執行 package main import fmt varname string 宣告全域性變數 func main func init 執行結果 howard good morning 1 用關鍵字var宣告變數,格式 var 變數名變數...

Go語言基礎 上 怎樣書寫 Go 語言程式?

第乙個go語言程式。在同乙個 module 裡匯入另乙個 package 新建資料夾ch01。然後在ch01內新建資料夾demo01。最後在demo01內檔案main.go。最後在main.go裡書寫一下內容 注意所有標點都是英文半形 code 1 1 package main import tim...