Golang 101: Fonksiyonlar (Functions)
Tags: go, functions
Published: 2021-10-11 16:00:58

Fonksiyonlar `main()` fonksiyonu dışında tanımlanmalıdır fakat bir istisna olan **Fonksiyonun Değişkene Atanması** ise tam tersi `main()` içerisinde tanımlanmak zorundadır.

```golang
package main

import "fmt"

// Ayrı Ayrı Argüman Tanımları ve Değer Dönme
func topla(a int, b int) int {
	return a + b
}

// Ayrı Türlerden Argümanları Gruplama
func cikar(a, b int) int {
	return a - b
}

// Fonksiyona Kesit (Slice) Argümanı
func ortalama(kesit []int) int {
	var toplam int
	for _, sayi := range kesit {
		toplam += sayi
	}

	return toplam / len(kesit)
}

// Çift Çıktı
func hesapla(kesit []int) (int, int) {
	var toplam, ortalama int
	for _, sayi := range kesit {
		toplam += sayi
	}

	ortalama = toplam / len(kesit)

	return toplam, ortalama
}

// Değişken Sayılı Argüman Kullanma
func topla2(sayilar ...int) int {
	var toplam int
	for _, sayi := range sayilar {
		toplam += sayi
	}

	return toplam
}

// Fonksiyonun Çağrılması
func main() {

	sonuc := topla(1, 2)
	fmt.Println("Toplam:", sonuc)

	sonuc = cikar(3, 1)
	fmt.Println("Kalan:", sonuc)

	kesit := []int{100, 200, 300, 400, 500}
	sonuc = ortalama(kesit)
	fmt.Println("Ortalama:", sonuc)

	// Fonksiyonun Değişkene Atanması
	a, b := 3, 5
	topla := func() int {
		return a + b
	}()
	topla2 := func() int {
		return a + b
	}
	fmt.Println(topla)
	fmt.Println(topla2())
}
```
```
Toplam: 3
Kalan: 2
Ortalama: 300
8
8
```
[çalıştır!](https://go.dev/play/p/aGKB0CK7g-H)

## Ayrı Ayrı Argüman Tanımları ve Değer Dönme
```golang
func topla(a int, b int) int {
	return a + b
}
```
Fonksiyon argümanlarından `a` ve `b` için `int` türünde girdi tanımlandı. Toplama işleminin dışarı çıkarılabilmesi `return` için de `int` türü tanımlandı.

## Ayrı Türlerden Argümanları Gruplama
```golang
func cikar(a, b int) int {
	return a - b
}
```
Fonksiyon da belirtilecek argümanlar aynı türden ve ardışık ise virgülle ayrılarak topluca belirtilebilir. Örnekte `a` ve `b` türleri aynı olduğu için tek seferde `int` olarak belirtildi.

## Fonksiyona Kesit (Slice) Argümanı
```golang
func ortalama(kesit []int) int {
	var toplam int
	for _, sayi := range kesit {
		toplam += sayi
	}

	return toplam / len(kesit)
}
```
Fonksiyona girilen kesit (slice) `for` ve `range` ile toplanıp, sonuç kesit eleman sayısına (`len()`) bölünerek döndürülüyor.

## Çift Çıktı
```golang
func hesapla(kesit []int) (int, int) {
	var toplam, ortalama int
	for _, sayi := range kesit {
		toplam += sayi
	}

	ortalama = toplam / len(kesit)

	return toplam, ortalama
}
```
`Range` ile yapılan döngü içi atamalarda (`a, b := range degisken`) kullanımındaki örneklerde çoğunlukla çift değer görmüştük, burada da fonksiyondan `return` ile çift değer dönüyoruz. Fakat öncesinde fonksiyondan çift değer döneceği belirtilmelidir `(int, int)`.

## Değişken Sayılı Argüman Kullanma
```golang
func topla2(sayilar ...int) int {
	var toplam int
	for _, sayi := range sayilar {
		toplam += sayi
	}

	return toplam
}
```
Argümanda tür belirtecinden önce konulan `...` nokta ile belirsiz sayıda argüman girileceği belirtilmiştir. Eğer girilecek argüman sayısı belli farklı argümanlar var ise belirsiz olan en sona girilmelidir: `func fonksiyon(sayi int, harfler ...string)` gibi.

## Fonksiyonun Değişkene Atanması
```golang
	a, b := 3, 5
	topla := func() int {
		return a + b
	}()
	topla2 := func() int {
		return a + b
	}
	fmt.Println(topla)
	fmt.Println(topla2())
```
Bu en ilginç fonksiyon tanımlama yöntemidir. Değişkene atanan fonksiyon da fonksiyon adı değişkenin kendisidir. Girdi için argüman belirtilmiyor ve çıktılar (`return`) var ise türler belirtilmelidir. İki ayrı fonksiyon olan `topla` ve `topla2` arasında küçük bir fark vardır o da `Println` ile ekrana yazma sırasında da açıkça görülmektedir. Dikkatlice inceleyerek aradaki farkı bulacağınızı düşünüyorum. Bu fark aslında fonksiyon tanımlama ve çağırma sırasında `()` kullanımının zorunlu olduğunu gösteriyor. Aksi bir kullanım görmedim ama varsa lütfen yorumlarda belirtiniz.

**NOT**: Fonksiyonların çağrılması ile ilgili kısımlar `main()` fonksiyonunda gösterilmiştir.