1. พื้นฐานของไลบรารี OS

แพ็คเกจ os ใน Golang มีการให้บริการอินเทอร์เฟซที่ไม่ขึ้นอยู่กับแพลตฟอร์มสำหรับฟังก์ชันของระบบปฏิบัติการ ต่อไปนี้เราจะพูดถึงวิธีการใช้แพ็คเกจ os ในการจัดการเปิดไฟล์ ปิดไฟล์ อ่าน เขียน รวมถึงการรับและตั้งค่าแอตทริบิวต์ของไฟล์

1.1 เปิดและปิดไฟล์

ใน Go language คุณสามารถใช้ฟังก์ชัน 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 statement เพื่อให้แน่ใจว่าไฟล์จะถูกปิดในที่สุด
    defer file.Close()

    // ดำเนินการกับไฟล์...

    fmt.Println("เปิดไฟล์สำเร็จ")
}

ในโค้ดข้างต้น เราใช้ defer statement เพื่อให้แน่ใจว่า file.Close จะถูกประมาณ นี้เป็นการปฏิบัติที่พบใน Go language เพื่อทำความสะอาดทรัพยากร

1.2 การดำเนินการอ่านและเขียนไฟล์

ชนิดข้อมูล os.File มีเมธอด Read และ Write ซึ่งสามารถใช้สำหรับการดำเนินการอ่านและเขียนไฟล์ เมธอด Read อ่านข้อมูลจากไฟล์เข้าสู่ slice ของไบต์และเมธอด Write ทำการเขียนข้อมูลจาก slice ของไบต์ไปยังไฟล์

ตัวอย่างต่อไปนี้แสดงให้เห็นว่า การอ่านและเขียนไปยังไฟล์:

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 ซึ่งหมายความว่าไฟล์จะถูกเปิดในโหมดอ่าน-เขียน

1.3 คุณสมบัติและการอนุญาตของไฟล์

คุณสามารถใช้ฟังก์ชันจากแพ็คเกจ os เพื่อเข้าถึงและปรับเปลี่ยนข้อมูลสถานะของไฟล์ ใช้ os.Stat หรือ os.Lstat เพื่อรับ os.FileInfo interface ซึ่งให้ข้อมูลเกี่ยวกับไฟล์ เช่น ขนาด สิทธิ์การเข้าถึง วันเวลาการปรับเปลี่ยน และอื่น ๆ

นี่คือตัวอย่างการรับสถานะของไฟล์:

package main

import (
    "fmt"
    "os"
)

func main() {
    fileInfo, err := os.Stat("test.txt")
    if err != nil {
        fmt.Println("เกิดข้อผิดพลาดในการรับข้อมูลของไฟล์:", err)
        return
    }

    // พิมพ์ขนาดของไฟล์
    fmt.Printf("ขนาดของไฟล์: %d ไบต์\n", fileInfo.Size())

    // พิมพ์สิทธิ์การเข้าถึงของไฟล์
    fmt.Printf("สิทธิ์การเข้าถึงของไฟล์: %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("เกิดข้อผิดพลาดในการเปลี่ยนสิทธิ์การเข้าถึงของไฟล์:", err)
        return
    }

    // เปลี่ยนชื่อของไฟล์
    renameErr := os.Rename("test.txt", "renamed.txt")
    if renameErr != nil {
        fmt.Println("เกิดข้อผิดพลาดในการเปลี่ยนชื่อของไฟล์:", renameErr)
        return
    }
    
    fmt.Println("ดำเนินการกับไฟล์สำเร็จ")
}

ที่นี่ เราเปลี่ยนสิทธิ์การเข้าถึงของไฟล์ test.txt เป็นแบบอ่านอย่างเดียว และจากนั้นเปลี่ยนชื่อไฟล์เป็น renamed.txt โปรดทราบว่าเมื่อปรับเปลี่ยนสิทธิ์การเข้าถึงของไฟล์ ควรระมัดระวัง เนื่องจากการตั้งค่าสิทธิ์การเข้าถึงที่ไม่ถูกต้องอาจ导致ไฟล์ไม่สามารถเข้าถึงได้

2. การใช้งานพื้นฐานของไลบรารี IO

ในภาษา Go ไลบรารี io ให้ส่วนของพื้นฐานสำหรับ I/O primitives (การดำเนินการนำเข้า/การดำเนินการส่งออก) การออกแบบของไลบรารี io ทำตามหลักของความเรียบง่ายและการเชื่อมต่อที่สม่ำเสมอ ให้การสนับสนุนพื้นฐานสำหรับประเภทการดำเนินการ I/O ต่าง ๆ เช่น การอ่าน/เขียนไฟล์ การสื่อสารผ่านเครือข่าย การเตรียมข้อมูล และอื่น ๆ

2.2 การใช้งานอินเตอร์เฟซของการอ่านและเขียน

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("สวัสดี, โลก!")

    buf := make([]byte, 4)
    for {
        n, err := r.Read(buf)
        if err == io.EOF {
            break
        }
        fmt.Printf("อ่านไบต์: %d, เนื้อหา: %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("สวัสดี, โลก!\n")
    n, err := os.Stdout.Write(data)
    if err != nil {
        panic(err)
    }
    fmt.Printf("ไบต์ที่เขียน: %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)
    }
}

ในตัวอย่างนี้ เราได้ทำการคัดลอกข้อความไปที่ผลลัพธ์มาตรฐานโดยตรง

ฟังก์ชันการอ่านอย่างน้อย

ฟังก์ชัน 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 พยายามอ่านอย่างน้อย 14 ไบต์ข้อมูลเข้าไปใน buf

ฟังก์ชันการอ่าน/เขียนขั้นสูงเหล่านี้ช่วยให้คุณจัดการกับงานที่เกี่ยวข้องกับ I/O อย่างมีประสิทธิภาพมากขึ้น และให้พื้นฐานที่แข็งแกร่งสำหรับการสร้างตรรกะโปรแกรมที่ซับซ้อนมากขึ้น