喜歡CLI應用程序嗎?不要錯過洛爾卡特教程也一樣!
考賽是您不可或缺的應用程序之一。
在上面的屏幕快照中,它基本上會生成帶有您傳遞給它的任何消息的母牛的ASCII圖片。fortune
生成它。但這不僅限於牛域,它還可以打印企鵝,駝鹿和許多其他動物。
聽起來像是一個有用的應用程序,可移植到Go!
另外,我喜歡所附的普通英語許可證:
==============
cowsay License
==============
cowsay is distributed under the same licensing terms as Perl: the
Artistic License or the GNU General Public License. If you don’t
want to track down these licenses and read them for yourself, use
the parts that I’d prefer:
(0) I wrote it and you didn’t.
(1) Give credit where credit is due if you borrow the code for some
other purpose.
(2) If you have any bugfixes or suggestions, please notify me so
that I may incorporate them.
(3) If you try to make money off of cowsay, you suck.
讓我們從定義問題開始。我們想通過管道接受輸入,然後讓我們的牛說出來。
第一次迭代從管道讀取用戶輸入,然後將其打印回去。沒有太多複雜。
package main
import (
“bufio”
“fmt”
“io”
“os”
)
func main() {
info, _ := os.Stdin.Stat()
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">info</span>.<span style="color:#a6e22e">Mode</span>()<span style="color:#f92672">&</span><span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">ModeCharDevice</span> <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span> {
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The command is intended to work with pipes."</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Usage: fortune | gocowsay"</span>)
<span style="color:#66d9ef">return</span>
}
<span style="color:#a6e22e">reader</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">bufio</span>.<span style="color:#a6e22e">NewReader</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stdin</span>)
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">output</span> []<span style="color:#66d9ef">rune</span>
<span style="color:#66d9ef">for</span> {
<span style="color:#a6e22e">input</span>, <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">reader</span>.<span style="color:#a6e22e">ReadRune</span>()
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&&</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">io</span>.<span style="color:#a6e22e">EOF</span> {
<span style="color:#66d9ef">break</span>
}
<span style="color:#a6e22e">output</span> = append(<span style="color:#a6e22e">output</span>, <span style="color:#a6e22e">input</span>)
}
<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">j</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">j</span> < len(<span style="color:#a6e22e">output</span>); <span style="color:#a6e22e">j</span><span style="color:#f92672">++</span> {
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"%c"</span>, <span style="color:#a6e22e">output</span>[<span style="color:#a6e22e">j</span>])
}
}
我們想念這頭牛,還需要將消息包裝成一個氣球,格式正確。
這是我們程序的第一次迭代:
package main
import (
“bufio”
“fmt”
“io”
“os”
“strings”
“unicode/utf8”
)
// buildBalloon takes a slice of strings of max width maxwidth
// prepends/appends margins on first and last line, and at start/end of each line
// and returns a string with the contents of the balloon
func buildBalloon(lines []string, maxwidth int) string {
var borders []string
count := len(lines)
var ret []string
<span style="color:#a6e22e">borders</span> = []<span style="color:#66d9ef">string</span>{<span style="color:#e6db74">"/"</span>, <span style="color:#e6db74">"\\"</span>, <span style="color:#e6db74">"\\"</span>, <span style="color:#e6db74">"/"</span>, <span style="color:#e6db74">"|"</span>, <span style="color:#e6db74">"<"</span>, <span style="color:#e6db74">">"</span>}
<span style="color:#a6e22e">top</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">" "</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Repeat</span>(<span style="color:#e6db74">"_"</span>, <span style="color:#a6e22e">maxwidth</span><span style="color:#f92672">+</span><span style="color:#ae81ff">2</span>)
<span style="color:#a6e22e">bottom</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">" "</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Repeat</span>(<span style="color:#e6db74">"-"</span>, <span style="color:#a6e22e">maxwidth</span><span style="color:#f92672">+</span><span style="color:#ae81ff">2</span>)
<span style="color:#a6e22e">ret</span> = append(<span style="color:#a6e22e">ret</span>, <span style="color:#a6e22e">top</span>)
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">count</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span> {
<span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">"%s %s %s"</span>, <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">5</span>], <span style="color:#a6e22e">lines</span>[<span style="color:#ae81ff">0</span>], <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">6</span>])
<span style="color:#a6e22e">ret</span> = append(<span style="color:#a6e22e">ret</span>, <span style="color:#a6e22e">s</span>)
} <span style="color:#66d9ef">else</span> {
<span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">`%s %s %s`</span>, <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">0</span>], <span style="color:#a6e22e">lines</span>[<span style="color:#ae81ff">0</span>], <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">1</span>])
<span style="color:#a6e22e">ret</span> = append(<span style="color:#a6e22e">ret</span>, <span style="color:#a6e22e">s</span>)
<span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">1</span>
<span style="color:#66d9ef">for</span> ; <span style="color:#a6e22e">i</span> < <span style="color:#a6e22e">count</span><span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span> {
<span style="color:#a6e22e">s</span> = <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">`%s %s %s`</span>, <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">4</span>], <span style="color:#a6e22e">lines</span>[<span style="color:#a6e22e">i</span>], <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">4</span>])
<span style="color:#a6e22e">ret</span> = append(<span style="color:#a6e22e">ret</span>, <span style="color:#a6e22e">s</span>)
}
<span style="color:#a6e22e">s</span> = <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">`%s %s %s`</span>, <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">2</span>], <span style="color:#a6e22e">lines</span>[<span style="color:#a6e22e">i</span>], <span style="color:#a6e22e">borders</span>[<span style="color:#ae81ff">3</span>])
<span style="color:#a6e22e">ret</span> = append(<span style="color:#a6e22e">ret</span>, <span style="color:#a6e22e">s</span>)
}
<span style="color:#a6e22e">ret</span> = append(<span style="color:#a6e22e">ret</span>, <span style="color:#a6e22e">bottom</span>)
<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Join</span>(<span style="color:#a6e22e">ret</span>, <span style="color:#e6db74">"\n"</span>)
}
// tabsToSpaces converts all tabs found in the strings
// found in the lines
slice to 4 spaces, to prevent misalignments in
// counting the runes
func tabsToSpaces(lines []string) []string {
var ret []string
for _, l := range lines {
l = strings.Replace(l, “\t”, " ", -1)
ret = append(ret, l)
}
return ret
}
// calculatemaxwidth given a slice of strings returns the length of the
// string with max length
func calculateMaxWidth(lines []string) int {
w := 0
for _, l := range lines {
len := utf8.RuneCountInString(l)
if len > w {
w = len
}
}
<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">w</span>
}
// normalizeStringsLength takes a slice of strings and appends
// to each one a number of spaces needed to have them all the same number
// of runes
func normalizeStringsLength(lines []string, maxwidth int) []string {
var ret []string
for _, l := range lines {
s := l + strings.Repeat(" ", maxwidth-utf8.RuneCountInString(l))
ret = append(ret, s)
}
return ret
}
func main() {
info, _ := os.Stdin.Stat()
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">info</span>.<span style="color:#a6e22e">Mode</span>()<span style="color:#f92672">&</span><span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">ModeCharDevice</span> <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span> {
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"The command is intended to work with pipes."</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Usage: fortune | gocowsay"</span>)
<span style="color:#66d9ef">return</span>
}
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">lines</span> []<span style="color:#66d9ef">string</span>
<span style="color:#a6e22e">reader</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">bufio</span>.<span style="color:#a6e22e">NewReader</span>(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Stdin</span>)
<span style="color:#66d9ef">for</span> {
<span style="color:#a6e22e">line</span>, <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">reader</span>.<span style="color:#a6e22e">ReadLine</span>()
<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&&</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">io</span>.<span style="color:#a6e22e">EOF</span> {
<span style="color:#66d9ef">break</span>
}
<span style="color:#a6e22e">lines</span> = append(<span style="color:#a6e22e">lines</span>, string(<span style="color:#a6e22e">line</span>))
}
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">cow</span> = <span style="color:#e6db74">` \ ^__^
\ (oo)_______
(__)\ )/
||----w |
|| ||
`
<span style="color:#a6e22e">lines</span> = <span style="color:#a6e22e">tabsToSpaces</span>(<span style="color:#a6e22e">lines</span>)
<span style="color:#a6e22e">maxwidth</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">calculateMaxWidth</span>(<span style="color:#a6e22e">lines</span>)
<span style="color:#a6e22e">messages</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">normalizeStringsLength</span>(<span style="color:#a6e22e">lines</span>, <span style="color:#a6e22e">maxwidth</span>)
<span style="color:#a6e22e">balloon</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">buildBalloon</span>(<span style="color:#a6e22e">messages</span>, <span style="color:#a6e22e">maxwidth</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">balloon</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">cow</span>)
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>()
}
現在,通過添加一個劍龍
原始應用程序使用-f
標誌以接受自定義圖形。因此,讓我們做同樣的事情處理命令行標誌。
我簡要地更改了以前的程序以進行介紹printFigure()
// printFigure given a figure name prints it.
// Currently accepts `cow` and `stegosaurus`.
func printFigure(name string) {
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">cow</span> = <span style="color:#e6db74">` \ ^__^
\ (oo)_______
(__)\ )/
||----w |
|| ||
`
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">stegosaurus</span> = <span style="color:#e6db74">` \ . .
\ / </span> <span style="color:#f92672">+</span> <span style="color:#e6db74">"
" + . .' " </span><span style="color:#e6db74"> \ .---. < > < > .---. </span><span style="color:#e6db74"> \ | \ \ - ~ ~ - / / | </span><span style="color:#e6db74"> _____ ..-~ ~-..-~ </span><span style="color:#e6db74"> | | \~~~\\.'
+ ""</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">
./~/
--------- _/ _/
.’ O \ / / \ "
(_____, </span> <span style="color:#f92672">+</span> <span style="color:#e6db74">"
" + ._.' | } \/~~~/ </span><span style="color:#e6db74">
+ ""</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">
----. / } | / __/
</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">"
" + -. | / | /
+ ""</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">
. ,|
~-.| /_ - ~ ^| /- _ </span> <span style="color:#f92672">+</span> <span style="color:#e6db74">"
" + ..-' </span><span style="color:#e6db74"> | / | / ~-.
+ ""</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">
-. _ _ _
|| |__| ~ - . _ _ _ _ _>
`
<span style="color:#66d9ef">switch</span> <span style="color:#a6e22e">name</span> {
<span style="color:#66d9ef">case</span> <span style="color:#e6db74">"cow"</span>:
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">cow</span>)
<span style="color:#66d9ef">case</span> <span style="color:#e6db74">"stegosaurus"</span>:
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">stegosaurus</span>)
<span style="color:#66d9ef">default</span>:
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">"Unknown figure"</span>)
}
}
和改變main()
接受一個標誌並將其傳遞給printFigure()
:
func main() {
//...
var figure string
flag.StringVar(&figure, "f", "cow", "the figure name. Valid values are `cow` and `stegosaurus`")
flag.Parse()
<span style="color:#75715e">//...
printFigure(figure)
fmt.Println()
}
我認為我們處在一個好時機。我只想在系統上使它可用,而無需運行go run main.go
,所以我只輸入go build
和go install
。
我現在可以與戈洛爾卡特和gocowsay
更多教程:
- 使用NGINX反向代理服務Go服務
- 在Go中復制結構
- Go Web服務器的基礎
- 在Go中對地圖類型進行排序
- 簡而言之去指針
- 轉到標籤說明
- 開始日期和時間格式
- 使用Go進行JSON處理
- 可變參數函數
- 去弦備忘單
- 轉到空界面說明
- 使用VS Code和Delve調試Go
- 命名為Go返回參數
- 在Go中生成隨機數和字符串
- Go項目的文件系統結構
- Go中的二進制搜索算法
- 在Go中使用命令行標誌
- GOPATH解釋
- 使用Go構建一個命令行應用程序:lolcat
- 使用Go構建CLI命令:Cowsay
- 在Go中使用殼管
- Go CLI教程:財富克隆
- 使用Go列出文件夾中的文件
- 使用Go從GitHub獲取存儲庫列表
- 去,將一小段字符串附加到文件中
- 去,將字符串轉換為字節片
- 使用Go可視化您本地的Git貢獻
- Go CPU和內存分析入門
- 解決Go程序中的“不支持索引”錯誤
- 測量Go程序中的執行時間
- 使用Go構建Web爬網程序以檢測重複的標題
- 最佳實踐:指針還是價值接收者?
- 最佳實踐:您應該使用方法還是函數?
- Go數據結構:集
- 前往地圖備忘單
- 在Go中生成泛型類型的實現
- Go數據結構:字典
- Go數據結構:哈希表
- 在“通過通道”中實現事件偵聽器
- Go數據結構:堆棧
- Go數據結構:隊列
- Go數據結構:二進制搜索樹
- Go數據結構:圖形
- Go數據結構:鍊錶
- Go數據結構的完整指南
- 比較Go值
- Go是面向對象的嗎?
- 在Go中使用SQL數據庫
- 在Go中使用環境變量
- 上篇教程:PostgreSQL支持的REST API
- 在Go Web服務器上啟用CORS
- 在Docker容器中部署Go應用程序
- 為什麼Go是作為PHP開發人員學習的功能強大的語言
- 去,刪除io.Reader.ReadString換行符
- 開始,如何觀看更改並重建程序
- 去算一下自約會以來的月份
- 在Go中訪問HTTP POST參數