io va bufio paketlari
Goda fayl, tarmoq ulanishi, konsol yoki hatto xotiradagi matn — bularning barchasi bir xil umumiy tushuncha orqali ifodalanadi: oqim (stream). io paketi shu oqimlar bilan ishlash uchun umumiy interfeyslarni (Reader, Writer) belgilaydi, bufio esa ularni buferlash orqali tezroq va qulayroq qiladi (masalan, qator-qator o'qish).
import (
"bufio"
"io"
)
io.Reader va io.Writerio paketining yuragi — bu ikkita juda oddiy interfeys:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
Fayl, tarmoq ulanishi, strings.Builder, bytes.Buffer, hatto os.Stdout — bularning barchasi shu ikki interfeysni amalga oshiradi. Shu sababli, agar sizning funksiyangiz io.Writer qabul qilsa, u bir xil kodni fayl, tarmoq yoki oddiy matn buferiga yozish uchun ishlata oladi — manba/manzil qayerdaligi funksiya uchun muhim emas.
io.ReadAll()package main
import (
"fmt"
"io"
"strings"
)
func main() {
// strings.NewReader — oddiy satrni io.Reader ko'rinishiga aylantiradi
reader := strings.NewReader("Salom, Go dunyosi!")
data, err := io.ReadAll(reader)
fmt.Println(string(data))
fmt.Println(err)
}
Natija:
Salom, Go dunyosi!
<nil>
[!NOTE]
os.ReadFile()(oldingi darsda ko'rgan edik) ichki jarayonda aynanio.ReadAll()dan foydalanadi. Farqi shundaki,os.ReadFile()faqat fayllar uchun mo'ljallangan qulay "qisqartma",io.ReadAll()esa istalganio.Reader(fayl, tarmoq, satr...) bilan ishlaydi.
io.Copy()package main
import (
"fmt"
"io"
"strings"
)
func main() {
src := strings.NewReader("Nusxalash uchun matn")
var dst strings.Builder
// src dagi hamma narsani dst ga ko'chiradi
n, err := io.Copy(&dst, src)
fmt.Println(dst.String())
fmt.Println("Ko'chirilgan bayt:", n)
fmt.Println(err)
}
Natija:
Nusxalash uchun matn
Ko'chirilgan bayt: 20
<nil>
io.Copy() katta fayllarni nusxalashda ham juda samarali ishlaydi, chunki u butun faylni xotiraga yuklamasdan, kichik-kichik bo'laklarda o'qib-yozib boradi.
bufio.ScannerFoydalanuvchi kiritgan matnni yoki faylni qator-qator (yoki so'z-so'z) o'qishning eng qulay usuli — bufio.Scanner:
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
text := "Birinchi qator\nIkkinchi qator\nUchinchi qator"
scanner := bufio.NewScanner(strings.NewReader(text))
// Scan() har chaqirilganda navbatdagi qatorga o'tadi, qator qolmaganda false qaytaradi
for scanner.Scan() {
fmt.Println("Qator:", scanner.Text())
}
}
Natija:
Qator: Birinchi qator
Qator: Ikkinchi qator
Qator: Uchinchi qator
[!IMPORTANT] Aynan shu
bufio.Scanner— konsoldan (os.Stdin) foydalanuvchi ma'lumotini qator-qator o'qishning eng tabiiy usuli:bufio.NewScanner(os.Stdin). Bufmt.Scanln()dan farqli o'laroq, bo'sh joy ichida bo'lgan butun qatorni (masalan, "Ali Valiyev" kabi ism-familiyani) bitta kirish sifatida o'qiy oladi.
Scannerni so'z-so'z o'qish uchun ham sozlash mumkin:
wordScanner := bufio.NewScanner(strings.NewReader("Go juda qiziqarli til"))
wordScanner.Split(bufio.ScanWords) // standart holat qator-qator, buni so'z-so'zga o'zgartiramiz
for wordScanner.Scan() {
fmt.Println(wordScanner.Text())
}
Natija:
Go
juda
qiziqarli
til
bufio.ReaderAgar qator emas, balki istalgan boshqa belgigacha (masalan, vergulgacha) o'qish kerak bo'lsa, bufio.Reader ishlatiladi:
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
r := bufio.NewReader(strings.NewReader("Salom dunyo\n"))
// '\n' belgisi uchrashiga qadar (shu belgi bilan birga) o'qiydi
line, err := r.ReadString('\n')
fmt.Printf("%q\n", line)
fmt.Println(err)
}
Natija:
"Salom dunyo\n"
<nil>
bufio.WriterKo'p marta kichik-kichik yozish amalini bajarish (masalan, faylga har bir qatorni alohida yozish) sekin ishlashi mumkin, chunki har safar haqiqiy "yozish" amali sodir bo'ladi. bufio.Writer yozuvlarni avval xotirada to'playdi, so'ng bitta katta bo'lak sifatida jo'natadi:
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
var buf strings.Builder
w := bufio.NewWriter(&buf)
w.WriteString("bufio orqali yozilgan")
// Flush() chaqirilmaguncha ma'lumot buferda "kutib" turadi!
w.Flush()
fmt.Println(buf.String())
}
Natija:
bufio orqali yozilgan
[!WARNING]
bufio.Writerbilan ishlagandaFlush()ni chaqirishni unutmang! Aks holda, buferga yig'ilgan ma'lumot haqiqiy manzilga (fayl, konsol) hech qachon yozilmasligi mumkin — dastur tugaganda ham bufer "bo'shatilmasdan" qolib ketishi mumkin.
| Vazifa | Funksiya |
|---|---|
| Istalgan oqimdan hammasini bir yo'la o'qish | io.ReadAll() |
| Bir oqimdan boshqasiga nusxalash | io.Copy() |
| Konsol yoki fayldan qator-qator o'qish | bufio.NewScanner() |
| So'z-so'z o'qish | scanner.Split(bufio.ScanWords) |
| Ma'lum belgigacha o'qish | bufio.NewReader().ReadString(belgi) |
| Tez-tez kichik yozuvlarni samarali yig'ish | bufio.NewWriter() + Flush() |