Skip to content

Fayllar bilan ishlash

Fayllar bilan ishlash har qanday tizim dasturining muhim qismidir. Go da bu jarayon juda oson va xavfsiz tarzda amalga oshiriladi.

Go fayllar bilan ishlash uchun asosan quyidagi paketlardan foydalanadi:

  • os: Fayl yaratish, o'qish, yozish, o'chirish, ruxsatlar, stat kabi asosiy amallar uchun.
  • io: O'qish va yozishni standart interfeyslar orqali boshqarish uchun.
  • bufio: Qatorma-qator o'qish yoki buferli yozish uchun.
  • io/ioutil: (eskirgan) Yengil o'qish/yozish uchun. O'rniga os.ReadFile, os.WriteFile ishlatiladi

Fayl yaratish va yozish (os.WriteFile)

package main

import (
    "os"
    "fmt"
)

func main() {
    content := []byte("Bu Go tilida yozilgan fayl.\n")

    err := os.WriteFile("fayl.txt", content, 0644)
    if err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }
}

Natija:

fayl.txt fayl hosil bo'ladi.

Bu yerda:

  • content โ€” []byte (baytlardan iborat slice) tipidagi o'zgaruvchi.
  • "Bu Go tilida yozilgan fayl.\n" โ€” matn, uni faylga yozadi.
  • []byte(...) โ€” bu matnni baytlarga (kompyuter tushunadigan formatga) aylantiradi.
  • 0644 โ€” ruxsat kodi: egasi yozadi/o'qiydi, boshqalar faqat o'qiydi.

Nega []byte ishlatilgan?

Go tilida faylga yozish funksiyalari (masalan, os.WriteFile) baytlar ketma-ketligi ([]byte) bilan ishlaydi, chunki fayllar baytlar orqali saqlanadi. Kompyuterlar matnni ham, rasmni ham, kodni ham bayt ko'rinishida saqlaydi. Shuning uchun matnni yozishdan oldin uni []bytega aylantirish kerak bo'ladi, stringni to'g'ridan-to'g'ri berib bo'lmaydi, uni baytlarga aylantirish zarur.

Fayldan o'qish

package main

import (
    "fmt"
    "os"
)

func main() {
    data, err := os.ReadFile("fayl.txt")
    if err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }

    fmt.Println(string(data))
}

Natija:

Bu Go tilida yozilgan fayl.

Faylga qo'shimcha yozish (os.OpenFile + os.O_APPEND)

package main

import (
    "fmt"
    "os"
)

func main() {
    f, err := os.OpenFile("fayl.txt", os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }
    defer f.Close()

    _, err = f.WriteString("Yana bir qatordan yozildi.\n")
    if err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }
}
  • os.O_APPEND Faylga yozish oxiridan qo'shiladi (append rejimi). Fayl mavjud bo'lsa, yozuv oxiriga qo'shiladi, mavjud bo'lmasa yaratmaydi (faqat O_CREATE bo'lsa yaratadi).
  • os.O_WRONLY Faylga faqat yozish rejimida ochiladi (o'qib bo'lmaydi).
  • | bu yerda bitwise OR bo'lib, ikkita flagni birlashtiradi.

Faylni qatorma-qator o'qish (bufio.Scanner)

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("fayl.txt")
    if err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }
}

Faylni o'qib kerakli ishlar amalga oshirilganidan so'ng uni yopishni unutmaslik zarur, agar yopilmasdan qolib ketsa ortiqcha resurs sarflanadi. Har bir ochiq fayl xotiradan joy oladi. Yopilmasa xotira sekin-asta oshib boradi. Yuqoridagi misolda yopish defer file.Close() bilan amalga oshirilgan. Ya'ni funksiya ishini yakunlagan zaxoti faylni file.Close() funksiyasini chaqirib yopadi.

Faylni o'chirish (os.Remove)

package main

import (
    "fmt"
    "os"
)

func main() {
    err := os.Remove("fayl.txt")
    if err != nil {
        fmt.Println("Xatolik sodir bo'ldi")
    }
}

Fayl mavjudligini tekshirish

package main

import (
    "fmt"
    "os"
)

func main() {
    if _, err := os.Stat("fayl.txt"); os.IsNotExist(err) {
        fmt.Println("Fayl mavjud emas.")
    } else {
        fmt.Println("Fayl mavjud.")
    }
}

Fayl haqida ma'lumot olish (os.FileInfo)

package main

import (
    "fmt"
    "os"
)

func main() {
    if info, err := os.Stat("fayl.txt"); os.IsNotExist(err) {
        fmt.Println("Fayl mavjud emas.")
    } else {
        fmt.Println("Fayl: ", info.IsDir())
        fmt.Println("Fayl: ", info.Name())
        fmt.Println("Fayl: ", info.Mode())
        fmt.Println("Fayl: ", info.ModTime())
        fmt.Println("Fayl: ", info.Sys())
        fmt.Println("Fayl: ", info.Size())

    }
}
  • info.IsDir() Fayl papkami yoki oddiy faylmi, shuni tekshiradi.
  • info.Name() Faqat fayl nomini qaytaradi, joylashgan joyini emas.
  • info.Mode() Faylning ruxsatlari va turini (os.FileMode) qaytaradi.
  • info.ModTime() Faylning oxirgi o'zgartirilgan vaqtini (time.Time) qaytaradi.
  • info.Sys() Tizimdan kelgan qo'shimcha metadata (interface{}) qaytaradi.
  • info.Size() Fayl hajmini baytlarda (int64) qaytaradi.

JSON

Go da JSON fayl bilan ishlash juda oddiy, chunki encoding/json paketida hamma kerakli funksiyalar mavjud.

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Person struct {
    Name   string   `json:"name"`
    Age    int      `json:"age"`
    Skills []string `json:"skills"`
}

func main() {
    file, err := os.Open("fayl.json")
    if err != nil {
        fmt.Println("Xato:", err)
        return
    }
    defer file.Close()

    var p Person
    decoder := json.NewDecoder(file)
    err = decoder.Decode(&p)
    if err != nil {
        fmt.Println("Decode xato:", err)
        return
    }

    fmt.Println("Ism:", p.Name)
    fmt.Println("Yosh:", p.Age)
    fmt.Println("Ko'nikmalar:", p.Skills)
}

fayl.json

{
  "name": "Ali",
  "age": 25,
  "skills": ["Go", "Python", "JavaScript"]
}

Bu yerda tushunishimiz kerak bo'ladigan muhim narsalardan bir bu struct tag. Go da struct tag sintaksisi struct maydonlariga qo'shimcha metadata biriktirish usuli. Struct tag `json:"name"` ko'rinishida yoziladi. encoding/json paketi bu taglarni o'qib, JSON bilan struct maydonlarini qanday moslashtirish kerakligini biladi. Agar tag yozilmasa:

struct:

type Person struct {
    Name   string
    Age    int
    Skills []string
}

fayl.json:

{
  "name": "Ali",
  "age": 25,
  "skills": ["Go", "Python", "JavaScript"]
}

Agar tag bo'lmasa maydon nomi case-insensitive tekshiriladi. "name" JSON maydoni Name struct maydoniga tushadi (harf registriga qaramaydi). Shuning uchun "name", "NAME", "Name" hammasi Name deb o'qiladi.