¿Te gustan las aplicaciones CLI?No te pierdas elgato graciosotutorial también!
Cowsayes una de esas aplicaciones sin las que no puedes vivir.
Básicamente genera imágenes ASCII de una vaca con cualquier mensaje al que se la pase, en la captura de pantalla anterior usandofortune
para generarlo. Pero no se limita al dominio de las vacas, puede imprimir pingüinos, alces y muchos otros animales.
¡Suena como una aplicación útil para portar a Go!
Además, me gusta la licencia en inglés simple adjunta:
==============
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.
Comencemos por definir el problema. Queremos aceptar información a través de una tubería y que nuestra vaca lo diga.
La primera iteración lee la entrada del usuario de la tubería y la imprime. No es demasiado complicado.
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>])
}
}
Nos falta la vaca, y también tenemos que envolver el mensaje en un globo, bien formateado.
Aquí está la primera iteración de nuestro programa:
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>()
}
Hagamos ahora configurable la figura, agregando unestegosaurio
La aplicación original utiliza el-f
bandera para aceptar una figura personalizada. Así que hagamos lo mismo porprocesando una bandera de línea de comando.
Cambio brevemente el programa anterior para introducirprintFigure()
// 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>)
}
}
y cambiandomain()
aceptar una bandera y pasarla aprintFigure()
:
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()
}
Creo que estamos en un buen momento. Solo quiero que este sistema sea utilizable, sin ejecutargo run main.go
, así que solo escribirégo build
ygo install
.
Ahora puedo pasar el día congololcaty gocowsay
Más tutoriales de go:
- Uso de NGINX Reverse Proxy para brindar servicios de Go
- Hacer una copia de una estructura en Go
- Los conceptos básicos de un servidor web Go
- Ordenar un tipo de mapa en Go
- Ir consejos en pocas palabras
- Explicación de las etiquetas Go
- Ir al formato de fecha y hora
- Procesamiento JSON con Go
- Ir a funciones variadas
- Hoja de referencia de Go Strings
- Explicación de la interfaz Go Empty
- Depuración de Go con VS Code y Delve
- Parámetros de devoluciones de Go Named
- Generación de cadenas y números aleatorios en Go
- Estructura del sistema de archivos de un proyecto de Go
- Algoritmo de búsqueda binaria implementado en Go
- Uso de indicadores de línea de comando en Go
- GOPATH explicado
- Cree una aplicación de línea de comandos con Go: lolcat
- Construyendo un comando CLI con Go: cowsay
- Uso de Shell Pipes con Go
- Tutorial de Go CLI: clon de la fortuna
- Enumere los archivos en una carpeta con Go
- Use Ir para obtener una lista de repositorios de GitHub
- Ve, agrega un trozo de cadenas a un archivo
- Ve, convierte una cadena en un segmento de bytes
- Visualice sus contribuciones locales de Git con Go
- Introducción a la creación de perfiles de memoria y CPU de Go
- Resolver el error "no admite la indexación" en un programa Go
- Medir el tiempo de ejecución en un programa Go
- Creación de un rastreador web con Go para detectar títulos duplicados
- Siga las mejores prácticas: ¿puntero o receptores de valor?
- Siga las mejores prácticas: ¿Debería utilizar un método o una función?
- Ir a estructuras de datos: Establecer
- Hoja de referencia de Go Maps
- Genere implementaciones para tipos genéricos en Go
- Ir a estructuras de datos: diccionario
- Ir a estructuras de datos: tabla hash
- Implementar oyentes de eventos en canales de paso
- Ir a estructuras de datos: apilar
- Ir a estructuras de datos: cola
- Ir a estructuras de datos: árbol de búsqueda binaria
- Ir a estructuras de datos: gráfico
- Ir a estructuras de datos: lista vinculada
- La guía completa de Go Data Structures
- Comparación de valores de Go
- ¿Go está orientado a objetos?
- Trabajar con una base de datos SQL en Go
- Usar variables de entorno en Go
- Ir al tutorial: API REST respaldada por PostgreSQL
- Habilitación de CORS en un servidor web Go
- Implementación de una aplicación Go en un contenedor Docker
- Por qué Go es un lenguaje poderoso para aprender como desarrollador PHP
- Ve, elimina el carácter de nueva línea io.Reader.ReadString
- Ir, cómo ver los cambios y reconstruir su programa
- Ve, cuenta los meses desde una fecha
- Acceder a los parámetros HTTP POST en Go