Skip to content

Entrada e Saída do Go

go
package main

import "fmt"

func main() {
   fmt.Println("Hello 世界!")
}

O primeiro exemplo introdutório deste site é a saída de uma string, esta seção explicará como realizar entrada e saída em Go.

Descritores de Arquivo

go
var (
   Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
   Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
   Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

No pacote os existem três descritores de arquivo expostos, todos do tipo *os.File, que são

  • os.Stdin - entrada padrão
  • os.Stdout - saída padrão
  • os.Stderr - erro padrão

A entrada e saída em Go dependem deles.

Saída

Em Go, existem muitos métodos de saída, abaixo estão alguns dos mais comuns

stdout

Como a saída padrão em si é um arquivo, você pode escrever diretamente uma string na saída padrão

go
package main

import "os"

func main() {
  os.Stdout.WriteString("hello world!")
}

print

Go tem duas funções incorporadas print, println, elas enviam os parâmetros para o erro padrão, apenas para depuração, geralmente não recomendado usar.

go
package main

func main() {
  print("hello world!\n")
  println("hello world")
}

fmt

O uso mais comum é usar o pacote fmt, ele fornece a função fmt.Println, que por padrão envia os parâmetros para a saída padrão.

go
package main

import "fmt"

func main() {
  fmt.Println("hello world!")
}

Seus parâmetros suportam qualquer tipo, se o tipo implementar a interface String também chamará o método String para obter sua representação em string, então o conteúdo que ele produz tem legibilidade relativamente alta, adequado para a maioria das situações, mas como usa reflexão internamente, não é recomendado usar muito em cenários sensíveis a desempenho.

bufio

bufio fornece métodos de saída com buffer, ele primeiro escreve os dados na memória, acumula até um certo limite e então envia para o Writer especificado, o tamanho padrão do buffer é 4KB. Recomenda-se usar este pacote para IO de arquivos, IO de rede.

go
func main() {
  writer := bufio.NewWriter(os.Stdout)
  defer writer.Flush()
  writer.WriteString("hello world!")
}

Você também pode combiná-lo com o pacote fmt

go
func main() {
  writer := bufio.NewWriter(os.Stdout)
  defer writer.Flush()
  fmt.Fprintln(writer, "hello world!")
}

Formatação

A funcionalidade de formatação de saída em Go é basicamente fornecida pela função fmt.Printf, se você já aprendeu linguagens da família C, vai achar familiar, abaixo está um exemplo simples.

go
func main() {
  fmt.Printf("hello world, %s!", "jack")
}

Abaixo estão todos os verbos de formatação Go atuais.

0FormataçãoDescriçãoTipo de Entrada
1%%Saída do sinal de porcentagem %Qualquer
2%sSaída do valor string/[] bytestring,[] byte
3%qFormata string, a string de saída tem aspas duplas "" nos dois ladosstring,[] byte
4%dSaída de valor inteiro em decimalInteiro
5%fSaída de número de ponto flutuantePonto flutuante
6%eSaída em forma de notação científica, também pode ser usado para números complexosPonto flutuante
7%EIgual a %ePonto flutuante
8%gJulga automaticamente se deve usar %f ou %e para saída, remove zeros desnecessáriosPonto flutuante
9%bSaída da representação binária de inteiroNúmero
10%#bSaída da representação binária completaNúmero
11%oSaída da representação octal de inteiroInteiro
12%#oSaída da representação octal completa de inteiroInteiro
13%xSaída da representação hexadecimal minúscula de inteiroNúmero
14%#xSaída da representação hexadecimal minúscula completa de inteiroNúmero
15%XSaída da representação hexadecimal maiúscula de inteiroNúmero
16%#XSaída da representação hexadecimal maiúscula completa de inteiroNúmero
17%vSaída do valor na forma original, muito usado para saída de estruturas de dadosQualquer
18%+vAo sair struct, adicionará nomes de camposQualquer
19%#vSaída do valor em formato de sintaxe Go completoQualquer
20%tSaída de valor booleanoBooleano
21%TSaída do tipo Go correspondente ao valorQualquer
22%cSaída do caractere correspondente ao código Unicodeint32
23%USaída do código Unicode correspondente ao caractererune,byte
24%pSaída do endereço apontado pelo ponteiroPonteiro

Use fmt.Sprintf ou fmt.Printf para formatar strings ou sair strings formatadas, veja alguns exemplos

go
fmt.Printf("%%%s\n", "hello world")

fmt.Printf("%s\n", "hello world")
fmt.Printf("%q\n", "hello world")
fmt.Printf("%d\n", 2<<7-1)

fmt.Printf("%f\n", 1e2)
fmt.Printf("%e\n", 1e2)
fmt.Printf("%E\n", 1e2)
fmt.Printf("%g\n", 1e2)

fmt.Printf("%b\n", 2<<7-1)
fmt.Printf("%#b\n", 2<<7-1)
fmt.Printf("%o\n", 2<<7-1)
fmt.Printf("%#o\n", 2<<7-1)
fmt.Printf("%x\n", 2<<7-1)
fmt.Printf("%#x\n", 2<<7-1)
fmt.Printf("%X\n", 2<<7-1)
fmt.Printf("%#X\n", 2<<7-1)

type person struct {
    name    string
    age     int
    address string
}
fmt.Printf("%v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%+v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%#v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%t\n", true)
fmt.Printf("%T\n", person{})
fmt.Printf("%c%c\n", 20050, 20051)
fmt.Printf("%U\n", '')
fmt.Printf("%p\n", &person{})

Ao usar outras bases, adicionar um espaço entre % e o verbo de formatação pode obter o efeito de separador, por exemplo

go
func main() {
  str := "abcdefg"
  fmt.Printf("%x\n", str)
  fmt.Printf("% x\n", str)
}

O resultado deste exemplo é

61626364656667
61 62 63 64 65 66 67

Ao usar números, também pode-se preencher com zeros automaticamente. Por exemplo

go
fmt.Printf("%09d", 1)
// 000000001

O mesmo vale para binário

go
fmt.Printf("%09b", 1<<3)
// 000001000

Situações de Erro

Quantidade de caracteres de formatação < quantidade da lista de parâmetros

go
fmt.Printf("", "") //%!(EXTRA string=)

Quantidade de caracteres de formatação > quantidade da lista de parâmetros

go
fmt.Printf("%s%s", "") //%!s(MISSING)

Tipo incompatível

go
fmt.Printf("%s", 1) //%!s(int=1)

Falta verbo de formatação

go
fmt.Printf("%", 1) // %!(NOVERB)%!(EXTRA int=1)

Entrada

Abaixo são apresentados os métodos comuns de entrada

read

Você pode ler o conteúdo de entrada como se estivesse lendo um arquivo diretamente, assim

go
func main() {
  var buf [1024]byte
  n, _ := os.Stdin.Read(buf[:])
  os.Stdout.Write(buf[:n])
}

Usar assim é muito trabalhoso, geralmente não recomendado.

fmt

Podemos usar várias funções fornecidas pelo pacote fmt, o uso é similar ao C.

go
// Lê o texto de os.Stdin, separa por espaços, nova linha também é considerada espaço
func Scan(a ...any) (n int, err error)

// Similar a Scan, mas para de ler ao encontrar nova linha
func Scanln(a ...any) (n int, err error)

// Lê de acordo com a string de formatação
func Scanf(format string, a ...any) (n int, err error)

Lendo dois números

go
func main() {
  var a, b int
  fmt.Scanln(&a, &b)
  fmt.Printf("%d + %d = %d\n", a, b, a+b)
}

Lendo um array de comprimento fixo

go
func main() {
  n := 10
  s := make([]int, n)
  for i := range n {
    fmt.Scan(&s[i])
  }
  fmt.Println(s)
}
1 2 3 4 5 6 7 8 9 10
[1 2 3 4 5 6 7 8 9 10]

bufio

Quando há uma grande quantidade de entrada para ler, é recomendado usar bufio.Reader para ler o conteúdo

go
func main() {
    reader := bufio.NewReader(os.Stdin)
    var a, b int
    fmt.Fscanln(reader, &a, &b)
    fmt.Printf("%d + %d = %d\n", a, b, a+b)
}

scanner

bufio.Scanner é similar a bufio.Reader, mas lê linha por linha.

go
func main() {
  scanner := bufio.NewScanner(os.Stdin)
  for scanner.Scan() {
    line := scanner.Text()
    if line == "exit" {
      break
    }
    fmt.Println("scan", line)
  }
}

O resultado é o seguinte

first line
scan first line
second line
scan second line
third line
scan third line
exit

TIP

Para praticar entrada e saída, se quiser treinar, vá em Luogu fazer alguns exercícios simples de algoritmos em modo ACM para praticar.

Golang por www.golangdev.cn edit