Chuyển đến nội dung chính
Mô-đun 8 · Bài học 3 trong tổng số 538/50 trong khóa học~14 min
Bài học theo mô-đun (3/5)

`io` và `os`: tập tin và luồng

Đọc và ghi tệp và luồng trong Go xoay quanh hai gói bổ sung: os (mở, tạo, siêu dữ liệu, quy trình) và io (giao diện Reader/Writer trừu tượng hóa mọi nguồn byte).

Đọc và ghi tập tin: các phím tắt

Đối với các tệp nhỏ hoặc cấu hình, một lệnh gọi là đủ:

Go
data, err := os.ReadFile("input.txt")        // returns []byte
if err != nil {
    return err
}
fmt.Println(string(data))

err = os.WriteFile("out.txt", []byte("ciao"), 0644)

os.ReadFile mở, đọc mọi thứ vào bộ nhớ và đóng lại. Hoàn hảo lên tới vài MB; Ngoài ra, phát trực tuyến tốt hơn.

Mở tập tin để phát trực tuyến

Đối với các tệp lớn hoặc quyền truy cập gia tăng, hãy mở tệp và đóng tệp bằng defer:

Go
f, err := os.Open("big.txt")        // read-only
if err != nil {
    return err
}
defer f.Close()

buf := make([]byte, 4096)
for {
    n, err := f.Read(buf)
    if n > 0 {
        process(buf[:n])
    }
    if err == io.EOF {
        break
    }
    if err != nil {
        return err
    }
}

os.Open mở ở chế độ chỉ đọc. Để viết, hãy sử dụng os.Create (cắt ngắn nếu nó tồn tại) hoặc os.OpenFile(path, flag, perm) với các cờ như os.O_APPEND | os.O_CREATE | os.O_WRONLY.

io.Reader và io.Writer: giao diện phổ quát

Go
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }

Bất cứ nơi nào thư viện chuẩn chấp nhận io.Reader, bạn có thể truyền một tệp (*os.File), một chuỗi (strings.NewReader), *bytes.Buffer, một phản hồi HTTP (resp.Body), một bộ giải nén... Điều tương tự cũng xảy ra với io.Writer.

Go
// Copy from a Reader to a Writer (e.g. download → file).
n, err := io.Copy(dst, src)

io.Copy là đặc điểm chính của đường dẫn byte: nó xử lý việc đệm và EOF một cách chính xác. io.ReadAll(r) đọc mọi thứ cho đến khi EOF thành []byte.

os.Args: Đối số CLI

os.Args là một đoạn chuỗi: chỉ mục 0 là tên chương trình, từ 1 trên các đối số thực tế:

Go
func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "uso: prog <nome>")
        os.Exit(1)
    }
    fmt.Println("ciao", os.Args[1])
}

Để phân tích cú pháp có cấu trúc hơn (cờ, mặc định, trợ giúp), hãy sử dụng gói flag từ stdlib hoặc các thư viện bên ngoài như cobra.

os.Stdin, os.Stdout, os.Stderr

Đây là ba *os.File toàn cầu: bất cứ nơi nào io.Reader hoặc io.Writer được chấp nhận, bạn có thể vượt qua chúng.

Go
fmt.Fprintln(os.Stderr, "log diagnostico")
io.Copy(os.Stdout, os.Stdin)  // echo

Bài tập

tập thể dục#go.m8.l3.e1
Nỗ lực: 0Đang tải…

In đối số dòng lệnh đầu tiên (os.Args[1]). Nếu thiếu, hãy in 'manca argomento' và trả lại.

Đang tải trình chỉnh sửa…

Giải pháp khả dụng sau 3 lần thử

tập thể dục#go.m8.l3.e2
Nỗ lực: 0Đang tải…

Viết chuỗi 'ciao' vào tệp 'out.txt' bằng os.WriteFile (quyền 0644). Xử lý lỗi.

Đang tải trình chỉnh sửa…

Giải pháp khả dụng sau 3 lần thử

Quiz#go.m8.l3.e3
Sẵn sàng

Chỉ mục của TÊN CHƯƠNG TRÌNH trong os.Args là gì?

Go
fmt.Println(os.Args[???])
Tùy chọn trả lời