Go Cheatsheet

Kısa Kısa Go

  • Sentaksı C sentaksına yakın
  • Açık kaynaklı
  • Statik tipli
  • Programlar native makine koduna derlenir
  • Imperative dil
  • Nesne yönelimli programlama yapılamaz
  • Nesne ve sınıf yok
  • Struct ve metot var
  • Interface var
  • Struct seviyesinde encapsulation yok
  • Encapsulation paket seviyesinde
  • Kalıtım yok (zaten sınıf da yok) ama tip gömme var
  • Birinci derece yazılım varlığı fonksiyon
  • Fonksiyon, birden fazla değer döndürebilir (aslında bağıntı)
  • Exception fırlatma yok
  • Closure var
  • Pointer var ama pointer aritmetiği yok
  • Temel concurrency elemanları goroutine ve channel
  • Hızlı derlenir
  • Çöp toplayıcısı var
  • Dahili paket yöneticisi var
  • İşe yaramayan değerler _ ‘ye atanır

2 Temel Ortam Değişkeni

GOROOT : Go’nun kurulduğu dizini içerir

GOPATH : Geliştirilen projelerin yer aldığı dizini içerir

Yorumlar (Comment)

// Tek satır yorum

/*
Çok
satırlı
yorum
*/

Tırnak İşaretlerinin Kullanımı

'A' // Tek tırnak bir tek karakter (mesela char veya rune tiplerinde olan karakter) için kullanılır

"My String" // Birden fazla karakterden oluşan bir string için kullanılır fakat tek satırda tanımlamaya izin verir

`First line
Second line
Third line` // Bir string için kullanılır fakat yeni satır karakterlerinde escape yapmaya ihtiyaç bırakmaz

Çalıştırma (Running)

Bir programı en basit şekilde hem derleyip hem de ilk defa çalıştırma:

go run main_iceren_dosya.go

En basit örnek program:

// demo.go
package main

import "fmt"

func main() {
	fmt.Println("Merhaba") // -> Merhaba
}
go run demo.go

Derlenmiş programı eğer derlendiği ortam ile özdeş ortamda ise çalıştırma:

./demo

Paketler (Package)

Paket Oluşturma

Her go dosyası bir pakete dahil edilir. Ve hangi pakete dahil olduğu dosyanın en başında deklare edilir:

package mypack

Çalıştırılabilir dosya (executable) oluşturabilmek için başlangıç noktası (entrypoint) dosyası main paketine dahil edilir:

package main

Paket Kullanımı

Paketler kullanılması için başka bir dosyaya import ifadesi aracılığı ile dahil edilir:

import "os"

Birden fazla paket import edilecekse:

import (
	"os"
	"fmt"
	"mymodule/mypack"
	"github.com/example/examplepack"
)

Paketlerin sabitleri, değişkenleri, fonksiyonları veya metotlarından yalnızca exported olanları paketin dışında kullanılabilir.

Sabit, değişken, fonksiyon ve metotların isimleri büyük harfle başlıyorsa exported, küçük harfle başlıyorsa unexported olur.

Import edilen paketin içinden kullanılacak herhangi varlığın önüne paketin adı eklenip separator olarak . kullanılır.

Paketin adı, / ile ayrılmış paket yolunun son dilimidir.

Paket import edilirken pakete takma ad verilebilir. Mesela mypack paketi mp olarak kullanılmak istense:

import (
	"fmt"
	mp "mymodule/mypack"
)

Import edilen paketin takma adı . olursa söz konusu kaynak paketteki varlıklar hedef paketin varlığıymış gibi kullanılabilir:

import (
	"fmt"
	. "mymodule/mypack"
)

Paket İndirme

Paket indirmek için komut satırından:

go get github.com/example/examplepack

Modüller (Module)

Modül Oluşturma

Komut satırı üzerinden oluşturulacak modülün kök dizinine gelinir ve initialize edilir:

mkdir mymodule
cd mymodule
go mod init example.com/myspace/mymodule

Bunun sonucunda modülün kök dizininde go.mod isimli bir dosya oluşur.

Modül içinde modül oluşturulamaz. Bu sebeple modülün kök dizini yolu altında başka bir modülün kök dizini bulunamaz.

Modül Bağımlılıkları

Modülün tüm bağımlılıklarını listelemek için:

go list -m all

Modülü kullanılmayan gereksiz bağımlılıklardan kurtarmak için:

go mod tidy

Modül İndirme

Modül indirme ile paket indirme arasında bir fark yok:

go get example.com/myspace/mymodule

Modül Kullanımı

