web-dev-qa-db-fra.com

Comment avoir une chaîne sur place qui se met à jour sur stdout

Je veux sortir sur stdout et avoir la sortie "écraser" la sortie précédente.

Par exemple; si je produis On 1/10, Je veux la sortie suivante On 2/10 pour remplacer On 1/10. Comment puis-je faire ceci?

44
user1529891

stdout est un flux (io.Writer). Vous ne pouvez pas modifier ce qui y était déjà écrit. Ce que peut être modifié est la façon dont ce flux est représenté au cas où il serait imprimé sur un terminal. Notez qu'il n'y a aucune bonne raison de supposer ce scénario. Par exemple, un utilisateur peut rediriger stdout vers un canal ou vers un fichier à volonté.

La bonne approche consiste donc à vérifier d'abord:

  • si la sortie standard va vers un terminal
  • quelle est la procédure de ce terminal pour écraser une ligne/un écran

Les deux ci-dessus sont hors de portée de cette question, mais supposons qu'un terminal est notre appareil. Ensuite, généralement, l'impression:

fmt.Printf("\rOn %d/10", i)

remplacera la ligne précédente dans le terminal. \r signifie carriage return, implémenté par de nombreux terminaux comme déplaçant le curseur au début de la ligne courante, fournissant ainsi la fonction "écraser la ligne".

À titre d'exemple de "autre" terminal avec un "écrasement" pris en charge différemment, voici un exemple au terrain de je .

78
zzzz

Utilisez cette solution si vous souhaitez réécrire plusieurs lignes dans la sortie. Par exemple, j'ai fait une sortie décente "Game of Life" de Conway en utilisant cette méthode.

AVERTISSEMENT: cela ne fonctionne que sur les terminaux ANSI, et en plus d'utiliser fmt ce n'est pas une réponse spécifique à Go non plus.

fmt.Printf("\033[0;0H")
// put your other fmt.Printf(...) here

Brève explication: il s'agit d'une séquence d'échappement qui indique au terminal ANSI de déplacer le curseur à un endroit particulier de l'écran. Le \033[ est la soi-disant séquence d'échappement, et le 0;0H est le type de code indiquant au terminal de déplacer le curseur sur la ligne 0, colonne 0 du terminal.

Source: https://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements

22
Frank Bryce

La solution pour une chaîne qui remplacera la chaîne entière

fmt.Printf("\033[2K\r%d", i)

Par exemple, il imprime correctement de 10 à 0:

for i:= 10; i>=0; i-- {
    fmt.Printf("\033[2K\r%d", i)
    time.Sleep(1 * time.Second)
}
fmt.Println()

quelles réponses précédentes ne résolvent pas.

6
abonec