Utilisation de Shell Pipes avec Go

Être un bon citoyen dans la ligne de commande signifie utiliser des tuyaux.

Utilisation de la barre verticale|nous pouvons passer la sortie d'une commande en tant qu'entrée d'une autre commande et enchaîner plusieurs commandes pour fournir une sortie unique.

J'ai fait 2 tutoriels qui utilisent des tuyaux comme entrée, construisantgocowsayetGololcat, mais je n'ai pas décrit en détail le processus pour obtenir des entrées d'un tuyau, alors voici un article sur ce sujet.

Voici un exemple:

package main

import ( “bufio” “fmt” “io” “os” )

func main() { info, err := os.Stdin.Stat() if err != nil { panic(err) }

<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">info</span>.<span style="color:#a6e22e">Mode</span>()<span style="color:#f92672">&amp;</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:#f92672">||</span> <span style="color:#a6e22e">info</span>.<span style="color:#a6e22e">Size</span>() <span style="color:#f92672">&lt;=</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">&amp;&amp;</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> &lt; 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>])
}

}

Examinons comment cela fonctionne. Première ligne intéressante:

info, err := os.Stdin.Stat()

os.Stdin, comme Stdout et Stderr, est un openDéposer. Il pointe vers le descripteur de fichier d'entrée standard.

Stat()est une méthode de File qui renvoie unFileInfodécrivant le fichier, fournissant des informations, y compris le mode et la taille du fichier.

La prochaine pièce intéressante est

info.Mode()&os.ModeCharDevice != 0

FileInfo.Mode()renvoie leuint32masque qui détermine le mode de fichier et les autorisations en tant que const (https://golang.org/pkg/os/#FileMode).

Usign un AND au niveau du bit détermine si le mode de fichier est os.ModeCharDevice. C'est un moyen de s'assurer que le fichier pointe vers unModeCharDevice, le périphérique de caractères Unix (terminal). Puisque le fichier pointe versos.Stdin, Nous excluons essentiellement que l'entrée soit un tuyau.

Bitwise renvoie 0 si le mode estne pasla constante que nous passons. Nous pourrions également vérifier

info.Mode()&os.ModeCharDevice == os.ModeCharDevice

c'est la même chose, mais plus lisible.

Si c'est faux, nous avons une vérification supplémentaire pour

info.Size() <= 0

qui, combiné avec la vérification précédente, s'assure d'avoir un tube d'entrée, et qui contient en fait quelques octets.

Nous pourrions également vérifier

if info.Mode()&os.ModeNamedPipe != 0 {
	// we have a pipe input
}

et cela garantira que l'entrée provient du tuyau.

Ensuite, le programme crée un lecteur

reader := bufio.NewReader(os.Stdin)

bufioest un package qui implémente des E / S tamponnées, encapsulant essentiellementio.Readeretio.Writer.

Nous lui demandons de nous donner un lecteur tamponné d'os.Stdin, en utilisant la taille de tampon par défaut qui est de 4096 octets.

bufio.Readerfournit de nombreuses méthodes pour lire les données:ReadByte,ReadBytes,ReadLine,ReadRune,ReadSlice,ReadString.

L'exemple utiliseReadRuneafin qu'il puisse ajouter chaque rune lue dans levar output []runetrancher et manipulerunicodechars sans aucun effort.

Lire la suite


Plus de tutoriels go: