Entrada y salida en Go
package main
import "fmt"
func main() {
fmt.Println("Hello Mundo!")
}El primer ejemplo introductorio de este sitio es imprimir una cadena, esta sección explicará cómo realizar entrada y salida en Go.
Descriptores de archivo
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)En el paquete os hay tres descriptores de archivo expuestos, todos de tipo *os.File, que son:
os.Stdin- Entrada estándaros.Stdout- Salida estándaros.Stderr- Error estándar
La entrada y salida en Go dependen de ellos.
Salida
En Go hay muchas formas de realizar la salida, aquí se presentan algunas de las más comunes
stdout
Como la salida estándar en sí es un archivo, puedes escribir directamente en la salida estándar
package main
import "os"
func main() {
os.Stdout.WriteString("hello world!")
}print
Go tiene dos funciones incorporadas print y println, que envían los parámetros al error estándar, solo para depuración, generalmente no se recomienda su uso.
package main
func main() {
print("hello world!\n")
println("hello world")
}fmt
El uso más común es el paquete fmt, que proporciona la función fmt.Println, que por defecto envía los parámetros a la salida estándar.
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}Sus parámetros soportan cualquier tipo, si el tipo implementa la interfaz String también llamará al método String para obtener su representación en cadena, por lo que el contenido que imprime es bastante legible, adecuado para la mayoría de los casos, sin embargo, como usa reflexión internamente, no se recomienda su uso intensivo en escenarios sensibles al rendimiento.
bufio
bufio proporciona métodos de salida con búfer, primero escribe los datos en memoria, y cuando se acumula hasta cierto umbral los envía al Writer especificado, el tamaño de búfer por defecto es 4KB. Se recomienda usar este paquete para operaciones de E/S de archivos y redes.
func main() {
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
writer.WriteString("hello world!")
}También puedes combinarlo con el paquete fmt
func main() {
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
fmt.Fprintln(writer, "hello world!")
}Formateo
La funcionalidad de formateo de salida en Go es básicamente proporcionada por la función fmt.Printf. Si has aprendido lenguajes de la familia C, te resultará familiar, aquí hay un ejemplo simple.
func main() {
fmt.Printf("hello world, %s!", "jack")
}A continuación se muestran todos los verbos de formateo actuales de Go.
| 0 | Formato | Descripción | Tipo recibido |
|---|---|---|---|
| 1 | %% | Imprime el signo de porcentaje % | Cualquiera |
| 2 | %s | Imprime valores string/[] byte | string,[] byte |
| 3 | %q | Formatea cadena, la cadena impresa tiene comillas dobles "" en ambos extremos | string,[] byte |
| 4 | %d | Imprime valor entero en decimal | Entero |
| 5 | %f | Imprime número de punto flotante | Punto flotante |
| 6 | %e | Imprime en notación científica, también se puede usar para números complejos | Punto flotante |
| 7 | %E | Igual que %e | Punto flotante |
| 8 | %g | Según la situación decide imprimir %f o %e, eliminará los ceros innecesarios | Punto flotante |
| 9 | %b | Imprime la representación binaria de un entero | Número |
| 10 | %#b | Imprime la representación binaria completa | Número |
| 11 | %o | Imprime la representación octal de un entero | Entero |
| 12 | %#o | Imprime la representación octal completa de un entero | Entero |
| 13 | %x | Imprime la representación hexadecimal en minúsculas de un entero | Número |
| 14 | %#x | Imprime la representación hexadecimal completa en minúsculas de un entero | Número |
| 15 | %X | Imprime la representación hexadecimal en mayúsculas de un entero | Número |
| 16 | %#X | Imprime la representación hexadecimal completa en mayúsculas de un entero | Número |
| 17 | %v | Imprime el valor en su forma original, principalmente usado para imprimir estructuras de datos | Cualquiera |
| 18 | %+v | Al imprimir estructuras agregará los nombres de los campos | Cualquiera |
| 19 | %#v | Imprime el valor en formato completo de sintaxis Go | Cualquiera |
| 20 | %t | Imprime valor booleano | Booleano |
| 21 | %T | Imprime el tipo Go correspondiente al valor | Cualquiera |
| 22 | %c | Imprime el carácter correspondiente al código Unicode | int32 |
| 23 | %U | Imprime el código Unicode correspondiente al carácter | rune,byte |
| 24 | %p | Imprime la dirección apuntada por el puntero | Puntero |
Usa fmt.Sprintf o fmt.Printf para formatear cadenas o imprimir cadenas formateadas, veamos algunos ejemplos
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{})Al usar otras bases, agregar un espacio entre % y el verbo de formateo puede lograr el efecto de separador, por ejemplo
func main() {
str := "abcdefg"
fmt.Printf("%x\n", str)
fmt.Printf("% x\n", str)
}El resultado de este ejemplo es
61626364656667
61 62 63 64 65 66 67Al usar números, también se puede agregar ceros automáticamente. Por ejemplo
fmt.Printf("%09d", 1)
// 000000001Igual para binario
fmt.Printf("%09b", 1<<3)
// 000001000Casos de error
Cantidad de caracteres de formateo < cantidad de parámetros
fmt.Printf("", "") //%!(EXTRA string=)Cantidad de caracteres de formateo > cantidad de parámetros
fmt.Printf("%s%s", "") //%!s(MISSING)Tipo no coincidente
fmt.Printf("%s", 1) //%!s(int=1)Falta verbo de formateo
fmt.Printf("%", 1) // %!(NOVERB)%!(EXTRA int=1)Entrada
A continuación se presentan métodos comunes de entrada
read
Puedes leer el contenido de entrada directamente como si leyeras un archivo, de la siguiente manera
func main() {
var buf [1024]byte
n, _ := os.Stdin.Read(buf[:])
os.Stdout.Write(buf[:n])
}Es muy engorroso de usar, generalmente no se recomienda.
fmt
Podemos usar varias funciones proporcionadas por el paquete fmt, se usan de manera similar a C.
// Escanea el texto leído de os.Stdin, separa por espacios, el salto de línea también se considera espacio
func Scan(a ...any) (n int, err error)
// Similar a Scan, pero detiene el escaneo al encontrar un salto de línea
func Scanln(a ...any) (n int, err error)
// Escanea según una cadena de formateo
func Scanf(format string, a ...any) (n int, err error)Leer dos números
func main() {
var a, b int
fmt.Scanln(&a, &b)
fmt.Printf("%d + %d = %d\n", a, b, a+b)
}Leer un array de longitud fija
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
Cuando hay mucha entrada para leer, se recomienda usar bufio.Reader para leer el contenido
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 es similar a bufio.Reader, pero lee línea por línea.
func main() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
if line == "exit" {
break
}
fmt.Println("scan", line)
}
}El resultado es
first line
scan first line
second line
scan second line
third line
scan third line
exitTIP
En cuanto a entrada y salida, si quieres practicar, ve a Luogu y resuelve algunos problemas de algoritmos simples en modo ACM para familiarizarte.
