Go öğreniyorum - Gün 8 : Paketler - Bölüm 1

`Introducing Go` kitabından bugün öğrendiklerim

DRY (Don’t repeat yourself) prensibi doğrultusunda Go, tekrar kullanılabilir kaliteli kod felsefesini benimsemiştir.

Chapter 8

Packages

Sürekli olarak gördüğümüz;

import "fmt"

fmt aslında kullandığımız paketin adı. İçinde farklı farklı fonksiyonlar bulunuyor. Bu fonksiyonlar sayesinde istediğimiz düzende çıktı alabiliyoruz. Bir araya toplanmış (bundled) fonksiyonlar topluluğu yani paket kullanmanın en önemli faydaları:

  1. Namespace, yani ilgili fonksiyonları kapsayan ortak isim uzayı sağlar ve proje ya da, sistemdeki diğer fonksiyonlarla karışmamayı sağlar,
  2. Kod organizasyonu sağlar,
  3. Derleyiciyi hızlandırır. Örneğin fmt her kullanışımızda derleyici tarafından derlenmez.

Core Paketler

Go, iyi düşünülmüş, işlerimizi kolaylaştıracak pek çok hazır paketle geliyor. Bunlara Core paketler deniliyor.

strings

String işlemleri ile ilgili pek çok yardımcı fonksiyon bu paketle gelir:

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.Contains("test", "es")) // => true
    fmt.Println(strings.Count("test", "t")) // => 2
    fmt.Println(strings.HasPrefix("unit_test", "unit")) // => true
    fmt.Println(strings.HasSuffix("file.jpg", "jpg")) // => true
    fmt.Println(strings.Index("test", "e")) // => 1
}

Contains ile içinde var mı? diye bakarsınız. test kelimesinde es var mı? Evet var. Count ile sayarsınız, acaba test kelimesinde kaç tane t harfi var ? HasPrefix ile acaba ön ek var mı ? HasSuffix ile acaba son ek var mı ? diye kelime içinde araştırma yaparsınız. Index ile de acaba e harfi test kelimesi içinde kaçıncı harf ? diyer bakarız. 0 indeksli olduğu için 2. harf yani cevap 1 gelir.

Aslında Contains method’u perde arkasında;

func Contains(s, substr, string) bool

şeklinde bir fonksiyon. Diğer tüm method’larda benzer fonksiyonlar aslında. Diğer String method’larını linkten görebilirsiniz.

Input/Output

Go’nun io paketi bir az miktarda fonksiyon içerirken ağırlıkta diğer paketlerin kullandığı interface’leri bünyesinde bulundurur. Bunların en bilinen ve sık kullanılanları Reader ve Writer interface’leridir. Pek çok fonksiyon bu iki interface’i argüman olarak alırlar. Örneğin Copy fonksiyonuna baktığımıza;

func Copy(dst Writer, src Reader)(written int64, err error)

bunu görebiliriz. bytes paketinde bulunan Buffer struct’ı ile []byte ya da string okuma/yazma yapabiliriz;

var buf bytes.Buffer
buf.Write([]byte("test"))

Dosyalar (Files) ve Dizinler (Folders)

Dosya, dizin okuma yazma işlemleri için io paketi kullanılır. Şimdi, test.txt adlı dosyayı açıp içini okuyacağız:

package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    file := "/Users/vigo/Desktop/test.txt"

    bs, err := ioutil.ReadFile(file)
    if err != nil {
        fmt.Println("file not found")
        return
    }

    str := string(bs)
    fmt.Println(str) // Hello World
}

Şimdi os paketinden Create method’unu kullanarak dosya oluşturalım:

package main

import (
    "os"
    "fmt"
)

func main() {
    targetFile := "/Users/vigo/Desktop/test1.txt"

    file, err := os.Create(targetFile)
    if err != nil {
        fmt.Println("error")
        return
    }
    defer file.Close()

    file.WriteString("test")
}

Şimdi yine os paketini kullanarak bir dizinin içindekileri görüntüleyelim:

package main

import (
    "fmt"
    "os"
)

func main() {
    targetDirectory := "/Users/vigo/Desktop"

    dir, err := os.Open(targetDirectory)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer dir.Close()

    fileInfos, err := dir.Readdir(-1)
    if err != nil {
        fmt.Println("error")
        return
    }

    for _, fi := range fileInfos {
        fmt.Println(fi.Name())
    }
}

// .DS_Store
// .localized
// IMG_1854.jpg
// IMG_2065.MOV
// iOS-Apps
// iOS-Playground
// people_resume.json
// people_resume_all.json
// people_resume_not_null.json
// swift-works
// test.txt
// test1.txt
// trap

Readdir tek bir argüman alıyor, bu geri dönecek elemanların sayısını belirliyor. Eğer -1 geçersek (ki geçtik) bu tüm elemanları dön anlamına geliyor. Eğer recursive yani dizin bulunca altının altının altı yanı son derinliğe kadar inmek istersek path/filepath paketinden Walk method’unu kullanıyoruz:

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func main() {

    targetDir := "/Users/vigo/Desktop/trap"

    filepath.Walk(targetDir, func(path string, info os.FileInfo, err error) error {
        fmt.Println(path)
        return nil
    })
}

// /Users/vigo/Desktop/trap
// /Users/vigo/Desktop/trap/.DS_Store
// /Users/vigo/Desktop/trap/new-tables.sql
// /Users/vigo/Desktop/trap/sample_files
// /Users/vigo/Desktop/trap/sample_files/.DS_Store
// /Users/vigo/Desktop/trap/sample_files/dummy.jpg
// /Users/vigo/Desktop/trap/sample_files/ldap_sample_data
// /Users/vigo/Desktop/trap/sample_files/ldap_sample_data/ugur.ozyilmazel.txt
// /Users/vigo/Desktop/trap/sample_files/test-dosya.pdf
// /Users/vigo/Desktop/trap/scrap.py
// /Users/vigo/Desktop/trap/webteam-avatar.png
// /Users/vigo/Desktop/trap/webteam.jpg

Error’ler

errors paketi yardımıyla kendimiz de error nesnesi üretebiliriz:

package main

import (
    "errors"
    "fmt"
)

func main() {
    err := errors.New("Hata mesajı")
    fmt.Println(err) // Hata mesajı
}

Not

Bu yazıyı 29 Temmuz 2016’da yazmaya başlamışım, ancak tamamladım :)