Chuỗi định dạng và các tham số
Các hàm thuộc họ *printf đều hỗ trợ tham số định dạng format, ở đây chúng ta sẽ phân loại theo từng placeholder để dễ dàng tra cứu và ghi nhớ.
Placeholder chung
| Placeholder | Mô tả |
|---|---|
| %v | Biểu diễn mặc định của giá trị |
| %+v | Tương tự %v nhưng khi in cấu trúc (struct) sẽ thêm tên trường |
| %#v | Biểu diễn cú pháp Go của giá trị |
| %T | In kiểu dữ liệu của giá trị |
| %% | Ký hiệu phần trăm |
Ví dụ mã nguồn:
package main
import "fmt"
func main() {
fmt.Printf("%v\n", 100)
fmt.Printf("%v\n", true)
o := struct{ ten string }{"Ngôi Sao Nhỏ"}
fmt.Printf("%v\n", o)
fmt.Printf("%#v\n", o)
fmt.Printf("%T\n", o)
fmt.Printf("100%%\n")
}
Kết quả đầu ra:
100
true
{Ngôi Sao Nhỏ}
struct { ten string }{ten:"Ngôi Sao Nhỏ"}
struct { ten string }
100%
Kiểu Boolean
| Placeholder | Mô tả |
|---|---|
| %t | true hoặc false |
Kiểu Số Nguyên
| Placeholder | Mô tả |
|---|---|
| %b | Biểu diễn dưới dạng nhị phân |
| %c | Giá trị tương ứng với ký tự Unicode |
| %d | Biểu diễn dưới dạng thập phân |
| %o | Biểu diễn dưới dạng bát phân |
| %x | Biểu diễn dưới dạng thập lục phân (chữ cái a-f) |
| %X | Biểu diễn dưới dạng thập lục phân (chữ cái A-F) |
| %U | Biểu diễn dưới dạng Unicode: U+1234 |
| %q | Biểu diễn dưới dạng ký tự đơn với dấu ngoặc đơn, nếu cần sẽ có escape sequence an toàn |
package main
import "fmt"
func main() {
so := 65
fmt.Printf("%b\n", so)
fmt.Printf("%c\n", so)
fmt.Printf("%d\n", so)
fmt.Printf("%o\n", so)
fmt.Printf("%x\n", so)
fmt.Printf("%X\n", so)
}
Kết quả đầu ra:
1000001
A
65
101
41
41
Số Thực và Số Phức
| Placeholder | Mô tả |
|---|---|
| %b | Định dạng khoa học không phần thập phân, chỉ số mũ nhị phân, ví dụ -123456p-78 |
| %e | Định dạng khoa học, ví dụ -1234.456e+78 |
| %E | Định dạng khoa học, ví dụ -1234.456E+78 |
| %f | Có phần thập phân nhưng không có số mũ, ví dụ 123.456 |
| %F | Tương đương với %f |
| %g | Chọn giữa %e hoặc %f tùy vào độ chính xác và gọn hơn |
| %G | Chọn giữa %E hoặc %F tùy vào độ chính xác và gọn hơn |
package main
import "fmt"
func main() {
f := 12.34
fmt.Printf("%b\n", f)
fmt.Printf("%e\n", f)
fmt.Printf("%E\n", f)
fmt.Printf("%f\n", f)
fmt.Printf("%g\n", f)
fmt.Printf("%G\n", f)
}
Kết quả đầu ra:
6946802425218990p-49
1.234000e+01
1.234000E+01
12.340000
12.34
12.34
Chuỗi và []byte
| Placeholder | Mô tả |
|---|---|
| %s | In trực tiếp chuỗi hoặc []byte |
| %q | Biểu diễn dưới dạng chuỗi với dấu ngoặc kép, nếu cần sẽ có escape sequence an toàn |
| %x | Mỗi byte được biểu diễn bằng hai ký tự thập lục phân (chữ cái a-f) |
| %X | Mỗi byte được biểu diễn bằng hai ký tự thập lục phân (chữ cái A-F) |
package main
import "fmt"
func main() {
s := "Ngôi Sao Nhỏ"
fmt.Printf("%s\n", s)
fmt.Printf("%q\n", s)
fmt.Printf("%x\n", s)
fmt.Printf("%X\n", s)
}
Kết quả đầu ra:
Ngôi Sao Nhỏ
"Ngôi Sao Nhỏ"
e5b08fe78e8be5ad90
E5B08FE78E8BE5AD90
Con Trỏ
| Placeholder | Mô tả |
|---|---|
| %p | Biểu diễn dưới dạng thập lục phân kèm tiền tố 0x |
package main
import "fmt"
func main() {
a := 10
fmt.Printf("%p\n", &a)
fmt.Printf("%#p\n", &a)
}
Kết quả đầu ra:
0xc000094000
c000094000
Biểu thức Chiều Rộng
Chiều rộng được chỉ định bởi một số thập phân ngay sau dấu %. Nếu không chỉ định chiều rộng, giá trị sẽ được biểu diễn mà không có bất kỳ khoảng trống nào bổ sung. Độ chính xác được chỉ định bởi số thập phân sau dấu chấm. Nếu không chỉ định độ chính xác, giá trị mặc định sẽ được sử dụng; nếu dấu chấm không đi kèm số thì độ chính xác là 0.
package main
import "fmt"
func main() {
n := 12.34
fmt.Printf("%f\n", n)
fmt.Printf("%9f\n", n)
fmt.Printf("%.2f\n", n)
fmt.Printf("%9.2f\n", n)
fmt.Printf("%9.f\n", n)
}
Kết quả đầu ra:
12.340000
12.340000
12.34
12.34
12
Các Flag Khác
| Placeholder | Mô tả |
|---|---|
| ’+’ | Lúc nào cũng hiển thị dấu dương hoặc âm của số; đối với %q (%+q), nó tạo ra một chuỗi hoàn toàn gồm các ký tự ASCII (bằng cách thoát). |
| ’ ‘ | Đối với số, thêm dấu cách trước số dương và dấu trừ trước số âm; đối với chuỗi khi dùng %x hoặc %X (% x hoặc % X), mỗi byte được in ra sẽ có dấu cách giữa chúng. |
| ’-’ | Thêm khoảng trắng bên phải thay vì bên trái (chuyển từ căn lề phải sang căn lề trái). |
| ’#’ | Thực hiện thêm tiền tố 0 cho số bát phân (%#o), tiền tố 0x cho số thập lục phân (%#x) hoặc 0X cho số thập lục phân viết hoa (%#X); bỏ tiền tố 0x đối với con trỏ (%#p). |
| ‘0’ | Sử dụng số 0 thay vì khoảng trắng để điền vào, đối với kiểu số, số 0 sẽ được đặt sau dấu cộng hoặc trừ. |
package main
import "fmt"
func main() {
s := "Ngôi Sao Nhỏ"
fmt.Printf("%s\n", s)
fmt.Printf("%5s\n", s)
fmt.Printf("%-5s\n", s)
fmt.Printf("%5.7s\n", s)
fmt.Printf("%-5.7s\n", s)
fmt.Printf("%5.2s\n", s)
fmt.Printf("%05s\n", s)
}
Kết quả đầu ra:
Ngôi Sao Nhỏ
Ngôi Sao Nhỏ
Ngôi Sao Nhỏ
Ngôi Sao Nhỏ
Ngôi Sao Nhỏ
Ngôi Sa
00Ngôi Sao Nhỏ
Nhập Dữ Liệu
Trong gói fmt của Go, có ba hàm fmt.Scan, fmt.Scanf, và fmt.Scanln giúp lấy dữ liệu từ người dùng trong quá trình chạy chương trình.
fmt.Scan
Hàm định nghĩa như sau:
func Scan(a ...interface{}) (n int, err error)
- Scan quét văn bản từ đầu vào chuẩn, đọc các giá trị được phân tách bởi khoảng trắng và lưu vào các tham số truyền vào.
- Hàm trả về số lượng dữ liệu đã quét thành công và lỗi nếu có.
Ví dụ mã nguồn:
package main
import "fmt"
func main() {
var (
ten string
tuoi int
ketHon bool
)
fmt.Scan(&ten, &tuoi, &ketHon)
fmt.Printf("Kết quả quét ten:%s tuoi:%d ketHon:%t \n", ten, tuoi, ketHon)
}
Chạy đoạn mã trên trong terminal và nhập lần lượt Ngôi Sao Nhỏ, 28, false với dấu cách làm phân cách.
$ ./scan_demo
Ngôi Sao Nhỏ 28 false
Kết quả quét ten:Ngôi Sao Nhỏ tuoi:28 ketHon:false
fmt.Scan quét dữ liệu từ đầu vào chuẩn và lưu các giá trị được phân tách bởi khoảng trắng vào các tham số được chỉ định.
fmt.Scanf
Hàm định nghĩa như sau:
func Scanf(format string, a ...interface{}) (n int, err error)
- Scanf quét văn bản từ đầu vào chuẩn, đọc các giá trị dựa trên định dạng được chỉ định và lưu vào các tham số truyền vào.
- Hàm trả về số lượng dữ liệu đã quét thành công và lỗi nếu có.
Ví dụ mã nguồn:
package main
import "fmt"
func main() {
var (
ten string
tuoi int
ketHon bool
)
fmt.Scanf("1:%s 2:%d 3:%t", &ten, &tuoi, &ketHon)
fmt.Printf("Kết quả quét ten:%s tuoi:%d ketHon:%t \n", ten, tuoi, ketHon)
}
Chạy đoạn mã trên trong terminal và nhập theo đúng định dạng được yêu cầu.
$ ./scan_demo
1:Ngôi Sao Nhỏ 2:28 3:false
Kết quả quét ten:Ngôi Sao Nhỏ tuoi:28 ketHon:false
fmt.Scanf khác với fmt.Scan ở chỗ nó yêu cầu dữ liệu phải tuân theo định dạng cụ thể được chỉ định.
fmt.Scanln
Hàm định nghĩa như sau:
func Scanln(a ...interface{}) (n int, err error)
- Scanln hoạt động tương tự Scan nhưng chỉ dừng quét khi gặp dòng mới.
- Hàm trả về số lượng dữ liệu đã quét thành công và lỗi nếu có.
Ví dụ mã nguồn:
package main
import "fmt"
func main() {
var (
ten string
tuoi int
ketHon bool
)
fmt.Scanln(&ten, &tuoi, &ketHon)
fmt.Printf("Kết quả quét ten:%s tuoi:%d ketHon:%t \n", ten, tuoi, ketHon)
}
Chạy đoạn mã trên trong terminal và nhập lần lượt Ngôi Sao Nhỏ, 28, false với dấu cách làm phân cách.
$ ./scan_demo
Ngôi Sao Nhỏ 28 false
Kết quả quét ten:Ngôi Sao Nhỏ tuoi:28 ketHon:false
fmt.Scanln dừng quét khi gặp dòng mới.
bufio.NewReader
Khi bạn muốn nhận toàn bộ nội dung đầu vào, kể cả khi nó chứa dấu cách, bạn có thể sử dụng gói bufio. Ví dụ mã nguồn:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin) // Tạo đối tượng đọc từ đầu vào chuẩn
fmt.Print("Nhập nội dung:")
text, _ := reader.ReadString('\n') // Đọc đến khi gặp dòng mới
text = strings.TrimSpace(text)
fmt.Printf("%#v\n", text)
}
Fscan Series
Các hàm này tương tự như fmt.Scan, fmt.Scanf, và fmt.Scanln, nhưng thay vì đọc từ đầu vào chuẩn, chúng đọc từ io.Reader.
func Fscan(r io.Reader, a ...interface{}) (n int, err error)
func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
Sscan Series
Các hàm này tương tự như fmt.Scan, fmt.Scanf, và fmt.Scanln, nhưng thay vì đọc từ đầu vào chuẩn, chúng đọc từ chuỗi được chỉ định.
func Sscan(str string, a ...interface{}) (n int, err error)
func Sscanln(str string, a ...interface{}) (n int, err error)
func Sscanf(str string, format string, a ...interface{}) (n int, err error)