Erhan Yakut Software Developer @Binalyze | Founder @Passwall | Golang Enthusiast | Open Sorcerer

Go Programlama Dili (Golang) ile Dosya İşlemleri

2 min read

golang file actions

Google tarafından geliştirilen ve geleceği oldukça parlak olan Go Programlama Dili (Golang) ile dosya işlemlerini (dosya oluştur, oku, yaz, kapat, sil, isim değiştir vs.) gerçekleştirmek oldukça kolay. Github sayfamda örnek kodlarını paylaştığım konuya burada da kısaca değinmek istiyorum. Tabi burada yazılanları yapabilmek için önce Go kurulumunu yapmış olmanız gerektiğini unutmayınız.

Go Programlama Dili “os” Paketi

Golang, bünyesinde os (Operating System – İşletim Sistemi) paketi‘ni barındırmaktadır. Konumuz olan dosya işlemleri de bu paket içerisinde bulunmaktadır. Elbettte ioutil gibi diğer paketler ile de bazı dosya işlemleri yapılabiliyor ancak bunlar da meseleyi os paketini temel alarak (genişleterek) çözüyorlar.

Bu yazıda da dosya işlemlerini en sade haliyle anlatmak için herhangi bir üçüncü parti paket kullanmaktan kaçınarak doğrudan os paketini kullandım.

Golang’de Dosya Açma Yöntemleri Nelerdir?

Öncelike bir dosyayı nasıl açabileceğimizi ve dosya açarken kullanabileceğimiz sabit değişkenleri bilmeliyiz. Aşağıdaki örneği inceleyerek başlayalım.

package main

import(
	"os"
)

func main () {

	file, err := os.OpenFile("read.txt", os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		panic(err)
	}

}

Bir dosyayı açarken onu ne amaçla açacağımızı belirtmeliyiz. Bunun için Golang’de üç sabit değişken vardır ve os.OpenFile fonksiyonunda bu üç değişkenden birisini mutlaka kullanmalıyız.
O_RDONLY : Dosyayı sadece okuma için (read-only) açar.
O_WRONLY : Dosyayı sadece yazma için (write-only) açar.
O_RDWR : Dosyayı hem okuma hem de yazma için (read-write) açar. En çok kullanılan budur.

Yukardaki üç sabitten birisini mutlaka kullanmalıyız. Bununla birlikte yukarıdakilere ilave olarak tercihen kullanabileceğimiz beş değişken daha vardır.
O_APPEND : Dosyaya yazma işlemi yaparken veriyi dosyanın en sonuna ekler.
O_CREATE : Dosyayı açarke eğer belirtilen isimde bir dosya yoksa oluşturur.
O_EXCL : O_CREATE ile birlikte kullanılır. Yeni dosyanın oluşturulabilmesi için belirtilen isimde bir dosyanın bulunmaması gerekir.
O_SYNC : Dosyanın synchronous I/O için açılmasını sağlar.
O_TRUNC : Dosya eğer zaten mevcutsa ve normal bir dosya ise 0 uzunlukta dosyayı keser (truncate)

Burada yani Go Programlama Dili‘nde geçen dosya açma konuları aslında Linux temel konularıdır. Linux’te dosya açma yöntemleri ile ilgili detaylara şuradan ulaşabilirsiniz.

Golang’de Dosya Bilgilerine Nasıl Ulaşılır?

Her dosyanın “isim”, “dosya büyüklüğü” gibi temel bilgileri bulunur. Bazen uygulamalarımızda bu bilgilere göre işlemler yaparız. İşte böyle durumlarda kullanılmak üzere Golang os paketi tarafından FileInfo isimli bir interface tanımlanmıştır. Detayları şu şekildedir:

type FileInfo interface {
	Name() string       // Dosya ismini gösterir
	Size() int64        // Byte olarak dosya boyutunu gösterir
	Mode() FileMode     // Dosya türünü gösterir
	ModTime() time.Time // Dosyanın son düzenlenme tarihini gösterir
	IsDir() bool        // Dosyanın klasör olup olmadığını belirtir
	Sys() interface{}   // Dosya kaynağını gösterir
}

Bir dosyanın FileInfo‘da belirtilen değerlerine ulaşmak için ya dosyayı Open, OpenFile vb. bir komutla açabilir, ya da daha basit bir şekilde Lstat veya Stat komutu ile yalnızca bilgileri göstermek için dosyaya ulaşabilirsiniz. Aşağıdaki örnek ile bir dosyanın dosya ismini ekrana yazdırabiliriz.

package main

import(
	"fmt"
	"os"
)

func main () {

	fi, err := os.Stat("read.txt")
	if err != nil {
		panic(err)
	}

	fmt.Println("File Name: " + fi.Name())

	// Çıktı: "File Name: read.txt"

}

Golang’de Dosya/Klasör Türünü Nasıl Öğreniriz?

Bir önceki başlıkta dosya bilgisini öğrenmek için FileInfo isimli interface tanımlandığını söylemiştik. Dikkat ederseniz FileInfo içinde Mode() isminde FileMode türünde başka bir interface tanımlı. İşte yukarıdaki yöntemlerle hedef dosyamıza ulaştıktan sonra Mode() yardımıyla dosyanın türüne göre dilediğimiz işlemi yapabiliriz. Mode()’un detayları şu şekildedir:

const (
        // The single letters are the abbreviations
        // used by the String method's formatting.
        ModeDir        FileMode = 1 << (32 - 1 - iota) // d: klasör
        ModeAppend                                     // a: sadece sonuna veri eklenebilir
        ModeExclusive                                  // l: özel kullanım
        ModeTemporary                                  // T: geçici (temporary) dosya
        ModeSymlink                                    // L: sembolik bağlantı (symbolic link)
        ModeDevice                                     // D: ciaz dosyası
        ModeNamedPipe                                  // p: isimlendirilmiş kanal (named pipe) (FIFO)
        ModeSocket                                     // S: Unix domain soket
        ModeSetuid                                     // u: uid belirleme
        ModeSetgid                                     // g: gid belirleme
        ModeCharDevice                                 // c: Unix cihaz karakteri
        ModeSticky                                     // t: sabit

        // Dosya türünün bit olarak maskelemesi için aşağıdakiler kullanılır. Normal dosyalar için bu değerler oluşmaz.
        ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice

        ModePerm FileMode = 0777 // Unix dosya izni
)

Yukarıda belirttiğim sabitler kafanızı karıştırmasın. Normal bir dosya (regular file) ile işlem yaparken şu örnekteki gibi bir kullanım ihtiyacınızı karşılayacaktır.

package main

import (
	"fmt"
	"os"
)

func main() {
	fi, err := os.Stat("read.txt")
	if err != nil {
		panic(err)
	}

	switch mode := fi.Mode(); {

		case mode.IsRegular():
			fmt.Println("regular file")

		case mode.IsDir():
			fmt.Println("directory")

		case mode&os.ModeSymlink != 0:
			fmt.Println("symbolic link")

		case mode&os.ModeNamedPipe != 0:
			fmt.Println("named pipe")
	}
}

Son Sözler ve Github Proje Sayfası

Bu konuya başlarken aslında Github sayfamda elimin altında bulunmasını istediğim basit bir golang dosyası düşünmüştüm. Fakat yine konu açıldıkça açıldı ve basit bir örnek veya blog yazısından çıkıp Go programlama dilinde dosya işlemlerini anlatan mini bir projeye dönüştü. Proje içerisinde yukarıda anlatılanlar ile birlikte Create, Rename, Chmod, Mkdir, Remove, RemoveAll, File.Readdir, File.Close gibi bir çok metodun kullanımı ile ilgili örnekler bulabilirsiniz. Umarım faydası dokunur. Güle güle kullanınız.

Kendime not: En kısa zamanda tek dosyada topladığın örneklerin her birini farklı dosya olarak oluştur ve projeyi güncelle :)

Erhan Yakut Software Developer @Binalyze | Founder @Passwall | Golang Enthusiast | Open Sorcerer

Go’da Empty Struct Karşılaştırma Problemi

Yazılım geliştirirken bazen anlam veremediğimiz durumlarla karşılaşırız. Her programlama dilinde olduğu gibi Go’da da özenle işlenmesi ve açıklanması gereken konular vardır. Bunlardan birisi de...
Erhan Yakut
2 min read

Go Programlama Dili Kaynakları

Her gün çevremde Go Programlama Dili‘ni merak eden ama nasıl ve nereden başlayacağını bilemeyen birçok kişiyle karşılaşıyorum. Twitter mesaj kutum da bu konuların sorulduğu...
Erhan Yakut
4 min read