File Operations

Go menyediakan berbagai package untuk operasi file seperti os, io, ioutil, dan path/filepath. Tutorial ini akan menunjukkan cara melakukan berbagai operasi file.

Contoh Masalah

Bagaimana cara:

  1. Membaca dan menulis file
  2. Mengelola direktori
  3. Mencari dan memfilter file
  4. Menangani path file

Penyelesaian

package main

import (
    "bufio"
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "path/filepath"
    "strings"
    "time"
)

// 1. Basic file operations
func basicFileOperations() error {
    // Create file
    file, err := os.Create("test.txt")
    if err != nil {
        return err
    }
    defer file.Close()

    // Write string
    content := "Hello, World!\nThis is a test file.\n"
    _, err = file.WriteString(content)
    if err != nil {
        return err
    }

    // Read entire file
    data, err := ioutil.ReadFile("test.txt")
    if err != nil {
        return err
    }
    fmt.Printf("File contents:\n%s", string(data))

    return nil
}

// 2. Buffered reading and writing
func bufferedOperations() error {
    // Write with buffer
    file, err := os.Create("buffered.txt")
    if err != nil {
        return err
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    for i := 0; i < 5; i++ {
        fmt.Fprintf(writer, "Line %d\n", i+1)
    }
    writer.Flush()

    // Read with buffer
    file, err = os.Open("buffered.txt")
    if err != nil {
        return err
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    for {
        line, err := reader.ReadString('\n')
        if err == io.EOF {
            break
        }
        if err != nil {
            return err
        }
        fmt.Printf("Read: %s", line)
    }

    return nil
}

// 3. Directory operations
func directoryOperations() error {
    // Create directory
    err := os.MkdirAll("testdir/subdir", 0755)
    if err != nil {
        return err
    }

    // Create some test files
    for i := 1; i <= 3; i++ {
        filename := fmt.Sprintf("testdir/file%d.txt", i)
        if err := ioutil.WriteFile(filename, []byte("test"), 0644); err != nil {
            return err
        }
    }

    // List directory
    files, err := ioutil.ReadDir("testdir")
    if err != nil {
        return err
    }

    fmt.Println("\nDirectory contents:")
    for _, file := range files {
        fmt.Printf("- %s (dir: %v, size: %d bytes)\n",
            file.Name(), file.IsDir(), file.Size())
    }

    return nil
}

// 4. File walking
func walkDirectory(root string) error {
    return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        
        rel, err := filepath.Rel(root, path)
        if err != nil {
            return err
        }

        fmt.Printf("%s: %d bytes\n", rel, info.Size())
        return nil
    })
}

// 5. File filtering
func findFiles(root, pattern string) ([]string, error) {
    var matches []string
    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if info.IsDir() {
            return nil
        }
        if matched, err := filepath.Match(pattern, filepath.Base(path)); err != nil {
            return err
        } else if matched {
            matches = append(matches, path)
        }
        return nil
    })
    return matches, err
}

// 6. File copy
func copyFile(src, dst string) error {
    source, err := os.Open(src)
    if err != nil {
        return err
    }
    defer source.Close()

    destination, err := os.Create(dst)
    if err != nil {
        return err
    }
    defer destination.Close()

    _, err = io.Copy(destination, source)
    return err
}

// 7. File watcher
func watchFile(filename string, duration time.Duration) error {
    initialStat, err := os.Stat(filename)
    if err != nil {
        return err
    }

    for {
        time.Sleep(duration)

        stat, err := os.Stat(filename)
        if err != nil {
            return err
        }

        if stat.ModTime() != initialStat.ModTime() {
            fmt.Printf("File %s has been modified\n", filename)
            initialStat = stat
        }
    }
}

func main() {
    // Basic file operations
    fmt.Println("Basic file operations:")
    if err := basicFileOperations(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    // Buffered operations
    fmt.Println("\nBuffered operations:")
    if err := bufferedOperations(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    // Directory operations
    fmt.Println("\nDirectory operations:")
    if err := directoryOperations(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    // Walk directory
    fmt.Println("\nWalking directory:")
    if err := walkDirectory("testdir"); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    // Find files
    fmt.Println("\nFinding files:")
    matches, err := findFiles("testdir", "*.txt")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
    } else {
        fmt.Println("Matching files:", strings.Join(matches, ", "))
    }

    // Copy file
    fmt.Println("\nCopying file:")
    if err := copyFile("test.txt", "test_copy.txt"); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    // Start file watcher in goroutine
    go func() {
        fmt.Println("\nWatching test.txt for changes...")
        if err := watchFile("test.txt", time.Second); err != nil {
            fmt.Printf("Error: %v\n", err)
        }
    }()

    // Cleanup
    time.Sleep(time.Second * 2)
    os.RemoveAll("testdir")
    os.Remove("test.txt")
    os.Remove("buffered.txt")
    os.Remove("test_copy.txt")
}

Penjelasan Kode

  1. Basic Operations

    • Create/Delete
    • Read/Write
    • File info
  2. Advanced Features

    • Buffered I/O
    • Directory walking
    • File watching
  3. Common Tasks

    • File copying
    • Pattern matching
    • Path manipulation

Output

Basic file operations:
File contents:
Hello, World!
This is a test file.

Buffered operations:
Read: Line 1
Read: Line 2
Read: Line 3
Read: Line 4
Read: Line 5

Directory operations:
Directory contents:
- file1.txt (dir: false, size: 4 bytes)
- file2.txt (dir: false, size: 4 bytes)
- file3.txt (dir: false, size: 4 bytes)
- subdir (dir: true, size: 0 bytes)

Walking directory:
.: 0 bytes
file1.txt: 4 bytes
file2.txt: 4 bytes
file3.txt: 4 bytes
subdir: 0 bytes

Finding files:
Matching files: testdir/file1.txt, testdir/file2.txt, testdir/file3.txt

Copying file:
File copied successfully

Watching test.txt for changes...

Tips

  • Selalu tutup file
  • Gunakan defer
  • Handle error dengan baik
  • Perhatikan permission
  • Gunakan path/filepath