go build , go test gibi paket inşa komutları ile modüle dahil tüm paketlerin bağımlılıkları go.mod dosyasına eklenmiş olur.

Modül ilk defa çalıştırıldığında modül kök dizininde go.sum dosyası oluşur. Bu bir bağımlılık lock dosyasıdır.

Modül İçinde Modül Kullanımı

// go.mod
module example.com/myspace/mymodule

go 1.123

require (
	example.com/anotherspace/anothermodule v1.0.0
)
Modül İçinde Yerel Modül Kullanımı
// go.mod
module example.com/myspace/mymodule

go 1.123

replace (
	"example.com/myspace/anothermodule" => "../anothermodule"
)

require (
	example.com/myspace/anothermodule v1.0.0
)

Operatörler (Operators)

Aritmetik (Arithmetic)

  • + toplama
  • - çıkarma
  • * çarpma
  • / bölme
  • % kalan

Atama (Assignment)

  • = atama
  • := deklarasyonlu atama / implicit tipli atama

Bitsel (Bitwise)

  • & bitsel “ve”
  • | bitsel “veya”
  • ^ bitsel “ya da”
  • &^ bitsel “ve değil”
  • << bitleri sola kaydır
  • >> bitleri sağa kaydır

Kanal (Channel)

  • <- gönder / al

Karşılaştırma (Comparison)

  • == eşit mi?
  • != eşit değil mi?
  • < küçük mü?
  • <= küçük veya eşit mi?
  • > büyük mü?
  • >= büyük veya eşit mi?

Mantıksal (Logical)

  • ! mantıksal “değil”
  • && mantıksal “ve”
  • || mantıksal “veya”

Pointer

  • & pointer oluştur / adresi
  • * referansı getir

Yerleşik Tipler (Built-in Types)

  • bool // varsayılan değeri false
  • int // varsayılan değeri 0
  • int8 // varsayılan değeri 0
  • int16 // varsayılan değeri 0
  • int32 // varsayılan değeri 0
  • rune // unicode code point, int32 ‘nin diğer adı, varsayılan değeri 0
  • int64 // varsayılan değeri 0
  • uint // varsayılan değeri 0
  • uint8 // varsayılan değeri 0
  • byte // uint8 ‘in diğer adı, varsayılan değeri 0
  • uint16 // varsayılan değeri 0
  • uint32 // varsayılan değeri 0
  • uint64 // varsayılan değeri 0
  • uintptr // varsayılan değeri 0
  • float32 // varsayılan değeri 0
  • float64 // varsayılan değeri 0
  • string // varsayılan değeri “”
  • complex64 // varsayılan değeri (0+0i)
  • complex128 // varsayılan değeri (0+0i)

Yerleşik tipteki bir değişken boş olamaz. O değişken mutlaka, tipin varsayılan değerine sahiptir.

Fonksiyon Çağırma (Function Call)

myFunction() // Değer dönmeyen bir fonksiyonun çağrımı
yourFunction(v) // Değer alan ama değer döndürmeyen bir fonksiyonun çağrımı
i := int(f) // Değer alan ve değer döndüren bir fonksiyonun çağrımı

Diziler (Array)

a := [5]int{1, 2, 4, 8, 16} // Beş elemanlı array oluştu
a[4] = 32 // Array'in beşinci elemanı 32 oldu
n := a[4] // Değişken int olarak tanımlandı ve 32 oldu
a := [...]{2, 4, 6} // Derleyici array'in boyutunu 3 olarak anlar

Dilimler (Slice)

s := []int{1, 2, 3} // Üç elemanlı bir array'in hepsi bir slice olarak alındı
k := []string{0: "a", 2: "c", 1: "b"} // [a b c] şeklinde bir slice
a := [3]string{"a", "b", "c"} // Üç elemanlı array oluştu
s := a[:] // Array'in hepsi slice olarak alındı
a := [4]string{"a", "b", "c", "d"} // Dört elemanlı array oluştu
s1 := a[0:4] // Array'in ilk elemanından dördüncü ve son elemanına kadar dilim olarak alındı
s2 := a[1:] // Array'in ikinci elemanından son elemanına kadar dilim olarak alındı
s3 := a[:3] // Array'in ilk elemanından üçüncü elemanına kadar dilim olarak alındı
low := 1
high := 3
s4 := a[low:high] // Array'in ikinci elemanından üçüncü elemanına kadar dilim olarak alındı
s := []string{"a", "b", "c", "d"} // [a b c d] şeklindeki bir slice
s = append(s, "e", "f", "g") // Slice [a b c d e f g] şeklini aldı
s1 := []string{"a", "b", "c", "d"} // [a b c d] şeklinde bir slice
s2 := []string{"e", "f", "g", "h"} // [e f g h] şeklinde bir slice
s3 := append(s1, s2...) // -> [a b c d e f g h] şeklinde türemiş bir slice
s1 := make([]int, 3) // Üç elemanlı bir array'den [0 0 0] şeklinde bir slice, kapasite opsiyonel
l1 := len(s1) // Uzunluk 3
c1 := cap(s1) // Kapasite 3
s2 := make([]int, 3, 10) // On elemanlı bir array'den [0 0 0] şeklinde bir slice
l2 := len(s2) // Uzunluk 3
c2 := cap(s2) // Kapasite 10

