- vừa được xem lúc

File I/O Trong Go

0 0 11

Người đăng: Toan Pham

Theo Viblo Asia

I. File I/O trong Go

Trong Go, có một số package cung cấp các công cụ và tiện ích để làm việc với file và I/O. Chúng ta sẽ tìm hiểu về các package chính và cách sử dụng chúng thông qua một số ví dụ.

Package os

Package os cung cấp một giao diện cho các chức năng cơ bản của hệ điều hành, bao gồm việc tạo, đọc, ghi và xóa file. Nó cũng cho phép quản lý thư mục và các tác vụ liên quan. Chúng ta có thể lấy ví dụ đơn giản về việc tạo một file mới:

file, err := os.Create("data.txt")
if err != nil { // Xử lý lỗi
}
defer file.Close()

Chúng ta thử xem kĩ hơn hàm Create trong package os

func Create(name string) (*File, error) { return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

Có thể thấy rằng hàm này nhận vào một chuỗi name đại diện cho tên (hoặc đường dẫn) của tệp cần tạo, gọi đến hàm OpenFile trả về một pointer đến một đối tượng File và một giá trị error. O_RDWR|O_CREATE|O_TRUNC: Đây là các hằng số định nghĩa cách mở tệp.O_RDWR nghĩa là mở tệp để đọc và ghi.O_CREATEnghĩa là tạo tệp nếu nó không tồn tại. O_TRUNC nghĩa là nếu tệp đã tồn tại, hãy cắt bỏ nội dung của nó (xóa hay ghi đè lên). 0666: Đây là quyền truy cập tệp. 0666 nghĩa là tất cả người dùng có thể đọc và ghi vào tệp.

Chúng ta cũng có thể mở một file bằng cách sử dụng hàm Open

file, err := os.Open("data.txt") if err != nil { // Xử lý lỗi
}
defer file.Close()

Một lần nữa hãy xem hàm Open của package os

func Open(name string) (*File, error) { return OpenFile(name, O_RDONLY, 0)
}

Có thể thấy Open cũng gọi đến hàm OpenFile, nhưng chúng truyền vào các tham số O_RDONLY, có nghĩa là tệp sẽ được mở chỉ để đọc. Nếu tệp không tồn tại, OpenFile sẽ trả về lỗi.

Đóng tệpfile.Close() giúp tránh vượt quá giới hạn tệp mở của hệ điều hành, đảm bảo dữ liệu được ghi từ bộ đệm vào tệp, và ngăn chặn lỗi khi các quá trình khác truy cập tệp.

Package io

Package io cung cấp các giao diện cơ bản cho việc đọc và ghi dữ liệu từ/đến các nguồn khác nhau, bao gồm cả file. Nó cũng cung cấp các công cụ hữu ích như io.Reader và io.Writer, ..

Ví dụ 1:

sourceFile, err := os.Open("source.txt")
if err != nil { // Xử lý lỗi
}
defer sourceFile.Close() destFile, err := os.Create("dest.txt")
if err != nil { // Xử lý lỗi
}
defer destFile.Close() _, err = io.Copy(destFile, sourceFile)
if err != nil { // Xử lý lỗi
}

Trong ví dụ này, chúng ta sử dụng hàm os.Open để mở file nguồnsource.txtos.Create để tạo file đích dest.txt. Sau đó, chúng ta sử dụng hàm io.Copy để sao chép dữ liệu từ file nguồn sang file đích.

Ví dụ 2:

file, err := os.Open("data.txt")
if err != nil { // Xử lý lỗi
}
data, err := io.ReadAll(file)
fmt.Println("Data: ", string(data)) 

Đoạn mã này mở file data.txt và đọc toàn bộ nội dung của nó vào bộ nhớ sử dụng io.ReadAll. Tuy nhiên, có một nhược điểm lớn với cách làm này, hãy xem hàm ReadAll của package io này nhé: image.png

Hàm ReadAll đọc toàn bộ dữ liệu từ một Reader vào một slice byte. Nó tạo một slice byte với cap (dung lượng) 512, sau đó liên tục đọc dữ liệu từ Reader vào slice cho đến khi không còn dữ liệu hoặc xảy ra lỗi. Nếu slice đầy, nó tăng dung lượng. Khi gặp EOF, hàm coi đó như kết thúc bình thường và trả về nil cho lỗi.

Vậy nên nếu tệp rất lớn (ví dụ: 10GB hoặc 1TB), việc đọc toàn bộ nội dung vào bộ nhớ sẽ dẫn đến lỗi tràn bộ nhớ và làm crash chương trình. Để giải quyết vấn đề này, chúng ta có thể sử dụng package bufio để đọc tệp theo từng phần. Điều này cho phép chúng ta xử lý từng phần của tệp mà không cần đọc toàn bộ nội dung của nó vào bộ nhớ cùng một lúc.

file, err := os.Open("data.txt")
if err != nil { // Xử lý lỗi
}
defer file.Close() scanner := bufio.NewScanner(file)
for scanner.Scan() { fmt.Println("Data: ", scanner.Text())
} if err := scanner.Err(); err != nil { fmt.Println("Error: ", err)
}

Trong đoạn mã này, chúng ta sử dụngbufio.NewScanner để tạo một Scanner mới cho tệp. Sau đó, chúng ta sử dụng phương thức Scan của Scanner để đọc từng dòng của tệp. Mỗi lần Scan trả về true, chúng ta in dòng đó ra console. Khi Scan trả về false, chúng ta kiểm tra xem có lỗi nào xảy ra trong quá trình quét tệp hay không bằng cách gọi scanner.Err().

**II. Kết Luận **

Như vậy, chúng ta đã sử dụng các package khác nhau cho File I/O trong Go. Từ tạo file mới với os, ghi nội dung với io, đọc file một cách hiệu quả với bufio, hiểu rõ hơn về các package này trong việc làm việc với file. Cám ơn các bạn đã đọc bài viết này.

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 131

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 56

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 60

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 237

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 54