Nhập xuất trong Go
package main
import "fmt"
func main() {
fmt.Println("Xin chào thế giới!")
}Ví dụ入门 đầu tiên của trang web này là xuất một chuỗi, phần này sẽ nói về cách thực hiện nhập xuất trong Go.
Mô tả tệp
var (
Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)Trong gói os có ba mô tả tệp được phơi bày bên ngoài, kiểu của chúng đều là *os.File, lần lượt là:
os.Stdin- Nhập chuẩnos.Stdout- Xuất chuẩnos.Stderr- Lỗi chuẩn
Nhập xuất trong Go đều không thể rời xa chúng.
Xuất
Trong Go có rất nhiều phương pháp xuất, dưới đây là một vài phương pháp phổ biến
stdout
Vì xuất chuẩn bản thân nó là một tệp, nên bạn có thể trực tiếp ghi chuỗi vào xuất chuẩn
package main
import "os"
func main() {
os.Stdout.WriteString("xin chào thế giới!")
}print
Go có hai hàm tích hợp print, println, chúng sẽ xuất tham số vào lỗi chuẩn, chỉ dùng để gỡ lỗi, thường không khuyến nghị sử dụng.
package main
func main() {
print("xin chào thế giới!\n")
println("xin chào thế giới")
}fmt
Cách dùng phổ biến nhất là sử dụng gói fmt, nó cung cấp hàm fmt.Println, hàm này mặc định sẽ xuất tham số vào xuất chuẩn.
package main
import "fmt"
func main() {
fmt.Println("xin chào thế giới!")
}Tham số của nó hỗ trợ bất kỳ kiểu nào, nếu kiểu thực hiện interface String cũng sẽ gọi phương thức String để lấy biểu diễn chuỗi của nó, nên nội dung mà nó xuất có khả năng đọc khá cao, phù hợp với hầu hết các tình huống, nhưng do bên trong dùng đến phản xạ, trong các tình huống nhạy cảm về hiệu năng không khuyến nghị sử dụng nhiều.
bufio
bufio cung cấp phương pháp xuất có thể đệm, nó sẽ trước tiên ghi dữ liệu vào bộ nhớ, tích lũy đến một ngưỡng nhất định rồi xuất vào Writer được chỉ định, kích thước đệm mặc định là 4KB. Khi IO tệp, IO mạng khuyến nghị sử dụng gói này.
func main() {
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
writer.WriteString("xin chào thế giới!")
}Bạn cũng có thể kết hợp nó với gói fmt để sử dụng
func main() {
writer := bufio.NewWriter(os.Stdout)
defer writer.Flush()
fmt.Fprintln(writer, "xin chào thế giới!")
}Định dạng
Chức năng xuất định dạng trong Go về cơ bản do hàm fmt.Printf cung cấp, nếu bạn đã học ngôn ngữ hệ C, chắc chắn sẽ cảm thấy rất quen thuộc, dưới đây là một ví dụ đơn giản.
func main() {
fmt.Printf("xin chào thế giới, %s!", "jack")
}Dưới đây là tất cả các động từ định dạng hiện có trong Go.
| 0 | Định dạng | Mô tả | Kiểu nhận |
|---|---|---|---|
| 1 | %% | Xuất dấu phần trăm % | Bất kỳ |
| 2 | %s | Xuất giá trị string/[] byte | string,[] byte |
| 3 | %q | Định dạng chuỗi, chuỗi xuất ra có dấu nháy kép "" ở hai đầu | string,[] byte |
| 4 | %d | Xuất giá trị số nguyên thập phân | Số nguyên |
| 5 | %f | Xuất số dấu phẩy động | Số dấu phẩy động |
| 6 | %e | Xuất dạng ký hiệu khoa học, cũng có thể dùng cho số phức | Số dấu phẩy động |
| 7 | %E | Giống với %e | Số dấu phẩy động |
| 8 | %g | Tự động phán đoán xuất %f hoặc %e theo tình hình thực tế, sẽ loại bỏ số 0 thừa | Số dấu phẩy động |
| 9 | %b | Xuất biểu diễn nhị phân của số nguyên | Số |
| 10 | %#b | Xuất biểu diễn nhị phân hoàn chỉnh | Số |
| 11 | %o | Xuất biểu diễn bát phân của số nguyên | Số nguyên |
| 12 | %#o | Xuất biểu diễn bát phân hoàn chỉnh của số nguyên | Số nguyên |
| 13 | %x | Xuất biểu diễn thập lục phân chữ thường của số nguyên | Số |
| 14 | %#x | Xuất biểu diễn thập lục phân chữ thường hoàn chỉnh của số nguyên | Số |
| 15 | %X | Xuất biểu diễn thập lục phân chữ hoa của số nguyên | Số |
| 16 | %#X | Xuất biểu diễn thập lục phân chữ hoa hoàn chỉnh của số nguyên | Số |
| 17 | %v | Xuất giá trị theo dạng ban đầu, thường dùng cho xuất cấu trúc dữ liệu | Bất kỳ |
| 18 | %+v | Xuất struct sẽ thêm tên trường | Bất kỳ |
| 19 | %#v | Xuất giá trị theo định dạng cú pháp Go hoàn chỉnh | Bất kỳ |
| 20 | %t | Xuất giá trị boolean | Boolean |
| 21 | %T | Xuất giá trị kiểu ngôn ngữ Go tương ứng | Bất kỳ |
| 22 | %c | Xuất ký tự tương ứng với mã Unicode | int32 |
| 23 | %U | Xuất mã Unicode tương ứng với ký tự | rune,byte |
| 24 | %p | Xuất địa chỉ mà con trỏ trỏ đến | Con trỏ |
Sử dụng fmt.Sprintf hoặc fmt.Printf để định dạng chuỗi hoặc xuất chuỗi định dạng, xem một vài ví dụ
fmt.Printf("%%%s\n", "xin chào thế giới")
fmt.Printf("%s\n", "xin chào thế giới")
fmt.Printf("%q\n", "xin chào thế giới")
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{})Khi sử dụng hệ cơ số khác, thêm một khoảng trắng giữa % và động từ định dạng là có thể đạt hiệu quả dấu phân cách, ví dụ
func main() {
str := "abcdefg"
fmt.Printf("%x\n", str)
fmt.Printf("% x\n", str)
}Kết quả xuất của ví dụ này là
61626364656667
61 62 63 64 65 66 67Khi sử dụng số, cũng có thể tự động bổ sung số 0. Ví dụ
fmt.Printf("%09d", 1)
// 000000001Nhị phân cũng tương tự
fmt.Printf("%09b", 1<<3)
// 000001000Tình huống lỗi
Số lượng ký tự định dạng < số lượng tham số
fmt.Printf("", "") //%!(EXTRA string=)Số lượng ký tự định dạng > số lượng tham số
fmt.Printf("%s%s", "") //%!s(MISSING)Kiểu không khớp
fmt.Printf("%s", 1) //%!s(int=1)Thiếu động từ định dạng
fmt.Printf("%", 1) // %!(NOVERB)%!(EXTRA int=1)Nhập
Dưới đây giới thiệu các phương pháp nhập phổ biến
read
Bạn có thể đọc nội dung nhập giống như đọc tệp trực tiếp, như sau
func main() {
var buf [1024]byte
n, _ := os.Stdin.Read(buf[:])
os.Stdout.Write(buf[:n])
}Cách dùng này quá phiền phức, thường không khuyến nghị sử dụng.
fmt
Chúng ta có thể sử dụng một vài hàm do gói fmt cung cấp, dùng gần giống như C.
// Quét văn bản đọc từ os.Stdin, phân cách theo khoảng trắng, xuống dòng cũng được coi là khoảng trắng
func Scan(a ...any) (n int, err error)
// Tương tự như Scan, nhưng gặp xuống dòng thì dừng quét
func Scanln(a ...any) (n int, err error)
// Quét theo chuỗi định dạng
func Scanf(format string, a ...any) (n int, err error)Đọc hai số
func main() {
var a, b int
fmt.Scanln(&a, &b)
fmt.Printf("%d + %d = %d\n", a, b, a+b)
}Đọc mảng độ dài cố định
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
Khi có một lượng lớn nhập cần đọc, khuyến nghị sử dụng bufio.Reader để đọc nội dung
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 tương tự như bufio.Reader, nhưng nó đọc theo dòng.
func main() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
if line == "exit" {
break
}
fmt.Println("scan", line)
}
}Kết quả như sau
first line
scan first line
second line
scan second line
third line
scan third line
exitTIP
Về mặt nhập xuất, nếu muốn luyện tập, hãy làm một vài bài toán thuật toán chế độ ACM đơn giản trên Luogu là có thể làm quen.