Map

m := map[string]bool{"k1": true, "k2": false} // map[k1:true k2:false] şeklinde bir map oluştu
m["k2"] = true // k2 anahtarlı eleman true oldu
e, ok := m["k2"] // k2 anahtarlı eleman mevcut olduğundan e -> true ve ok -> true
e, ok := m["k3"] // k3 anahtarlı eleman mevcut olmadığından e -> false (varsayılan bool değeri) ve ok -> false
m := make(map[string]int) // Boş bir string anahtarlı int map'i
m["key"] = 12 // key anahtarlı 12 değeri set edildi
delete(m, "key") // key anahtarlı değer unset edildi

Yapılar (Struct)

Yapı (struct) tiplerden bir tiptir

Yapı Deklarasyonu (Struct Declaration)

type Abc struct {
	A, B, C int
}

type Ghi struct {
	G string
	H int; I float64
}

Yapı Örnekleme (Struct Instantiating)

abc1 := Abc{1, 2, 3} // {1 2 3} şeklinde
abc2 := Abc{A: 1,  C: 3} // {1 0 3} şeklinde
col := []Abc{{1, 2, 3}, {4, 5, 6}} // [{1 2 3} {4 5 6}] şeklinde

Struct Üyelerine Erişim (Accessing Struct Members)

type Abc struct {
	A, B, C int
}

abc := Abc{1, 2, 3} // {1 2 3} şeklinde
abc.A = 4 // {4 2 3} şeklinde
abc.C = 6 // {4 2 6} şeklinde
b := abc.B // b -> 2

Arayüzler (Interface)

Arayüz Deklarasyonu (Interface Declaration)

type Producer interface {
	Produce() float64
	Consume()
}

Somut tiplerin hangi interface ‘i gerçekleyeceği deklare edilmez.

Değişken Deklarasyonu (Variable Declaration)

var i int // Tek değişken deklare edildi ama initialize edilmedi. Değişkenin değeri int tipinin varsayılan değeri olan 0
var j int = 123 // Tek değişken hem deklare hem de initialize edildi
var k1, k2 int // Birden fazla değişken tek seferde deklare edildi ama initialize edilmedi
var l1, l2 int = 123, 456 // Birden fazla değişken tek seferde hem deklare hem de initialize edildi

n := 789 // Implicit tipli değişken deklarasyonu, yalnızca fonksiyon gövdelerinde, tip kararı derleyicide

Tip İddiaları (Type Assertion)

var i interface{} = "mystring" // i değişkeni aslında bir string

var v int // v değişkenini int olarak varsay
var ok bool
v, ok = i.(int) // i değişkeninin int olduğunu iddia ederek v değişkenine ata
fmt.Println(v, ok) // v değişkeninin değeri 0 olur, çünkü i aslında bir string, int olduğu yalnızca bir iddia idi, yani tip dönüştürmesi söz konusu değil, haliyle isabet değişkeni olan ok değişkeni de false olur
var i interface{} = true // i aslında bir bool

var v string // v değişkenini string olarak varsay
v = i.(string) // i değişkeninin string olduğunu iddia ederek v değişkenine atarken isabet değişkenini eksik bırakırsan "panic" alırsın
var i interface{} = 1.0

v, ok := i.(string) // şeklinde veya
y, _ := i.(bool) // şeklinde de iddia edilebilir

Anonim Yapılar (Anonymous Struct)

myStruct := struct {
	A, B int
}{1, 2}

Anonim struct kullanımı map[string]interface{} kullanımından daha masrafsızdır.

İşaretçiler (Pointer)

abc := Abc{1, 2} // abc bir Abc 'dir
p := &abc // p, abc 'ye işaret eden bir işaretçidir
r := &Abc{1, 2} // r bir diğer Abc gerçeklemesine işaret eden bir işaretçidir

// Peki bir Abc 'ye işaret eden bir işaretçinin tipi nedir?
// *Abc 'dir

