1. مبانی کتابخانه OS
بسته os
در زبان گولانگ واسطی مستقل از پلتفرم برای انجام عملیات سیستم عامل فراهم میکند. در ادامه، به بحث درباره استفاده از بسته os
برای انجام عملیاتهای باز کردن، بستن، خواندن، نوشتن فایل و همچنین به دست آوردن و تنظیم ویژگیهای فایل خواهیم پرداخت.
1.1 باز کردن و بستن فایلها
در زبان گولانگ، میتوانید از تابع os.Open
برای باز کردن یک فایل استفاده کنید که یک شیء *os.File
و یک خطا برمیگرداند. پس از باز شدن فایل، میتوانید عملیات خواندن، نوشتن و دیگر عملیاتها را انجام دهید. پس از انجام عملیات، باید file.Close
را فراخوانی کنید تا فایل بسته شده و منابع مربوطه آزاد شود.
در زیر مثالی از باز کردن یک فایل آمده است:
package main
import (
"fmt"
"os"
)
func main() {
// باز کردن فایل test.txt در دایرکتوری فعلی
file, err := os.Open("test.txt")
if err != nil {
// رفع خطای باز کردن فایل
fmt.Println("خطا در باز کردن فایل:", err)
return
}
// استفاده از بیانه defer برای اطمینان از بستن فایل در نهایت
defer file.Close()
// عملیاتهای دستورات...
fmt.Println("فایل با موفقیت باز شد")
}
در کد فوق، از بیانه defer
برای اطمینان از اجرای file.Close
در هر حالتی استفاده شده است. این یک شیوه رایج در زبان گولانگ برای پاکسازی منابع است.
1.2 عملیات خواندن و نوشتن فایل
نوع os.File
دارای متدهای Read
و Write
است که برای عملیات خواندن و نوشتن فایل مورد استفاده قرار میگیرند. متد Read
دادهها را از فایل به یک برش بایت میخواند و متد Write
دادهها را از یک برش بایت به فایل مینویسد.
مثال زیر نحوه خواندن و نوشتن از یک فایل را نشان میدهد:
package main
import (
"fmt"
"os"
)
func main() {
// باز کردن فایل
file, err := os.OpenFile("test.txt", os.O_RDWR, 0644)
if err != nil {
fmt.Println("خطا در باز کردن فایل:", err)
return
}
defer file.Close()
// نوشتن محتوای فایل
message := []byte("سلام، گوفرها!")
_, writeErr := file.Write(message)
if writeErr != nil {
fmt.Println("خطا در نوشتن فایل:", writeErr)
return
}
// خواندن فایل از ابتدا
file.Seek(0, 0)
buffer := make([]byte, len(message))
_, readErr := file.Read(buffer)
if readErr != nil {
fmt.Println("خطا در خواندن فایل:", readErr)
return
}
fmt.Println("محتوای فایل:", string(buffer))
}
در این مثال، از os.OpenFile
به جای os.Open
استفاده شده است. تابع os.OpenFile
به شما امکان مشخص کردن حالت و دسترسیهای استفاده شده برای باز کردن فایل را میدهد. در مثال بالا، از پرچم os.O_RDWR
استفاده شده است که به معنای باز کردن فایل در حالت خواندن و نوشتن است.
۱.۳ ویژگیها و مجوزهای فایل
شما میتوانید از توابع بسته os
برای دسترسی و تغییر اطلاعات وضعیت فایل استفاده کنید. از os.Stat
یا os.Lstat
برای به دست آوردن رابط os.FileInfo
استفاده کنید که اطلاعاتی از همانند اندازه، مجوزها، زمان اصلاح و ... را ارائه میدهد.
اینجا یک نمونه از چگونگی به دست آوردن وضعیت فایل است:
package main
import (
"fmt"
"os"
)
func main() {
fileInfo, err := os.Stat("test.txt")
if err != nil {
fmt.Println("Error getting file information:", err)
return
}
// Print file size
fmt.Printf("File size: %d bytes\n", fileInfo.Size())
// Print file permissions
fmt.Printf("File permissions: %s\n", fileInfo.Mode())
}
اگر نیاز به تغییر نام فایل یا تغییر مجوزهای فایل داشته باشید، میتوانید از os.Rename
برای تغییر نام فایل و از os.Chmod
برای تغییر مجوزهای فایل استفاده کنید.
package main
import (
"fmt"
"os"
)
func main() {
// تغییر دادن مجوزهای فایل به فقطخواندنی
err := os.Chmod("test.txt", 0444)
if err != nil {
fmt.Println("Error changing file permissions:", err)
return
}
// تغییر نام فایل
renameErr := os.Rename("test.txt", "renamed.txt")
if renameErr != nil {
fmt.Println("Error renaming file:", renameErr)
return
}
fmt.Println("File operations successful")
}
در اینجا، ما مجوزهای فایل test.txt
را به حالت فقطخواندنی تغییر میدهیم و سپس فایل را به renamed.txt
تغییر نام میدهیم. توجه کنید که هنگام تغییر مجوزهای فایل، باید محتاط باشید، زیرا تنظیمات نادرست مجوز ممکن است به فایلهای قابل دسترسی ناممکن منجر شود.
۲. استفاده ابتدایی از کتابخانه IO
در زبان Go، کتابخانه io
رابطهای ابتدایی را برای ابزارهای ورودی/خروجی (عملیات ورودی/خروجی) فراهم میکند. طراحی کتابخانهی io
از اصول سادگی و رابطهای یکنواخت پیروی میکند و پشتیبانی ابتدایی را برای انواع مختلف عملیات I/O مانند خواندن/نوشتن فایل، ارتباط شبکه، بافرهای داده و ... فراهم میکند.
۲.۲ استفاده از رابطهای Reader و Writer
io.Reader
و io.Writer
دو رابط ابتدایی برای تعیین عملیات خواندن و نوشتن یک شی میباشند. آنها توسط انواع مختلفی مانند فایلها، اتصالات شبکه و بافرها پیادهسازی میشوند.
io.Reader
رابط io.Reader
دارای یک متد بنام Read است:
Read(p []byte) (n int, err error)
این متد تا len(p)
بایت داده را از io.Reader
به p
میخواند. تعداد بایتهای خوانده شده n
(0 <= n
<= len(p
)) و هر خطایی را که برخورده شود برمیگرداند.
کد نمونه:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("Hello, World!")
buf := make([]byte, 4)
for {
n, err := r.Read(buf)
if err == io.EOF {
break
}
fmt.Printf("Bytes read: %d, Content: %s\n", n, buf[:n])
}
}
در این مثال، ما یک strings.NewReader
ایجاد میکنیم تا داده را از یک رشته بخوانیم و سپس داده را به اندازه 4 بایت میخوانیم.
io.Writer
رابط io.Writer
دارای یک متد بنام Write است:
Write(p []byte) (n int, err error)
این متد داده را از p
به جریان دادهی زیرین مینویسد و تعداد بایتهای نوشته شده و هر خطایی را که برخورده شود برمیگرداند.
کد نمونه:
package main
import (
"fmt"
"os"
)
func main() {
data := []byte("Hello, World!\n")
n, err := os.Stdout.Write(data)
if err != nil {
panic(err)
}
fmt.Printf("Bytes written: %d\n", n)
}
در این مثال، یک رشته ساده را به خروجی استاندارد os.Stdout
که به عنوان یک پیادهسازی از io.Writer
عمل میکند، مینویسد.
2.3 توابع پیشرفته خواندن/نوشتن
بسته io
تعدادی توابع پیشرفته را فراهم میکند که میتواند وظایف مشترک را سادهتر کند، مانند کپی کردن داده و خواندن مقدار مشخصی از داده.
تابع کپی
io.Copy
یک روش مفید برای مستقیم کپی کردن داده از یک io.Reader
به یک io.Writer
بدون نیاز به یک بافر واسط است.
کد نمونه:
package main
import (
"io"
"os"
"strings"
)
func main() {
r := strings.NewReader("مثال عملیات کپی ساده")
_, err := io.Copy(os.Stdout, r)
if err != nil {
panic(err)
}
}
در این مثال، ما مستقیما یک رشته را به خروجی استاندارد کپی میکنیم.
تابع ReadAtLeast
تابع io.ReadAtLeast
برای اطمینان از اینکه حداقل یک مقدار مشخصی از یک io.Reader
قبل از بازگشت خوانده شود، استفاده میشود.
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
کد نمونه:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("وبسایت Go Language به زبان چینی")
buf := make([]byte, 14)
n, err := io.ReadAtLeast(r, buf, 14)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", buf[:n])
}
در این مثال، io.ReadAtLeast
تلاش میکند حداقل ۱۴ بایت داده را به buf
بخواند.
این توابع پیشرفته خواندن/نوشتن به شما امکان میدهد که وظایف مربوط به ورودی/خروجی را به صورت موثرتر مدیریت کرده و پایهای قوی برای ساخت منطق برنامههای پیچیدهتر فراهم میکند.