Bài học theo mô-đun (1/5)
`fmt` nâng cao
Gói fmt là cổng vào tất cả I/O văn bản trong Go. Biết rõ về nó có nghĩa là viết nhật ký có thể đọc được, các lỗi thông tin và định dạng các giá trị một cách thành ngữ mà không cần dùng đến các thư viện bên ngoài.
Bốn gia đình
fmt hiển thị các hàm trong bốn họ, được phân biệt bằng tiền tố:
Print*→ viết vàoos.Stdout(Print,Println,Printf).Fprint*→ ghi vàoio.Writerbất kỳ (Fprintln(os.Stderr, ...),Fprintf(file, ...)).Sprint*→ trả về chuỗi không in (Sprintf,Sprintln).Errorf→ tạo mộterrorđược định dạng.
fmt.Println("hello") // stdout
fmt.Fprintln(os.Stderr, "boom") // stderr
s := fmt.Sprintf("[%d]", 42) // "[42]"
err := fmt.Errorf("parse %q: %w", in, base) // wrapped errorSự khác biệt giữa Print và Println chỉ là khoảng cách giữa các đối số và dòng mới ở cuối: Println luôn thêm \n, Print không, Printf tuân theo định dạng.
Động từ chính
| Động từ | Nó làm gì |
|---|---|
%v | Giá trị mặc định (gọi String() nếu được triển khai). |
%+v | Cấu trúc với tên trường. |
%#v | Cú pháp Go (hữu ích cho việc gỡ lỗi và chụp ảnh nhanh). |
%T | Loại động của giá trị. |
%d | Số nguyên trong cơ số 10. |
%b %o %x %X | Nhị phân, bát phân, thập lục phân (chữ thường/chữ hoa). |
%f %e %g | Điểm nổi: cố định, hàm mũ, nhỏ gọn. |
%s | Chuỗi (hoặc error/Stringer). |
%q | Chuỗi được trích dẫn kiểu Go (bao gồm các ký tự thoát). |
%c | Ký tự Unicode (rune). |
%p | Con trỏ ở dạng thập lục phân. |
%w | Lỗi gói (chỉ bên trong Errorf). |
type Point struct{ X, Y int }
p := Point{1, 2}
fmt.Printf("%v\n", p) // {1 2}
fmt.Printf("%+v\n", p) // {X:1 Y:2}
fmt.Printf("%#v\n", p) // main.Point{X:1, Y:2}
fmt.Printf("%T\n", p) // main.PointChiều rộng, độ chính xác, cờ
Động từ dạng số và chuỗi chấp nhận độ rộng và độ chính xác:
%6d→ chiều rộng tối thiểu 6, phần đệm bên trái có khoảng trắng.%-6d→ chiều rộng 6, phần đệm bên phải (cờ-).%06d→ chiều rộng 6, đệm bằng0(cờ0).%.2f→ độ chính xác 2 chữ số thập phân.%8.2f→ chiều rộng 8, độ chính xác 2.
fmt.Printf("|%6d|\n", 42) // | 42|
fmt.Printf("|%-6d|\n", 42) // |42 |
fmt.Printf("|%06d|\n", 42) // |000042|
fmt.Printf("|%8.2f|\n", 3.14)// | 3.14|Đối với các bảng đã căn chỉnh, chiều rộng cố định + %-...s cho cột văn bản là mẫu đơn giản nhất trước khi chuyển sang text/tabwriter.
%w và gói lỗi
%w rất đặc biệt: nó chỉ hoạt động bên trong fmt.Errorf và giữ nguyên lỗi ban đầu trong chuỗi, để errors.Is và errors.As có thể thực hiện được.
if _, err := os.Open(path); err != nil {
return fmt.Errorf("read config %q: %w", path, err)
}Sử dụng %v thay vì %w in thông báo lỗi nhưng làm đứt chuỗi: không mở gói, không errors.Is. Quy tắc: nếu bạn muốn người gọi có thể phân biệt loại hoặc nhận dạng lỗi, hãy sử dụng %w (chỉ một lỗi cho mỗi Errorf).
Bài tập
Sử dụng fmt.Sprintf để định dạng chuỗi '[42]' từ số nguyên 42, sau đó in nó.
Giải pháp khả dụng sau 3 lần thử
In cấu trúc p với động từ %+v (nó phải bao gồm tên trường).
Giải pháp khả dụng sau 3 lần thử
Động từ nào, được sử dụng trong fmt.Errorf, bảo toàn chuỗi lỗi cho các lỗi.Is/As?
err := fmt.Errorf("read %q: ???", path, base)