var s *Abc = new(Abc) // new fonksiyonu bir Abc 'ye işaret eden bir *Abc tipli işaretçi üretiyor

Scope of Variables

Local / Global …….

Sabit Deklarasyonu (Constant Declaration)

const c1 int = 123 // Tip belirleyerek sabit deklarasyonu
const c2 = 456 // Implicit tipli sabit deklarasyonu

Yapı Gömme (Struct Embedding)

type Client struct {
	ApiHost string
	ApiPort int
	*log.Logger
}

client := &Client{"api.example.com", 80, log.New()}
client.Log("Ok") // Logger gömüldüğünden dolayı bu şekilde yazılarak aslında client.Logger.Log() çağrılır

var logger *log.Logger = client.Logger // Bu da sağlaması

Tip Dönüşümleri / Tip Çarpıtma (Type Conversion / Type Casting)

Yerleşik tip dönüşüm fonksiyonlarının adları tiplerin adları ile aynıdır.

f := -123.45 // -123.45
i := int(f) // -123
u := uint(i) // 18446744073709551493

Kontrol Yapıları (Control Structures)

If-Else

// Basit if - else if - else
if i > 0 {
	return 1
} else if i == 0 {
	return 0
} else {
	return -1
}
if i := j * k; i > 0 {
	return 1
} else {
	return 0
}

Döngüler (Loop)

// Yalnızca for var. while, do - while veya until yok

for i := 0; i < 10; i++ {
}
for ; i < 10;  { // while gibi çalışır
}
for i < 10  { // Elde yalnızca şart varsa ; notasyonu yazılmayabilir
}
for { // Şartı sabit true olan while gibi çalışır
}
for i := 0; i < 10; i++ {
	continue
}
for {
	if i >= 10 {
		break
	}
	i = i + 1
}

Switch

// Basit switch
switch operatingSystem {
case "darwin":
	fmt.Println("macOS")
        // break ifadesine gerek yok
case "linux":
	fmt.Println("Linux")
default:
	fmt.Println("Other")
}
// Switch'e konu değişkeni bildirmeden önce değişkene atama yapılabilir
switch os := runtime.GOOS; os {
	case "darwin":
		fmt.Println("macOS")
	case "linux":
		fmt.Println("Linux")
	default:
		fmt.Println("Other")
}
// Karşılaştırma case 'leri mümkün
i := 2
switch i {
case i > 0:
	fmt.Println("Positive")
case i < 0:
	fmt.Println("Negative")
default:
	fmt.Println("Zero")
}
// Case 'e dikkat
var c byte = '-'
switch c {
case '.', '-', '/':
	fmt.Println("It is a separator")
// default ifadesi zorunlu değil
}

Range

for ik, e := range array_or_slice_or_map {
	// ik -> endeks veya anahtar, e -> eleman
}

for ik := range array_or_slice_or_map { // Yalnız endeks veya anahtar lazım ise...
}

for _, e := range array_or_slice_or_map { // Yalnız eleman lazım ise...
}
for range time.Tick(time.Second) { // Hiçbir değişken lazım olmayabilir de...
}

Fonksiyonlar (Functions)

İsimlendirilmiş Fonksiyonlar (Named Functions)

Değer Halindeki Fonksiyonlar (Functions As Values)

Closure

Varyadik Fonksiyonlar (Variadic Functions)

Defer

Metotlar (Methods)

Gizli Arayüz Gerçeklemesi (Implicit Interface Fitting)

Bir struct ‘a bağlanan metotlar bir interface ‘de deklare edilen metotların hepsini gerçekliyorsa o struct o interface ‘i gerçeklemiş demektir:

type Abc struct {}

func (abc Abc) Produce() float64 {
	return 1.2
}

func (abc Abc) Consume() {
	fmt.Println("Consumed")
}

// Abc yapısı Producer arayüzünü gerçeklemiş oldu

Hata Ele Alımı (Error Handling)

Fonksiyonlar birden fazla değer döndürebildiğinden dolayı bir fonksiyonun son döndürdüğü değeri hata yapısı olarak belirlemek yeterlidir. Exception eksikliği hissedilmez.

// Ortak kullanım için standart hata arayüzü bu şekilde (built-in) tanımlıdır (predeclared identifier)
type error interface {
	Error() string
}

Hata yapısı tanımlanacaksa yapı isminin sonuna ...Error eklenmesi, hata atanacak bir değişken tanımlanacaksa değişken isminin başına Err... eklenmesi teamüldür ve tavsiye edilir.

// Hem başarı değeri hem standart hata arayüzü gerçekleyen hata değeri döndürebilen bir fonksiyonumuz olsun
func doSomething() (float64, error) {
	// ...
}

func main() {
	r, e := doSomething()
	if e != nil {
		// Hata boş değil, o zaman ele al (handle the error)
	} else {
		// Hata yok, o zaman yoluna devam et
	}
}

Hata mesajlarının küçük harflerle yazılması ve hata mesajlarının sonuna nokta konulmaması teamüldür ve tavsiye edilir

Eşzamanlılık (Concurrency)

Goroutine’ler (Goroutines)

Goroutine’ler Go tarafından yönetilen (yani işletim sistemi tarafından yönetilmeyen) az masraflı thread’lerdir.

func myRoutine(s string) { // goroutine olarak çağrılacak isimlendirilmiş fonksiyon
	// ...
}

func main() {
	go myRoutine("blabla") // isimlendirilmiş fonksiyonun goroutine olarak çağrılması
}
func main() {
	go func (i int) { // anonim fonksiyonun goroutine olarak başlatılması
		// ...
	}(12) // i parametresine 12 verilerek başlatıldı
}

Kanallar (Channels)

ch := make(chan int) // Bir integer kanalı oluşturuldu
ch <- 12 // ch kanalına 12 değeri gönderildi
i := <-ch // ch kanalından değer alındı

Reflection

Type Switch

func getType(v interface{}) { // v interface{} demek herhangi bir tipteki v demek
	switch t := v.(type) { // v.(type) ifadesi yalnızca switch içinde çalışır
	case int:
		fmt.Println("Integer")
	case float64:
		fmt.Println("Float 64")
	case string:
		fmt.Println("String")
	default:
		fmt.Println("Other")
	}
}

func main() {
	getType(12)
	getType("Hello")
	getType(1.2)
	getType(false)
}

Basma (Printing)

fmt.Println("Welcome\nHoşgeldin\nأهلا بك"); // String 'i stdout 'a yazar ve bir de yeni satır ekler

pt := struct { X, Y int }{ 1, 3 }
fmt.Println("Point:", pt, "X:", pt.X, "Y:", pt.Y) // Birden fazla Println çağırmak yerine bu şekilde tek bir Println çağrılabilir
s1 := fmt.Sprintln("Point:", pt, "X:", pt.X, "Y:", pt.Y)

fmt.Printf("dec: %d hex: %x bin: %b flp: %f sci: %e", 12, 12, 12, 12.0, 12.0) // c tarzı yer tutucular
s2 := fmt.Sprintf("dec: %d hex: %x bin: %b flp: %f sci: %e", 12, 12, 12, 12.0, 12.0)

welcomeMessages := `Welcome
Hoşgeldin
أهلا بك`

Unit Testleri (Unit Testing)

Test Fonksiyonu

Test dosyalarının adlarının sonunun _test.go ile bitirilmesi önerilir:

// demo_test.go
package demo

import (
	"testing" // Unit test için gereken paket
)

func TestMyFunction(t *testing.T) { // Test fonksiyonunun adı "Test" ile başlar
	expected := "Merhaba"
	actual := MyFunction() // Aynı pakette (demo) bulunan teste tabi fonksiyon
	if actual != expected {
		t.Errorf("Expected: %q, actual: %q", expected, actual)
	}
}

Arayüz Moklama (Interface Mocking)

Moklayıcı Kurulumu

go install github.com/golang/mock/mockgen@v1.5.0

Mok Üretimi

// abc_service.go
// Mock 'a temel olacak interface 'i tanımlayalım
package abc

type AbcService interface {
	Serve(s string) string
}

Mok jeneratörünü bu dosya için çalıştıralım:

mockgen -source=abc_service.go -package=mock_abc -destination=mock/abc_service_mock.go
package abc

import (
	mock_abc "example.com/myspace/abc/mock"
	"fmt"
	"github.com/golang/mock/gomock"
	"testing"
)

func TestAbcService(t *testing.T) {
	mockController := gomock.NewController(t)
	defer mockController.Finish()

	mockAbcService := mock_abc.NewMockAbcService(mockController)
	mockAbcService.
		EXPECT().
		Serve(gomock.Eq("dev")).
		Return("OK")

	s := mockAbcService.Serve("dev")
	fmt.Println(s)
}

Birim Testleri Koşturma

Yalnızca bulunulan dizinteki birim testlerin çalıştırılması için:

go test .

Bulunulan dizin ve alt dizinlerdeki tüm paketlerin birim testlerinin çalıştırılması için:

go test ./...
Şu kategoriye gönderildi: Golang