Bu bölümde, Go da kontrol ifadeleri ve fonksiyon işlemleri hakkında konuşacağız.
Akış kontrolü programcılıkta en büyük icattır. Onun sayesinde, basit kontrol ifadeleri kullanarak daha karmaşık lojik ifadeler temsil edilebilir. Akış kontrolünü üç kategoriye ayırabiliriz: şartlı, döngü kontrollü ve şartsız çıkış.
if
kelimesi büyük ihtimalle programlarında en sık geçen kelimedir. Eğer şartlar sağlanırsa birşeyler yapar, sağlanmazsa başka şeyler yapar.
if
şartları için Go da paranteze gerek yoktur.
if x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than or equal to 10")
eead24cf064976b648de5826eab51880c803b0fa }
Go da çok işe yarar bir if
kullanımı, şart ifadesinden önce değişken tanımlama yapmaktır. Bu değişkenin kapsamı sadece if
blok alanı içerisinde geçerlidir.
// x'i tanımla, ve 10 dan büyük olup olmadığını kontrol et
<<<<<<< HEAD if x := islenenDeger(); x > 10 { fmt.Println("x 10'dan büyüktür") } else { fmt.Println("x 10'dan küçüktür")
if x := computedValue(); x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than 10")
eead24cf064976b648de5826eab51880c803b0fa }
// Bu satır derlenemez
fmt.Println(x)
Birden fazla şart için if-else
kullanın.
<<<<<<< HEAD if sayı == 3 { fmt.Println("Sayı 3'e eşittir") } else if integer < 3 { fmt.Println("Sayı 3'ten küçüktür") } else { fmt.Println("Sayı 3'ten büyüktür")
if integer == 3 {
fmt.Println("The integer is equal to 3")
} else if integer < 3 {
fmt.Println("The integer is less than 3")
} else {
fmt.Println("The integer is greater than 3")
eead24cf064976b648de5826eab51880c803b0fa }
Go da goto
terimi mevcuttur fakat kullanırken dikkatli olun. goto
programın kontrol akışını önceden belirlenmiş aynı gövde içindeki bir label
a yönlendirir.
func myFunc() {
i := 0
<<<<<<< HEAD Buraya: // label sonuna ":" koyulur fmt.Println(i) i++ goto Buraya // "Buraya" labeline git
Here: // label ends with ":"
fmt.Println(i)
i++
goto Here // jump to label "Here"
eead24cf064976b648de5826eab51880c803b0fa }
Label'ın adı büyük-küçük harfe duyarlıdır.
for
Go da bulunan en güçlü kontrol lojiğidir. Datayı döngüsel olarak ve tekrarlı işlemlerle okuyabilir, while
döngüsü gibi.
<<<<<<< HEAD for ifade1; ifade2; ifade3 { //... }
ifade1
, ifade2
ve ifade3
birer ifade olmak üzere, ifade1
ve ifade3
değişken tanımlama veya bir fonksiyondan dönen değer olabilirken, ifade2
ise kontrol ifadesidir. ifade1
ifadesi döngüye girmeden önce bir kere işlenecektir. ifade3
ise her döngü sonunda işlenir.
for expression1; expression2; expression3 {
//...
}
expression1
, expression2
ve expression3
birer ifade olmak üzere, expression1
ve expression3
değişken tanımlama veya bir fonksiyondan dönen return olabilirken, expression2
ise kontrol ifadesidir. expression1
ifadesi döngüye girmeden önce bir kere işlenecektir. expression3
ise her döngü sonunda işlenir.
eead24cf064976b648de5826eab51880c803b0fa
Örnekler düz yazıdan daha yararlı olacaktır.
package main
import "fmt"
func main(){
<<<<<<< HEAD toplam := 0; for index:=0; index < 10 ; index++ { toplam += index } fmt.Println("sayıların toplamı= ", toplam) } // Ekran çıktısı:sayıların toplamı= 45
Bazen birden fazla atama yapmak gerekir fakat Go bunun için kullanılacak bir ,
operatörü yoktur. Biz de i, j = i + 1, j - 1
gibi paralel atamalar yaparız.
İhtiyaç yoksa ifade1
ve ifade3
çıkartılabilir.
toplam := 1
for ; toplam < 1000; {
toplam += toplam
======= sum := 0; for index:=0; index < 10 ; index++ { sum += index } fmt.Println("sum is equal to ", sum) } // Print:sum is equal to 45
Bazen birden fazla atama yapmak gerekir fakat Go bunun için kullanılacak bir ,
operatörü yoktur. Biz de i, j = i + 1, j - 1
gibi paralel atamalar yaparız.
İhtiyacımız yoksa expression1
ve expression1
ifadelerini çıkarabiliriz.
sum := 1
for ; sum < 1000; {
sum += sum
eead24cf064976b648de5826eab51880c803b0fa }
Hatta ;
bile çıkarılabilir. Tanıdık geldi mi? Evet, tamamen while
gibi oldu.
sum := 1
for sum < 1000 {
sum += sum
eead24cf064976b648de5826eab51880c803b0fa }
Döngülerde break
ve continue
adında iki önemli işlem vardır. break
döngüden çıkartır ve continue
o anki tekrarı atlar ve sonraki tekrara geçer. Eğer birden fazla iç içe döngüleriniz varsa break
ile labelları kullabilirsiniz.
for index := 10; index>0; index-- {
if index == 5{
<<<<<<< HEAD break // veya continue } fmt.Println(index) } // break varsa yazılanlar: 10、9、8、7、6 // continue varsa yazılanlar: 10、9、8、7、6、4、3、2、1
break // or continue
}
fmt.Println(index)
}
// break prints 10、9、8、7、6
// continue prints 10、9、8、7、6、4、3、2、1
eead24cf064976b648de5826eab51880c803b0fa
for
döngüsü range
kullanıldığında slice
ve map
de bulunan datayı okuyabilir.
for k,v:=range map {
fmt.Println("map's key:",k)
fmt.Println("map's val:",v)
eead24cf064976b648de5826eab51880c803b0fa }
Go da birden fazla değer return yapılabildiği ve kullanılmayan bir değişken olduğunda derleyici hata verdiği için, kullanmak istemediğiniz değişkenler için _
kullanabilirsiniz.
for _, v := range map{
fmt.Println("map's val:", v)
eead24cf064976b648de5826eab51880c803b0fa }
Bazı durumlarda çok fazla if-else
kullandığınızı farkedebilirsiniz. Bu programı okumayı zorlaştırır ve gelecekte bakım yapmayı zorlaştırabilir. Bu durumda problemi çözmek için switch
kullanmak mükemmeldir.
<<<<<<< HEAD switch anaIfade { case ifade1: // eşleşme olursa işlenecek kod case ifade2: // eşleşme olursa işlenecek kod case ifade3: // eşleşme olursa işlenecek kod default: // eşleşme olmazsa işlenecek kod
switch sExpr {
case expr1:
some instructions
case expr2:
some other instructions
case expr3:
some other instructions
default:
other code
eead24cf064976b648de5826eab51880c803b0fa }
sExpr
, expr1
, expr2
, ve expr3
ifadelerinin türleri aynı olmalıdır. switch
çok esnektir. Şartlar sabit olmak zorunda değildir ve şart sağlanana kadar yukarıdan aşağıya doğru çalışır. Eğer switch
in ardından bir ifade gelmiyorsa true
olarak görülür.
i := 10
switch i {
case 1:
<<<<<<< HEAD fmt.Println("i 1'e eşittir") case 2, 3, 4: fmt.Println("i 2, 3 veya 4'e eşittir") case 10: fmt.Println("i 10'a eşittir") default: fmt.Println("Tek bildiğim i nin bir sayi olduğu")
fmt.Println("i is equal to 1")
case 2, 3, 4:
fmt.Println("i is equal to 2, 3 or 4")
case 10:
fmt.Println("i is equal to 10")
default:
fmt.Println("All I know is that i is an integer")
eead24cf064976b648de5826eab51880c803b0fa }
Beşinci satırdaki gibi case
içinde birden fazla değer olabilir. case
sonlarına break
eklemeye gerek yoktur, şart sağlanıp işlem yapıldıktan sonra çıkacaktır. Eğer çıkmasını istemiyorsanız fallthrough
ifadesini kullanarak bir sonraki şarta devam edebilirsiniz.
<<<<<<< HEAD sayı := 6 switch sayı { case 4: fmt.Println("sayı <= 4") fallthrough case 5: fmt.Println("sayı <= 5") fallthrough case 6: fmt.Println("sayı <= 6") fallthrough case 7: fmt.Println("sayı <= 7") fallthrough case 8: fmt.Println("sayı <= 8") fallthrough default: fmt.Println("default durumu") }
Programın sonucu şu olacaktır.
sayı <= 6
sayı <= 7
sayı <= 8
default durumu
func
terimini kullanarak bir fonksiyon tanımlayın.
func fonksiyonAdı(parametre1 tür1, parametre2 tür2) (çıkış1 tür1, çıkış2 tür2) {
// fonksiyon gövdesi
// birden fazla return
return dönüş1, dönüş2
======= integer := 6 switch integer { case 4: fmt.Println("integer <= 4") fallthrough case 5: fmt.Println("integer <= 5") fallthrough case 6: fmt.Println("integer <= 6") fallthrough case 7: fmt.Println("integer <= 7") fallthrough case 8: fmt.Println("integer <= 8") fallthrough default: fmt.Println("default case") }
This program prints the following information.
integer <= 6
integer <= 7
integer <= 8
default case
func
terimini kullanarak bir fonksiyon tanımlayın.
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
// function body
// multi-value return
return value1, value2
eead24cf064976b648de5826eab51880c803b0fa }
Yukarıdaki örnekten tahmin edebileceğiniz üzere aşağıda açıklamaları bulunur.
<<<<<<< HEAD
fonksiyonAdı
adlı foonksiyonu tanımlamak içinfunc
terimini kullanın.- Fonksiyonlar sıfır veya daha fazla parametreye sahip olabilir. Parametrenin türü adından sonra gelir ve birden fazla parametre varsa
,
ile ayrılır. - Fonksiyonlar birden fazla değer döndürebilirler.
- Bu örnekte
çıkış1
veçıkış2
adında iki değer döndürülmüş. Bunlara ad vermek zorunda değilsiniz, türünü yazmanız yeterli. ======= funcName
adlı foonksiyonu tanımlamak içinfunc
terimini kullanın.- Fonksiyonlar sıfır veya daha fazla parametreye sahip olabilir. Parametrenin türü adından sonra gelir ve birden fazla parametre varsa
,
ile ayrılır. - Fonksiyonlar birden fazla değer döndürebilirler.
- Bu örnekte
output1
veoutput2
adında iki değer döndürülmüş. Bunlara ad vermek zorunda değilsiniz, türünü yazmanız yeterli.
eead24cf064976b648de5826eab51880c803b0fa
- Eğer sadece bir değer döndürecekseniz parantez olmadan yazmalısınız.
- Eğer en az bir değer döndürüyorsanız, fonksiyonun içinde istediğiniz yerde
return
terimini kullanmalısınız.
Şimdi pratik bir örnek görelim. (Maksimum değerini hesaplama)
package main
import "fmt"
// return greater value between a and b
eead24cf064976b648de5826eab51880c803b0fa func max(a, b int) int { if a > b { return a } return b }
func main() {
x := 3
y := 4
z := 5
<<<<<<< HEAD max_xy := max(x, y) // max(x, y) fonskiyonunu çağır max_xz := max(x, z) // max(x, z) fonksiyonunu çağır
fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // burada da fonksiyon çağırıldı
======= max_xy := max(x, y) // call function max(x, y) max_xz := max(x, z) // call function max(x, z)
fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // call function here
eead24cf064976b648de5826eab51880c803b0fa }
Yukarıdaki örnek fonksiyon max
da iki aynı tür parametre int
olduğu için bir tane yazmak yeterli olur. Yani a int, b int
yerine a, b int
kullanılır. Birden fazla parametre için de aynı kural geçerlidir. Farkettiyseniz max
fonksiyonu sadece bir değer döndürür ve zorunda olmadığımız için o değere bir isim vermedik, bu kısa halini kullandık.
Go'nun C'den iyi olduğu bir şey birden fazla değer döndürmeyi desteklemesidir.
Alttaki örnekte bunu kullanalım.
package main
import "fmt"
// return results of A + B and A * B
func SumAndProduct(A, B int) (int, int) {
eead24cf064976b648de5826eab51880c803b0fa return A+B, A*B }
func main() {
x := 3
y := 4
<<<<<<< HEAD xARTIy, xCARPIy := SumAndProduct(x, y)
fmt.Printf("%d + %d = %d\n", x, y, xARTIy)
fmt.Printf("%d * %d = %d\n", x, y, xCARPIy)
======= xPLUSy, xTIMESy := SumAndProduct(x, y)
fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
eead24cf064976b648de5826eab51880c803b0fa }
Üstteki fonksiyon isimsiz iki değer döndürür -isterseniz isim verebilirsiniz. Eğer isimlendirseydik, return
yazıp isimlerini yazmamız yeterdi. Çünkü fonksiyonun içinde tanımlılar. Şuna dikkat etmelisiniz ki eğer fonksiyonu başka bir pakette kullanacaksanız (fonksiyonun ilk harfi büyük harfle başlamalıdır) return
yapacaklarınızı tam bir ifade olarak yazmanız daha iyi olacaktır. Kodu daha okunur hale getirir.
<<<<<<< HEAD func ToplaVeCarp(A, B int) (toplanan int, carpılan int) { toplanan = A+B carpılan = A*B
func SumAndProduct(A, B int) (add int, multiplied int) {
add = A+B
multiplied = A*B
eead24cf064976b648de5826eab51880c803b0fa return }
Go birden fazla argüman alabilen fonksiyonları destekler. Bunlara variadic (belirsiz-değişen sayıda argüman alan) fonksiyon denir.
func myfunc(arg ...int) {}
arg …int
kısmı Go ya bu fonksiyonun değişen sayıda argüman aldığını söyler. Bu argümanların türü int
dir. arg
fonksiyonun gövdesinde int
türünde bir slice
olur.
for _, n := range arg {
fmt.Printf("And the number is: %d\n", n)
eead24cf064976b648de5826eab51880c803b0fa }
Bir fonksiyon çağırıp ona argüman verdiğimizde o fonksiyon aslında değişkenin bir kopyasını alır. Dolayısı ile yapılan işlemler değişkende bir değişiklik yaratmaz.
Bunun kanıtı olarak bir örnek görelim.
package main
import "fmt"
<<<<<<< HEAD // a ya 1 eklemek için basit bir fonksiyon func birEkle(a int) int { a = a+1 // a'nın değeri değişti return a // a'nın yeni değeri döndürülüyor
// simple function to add 1 to a
func add1(a int) int {
a = a+1 // we change value of a
return a // return new value of a
eead24cf064976b648de5826eab51880c803b0fa }
func main() {
x := 3
<<<<<<< HEAD fmt.Println("x = ", x) // sonuç "x = 3" olmalı
x1 := birEkle(x) // birEkle(x) fonksiyonu çağırıldı
fmt.Println("x+1 = ", x1) // sonuç "x+1 = 4" olmalı
fmt.Println("x = ", x) // sonuç "x = 3" olmalı
}
Gördünüz mü? birEkle
fonksiyonuna x
i gönderdiğimiz halde asıl değeri değişmedi.
Sebebi basit: birEkle
i çağırdığımızda ona x
in bir kopyasını gönderdik x
in kendisini değil.
Şimdi sorabilirsiniz x
in kendisini nasıl fonksiyona verebilirim diye.
Burada pointer kullanmamız gerekiyor. Biliyoruz ki değişkenler bellekte tutulur ve bir adresleri vardır. Eğer değişkenin aslını değiştirmek istiyorsak onun bellek adresini kullanmalıyız. Böylelikle birEkle
fonksiyonu x
in adresini kullanarak onun değerini değiştirebilir. Parametre türünü *int
olarak değiştiriyoruz ve değişkenin adresini &x
ile fonksiyona veriyoruz. Fonksiyona değerin bir kopyasını değil de bir pointer verdiğimize dikkat edin.
fmt.Println("x = ", x) // should print "x = 3"
x1 := add1(x) // call add1(x)
fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
fmt.Println("x = ", x) // should print "x = 3"
}
Gördünüz mü? add1
fonksiyonuna x
i gönderdiğimiz halde asıl değeri değişmedi.
Sebebi basit: add1
i çağırdığımızda ona x
in bir kopyasını gönderdik x
in kendisini değil.
Şimdi sorabilirsiniz x
in kendisini nasıl fonksiyona verebilirim diye.
Burada pointer kullanmamız gerekiyor. Biliyoruz ki değişkenler bellekte tutulur ve bir adresleri vardır. Eğer değişkenin aslını değiştirmek istiyorsak onun bellek adresini kullanmalıyız. Böylelikle add1
fonksiyonu x
in adresini kullanarak onun değerini değiştirebilir. Parametre türünü *int
olarak değiştiriyoruz ve değişkenin adresini &x
ile fonksiyona veriyoruz. Fonksiyona değerin bir kopyasını değil de bir pointer verdiğimize dikkat edin.
eead24cf064976b648de5826eab51880c803b0fa
package main
import "fmt"
<<<<<<< HEAD // a ya 1 eklemek için basit bir fonksiyon func birEkle(a *int) int { *a = *a+1 // a'nın değeri değişti return *a // a'nın yeni değeri döndürülüyor
// simple function to add 1 to a
func add1(a *int) int {
*a = *a+1 // we changed value of a
return *a // return new value of a
eead24cf064976b648de5826eab51880c803b0fa }
func main() {
x := 3
<<<<<<< HEAD fmt.Println("x = ", x) // sonuç "x = 3" olmalı
x1 := add1(&x) // birEkle(x) fonksiyonu çağırıldı ve x'in adresi verildi
fmt.Println("x+1 = ", x1) // sonuç "x+1 = 4" olmalı
fmt.Println("x = ", x) // sonuç "x = 4" olmalı
======= fmt.Println("x = ", x) // should print "x = 3"
x1 := add1(&x) // call add1(&x) pass memory address of x
fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
fmt.Println("x = ", x) // should print "x = 4"
eead24cf064976b648de5826eab51880c803b0fa }
Şimdi x
in asıl değerini değiştirebiliriz. Neden pointer kullanıyoruz? Avantajı nedir?
- Bir değişken üzerinde çalışmak için birden fazla fonksiyon kullanabilmemize olanak sağlar.
- Adres (8 byte) verdiğimiz için maliyet azalır. Değerin kopyasını vermek maliyet ve zaman için verimli bir yöntem değildir.
string
,slice
,map
referans türlerdir. Yani fonksiyona verilirken standart olarak pointer olarak verilirler. (Dikkat: Eğerslice
ın uzunluğunu değiştirmek istiyorsanız açıkça pointer olarak vermeniz gerekir.)
Go da iyi tasarlanmış defer
(ertelemek) adlı bir terim vardır. Bir fonksiyonda birden fazla defer
ifadesi bulunabilir, program çalıştığında sondan başa sırayla çalışacaklardır. Programın dosya açtığı durumlarda bu dosyaların hata vermeden önce kapatılması gerekir. Örneklere bakalım.
func ReadWrite() bool {
file.Open("file")
// Do some work
if failureX {
eead24cf064976b648de5826eab51880c803b0fa file.Close() return false }
if failureY {
eead24cf064976b648de5826eab51880c803b0fa file.Close() return false }
file.Close()
return true
}
Bazı kodların tekrar ettiğini görüyoruz. defer
bu problemi çok iyi çözer. Daha temiz kod yazmanıza yardım etmekle kalmaz kodunuzu daha okunur yapar.
<<<<<<< HEAD func OkuYaz() bool { file.Open("dosya") defer file.Close() if hataX { return false } if hataY {
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
}
if failureY {
eead24cf064976b648de5826eab51880c803b0fa return false } return true }
Eğer birden fazla defer
varsa ters sırayla çalışırlar. Sıradaki örnek 4 3 2 1 0
sonucunu yazar.
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
Go'da fonksiyonlar aynı zamanda değişken olabilirler. type
onları kullanarak tanımlayabiliriz. Aynı imzaya sahip fonksiyonlar ayno tür olarak görülebilir.
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])
eead24cf064976b648de5826eab51880c803b0fa
Bunun avantajı nedir? Cevap, fonksiyonları değer olarak verebilmemizi sağlamasıdır.
package main
import "fmt"
<<<<<<< HEAD type testInt func(int) bool // değişken olarak fonksiyon tanımlandı
func tekMi(sayı int) bool {
if sayı%2 == 0 {
======= type testInt func(int) bool // define a function type of variable
func isOdd(integer int) bool {
if integer%2 == 0 {
eead24cf064976b648de5826eab51880c803b0fa return false } return true }
func isEven(integer int) bool {
if integer%2 == 0 {
eead24cf064976b648de5826eab51880c803b0fa return true } return false }
<<<<<<< HEAD // 'f' fonksiyonunu bir fonksiyona parametre olarak ata
func filtre(slice []int, f testInt) []int {
var sonuc []int
for _, deger := range slice {
if f(deger) {
sonuc = append(sonuc, deger)
}
}
return sonuc
=======
// pass the function f
as an argument to another function
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
eead24cf064976b648de5826eab51880c803b0fa }
func main(){
slice := []int {1, 2, 3, 4, 5, 7}
fmt.Println("slice = ", slice)
<<<<<<< HEAD tek := filtre(slice, tekMi) // fonksiyonu değer olarak kullan fmt.Println("Slice'daki tek sayılar: ", tek) çift := filtre(slice, çiftMi) fmt.Println("Slice'daki çift sayılar: ", çift) }
Interface kullanılan durumlarda çok yararlıdır. Gördüğünüz gibi testInt
fonksiyon türünde bir değişkendir ve filtre
'nin döndürdüğü argümanlar ve değerler testInt
ile aynıdır. Böylelikle programlarımızda karmaşık mantık yürütebilir ve esneklik kazanabiliriz.
odd := filter(slice, isOdd) // use function as values
fmt.Println("Odd elements of slice are: ", odd)
even := filter(slice, isEven)
fmt.Println("Even elements of slice are: ", even)
}
Interface kullanılan durumlarda çok yararlıdır. Gördüğünüz gibi testInt
fonksiyon türünde bir değişkendir ve filter
ın döndürdüğü argümanlar ve değerler testInt
ile aynıdır. Böylelikle programlarımızda karmaşık mantık yürütebilir ve esneklik kazanabiliriz.
eead24cf064976b648de5826eab51880c803b0fa
Go da Java gibi try-catch
yapısı yoktur. Go exception fırlatmak yerine panic
ve recover
ile hatalarla ilgilenir. Etkili olmasına karşın panic
çok fazla kullanılmamalıdır.
Panic
programın normal akışını durdurmak ve panik haline sokmak için kullanılır. F
adında bir fonksiyon panic
çağırdığında fonksiyon çalışmayı durdurur ve ertelenen defer
fonksiyonları çalıştırılır. Sonra F
panik halinin başladığı yere döner. Bütün fonksiyonlar F
gibi başladığı yerdeki goroutine
e dönmeden program sonlanmaz. panic
programın içinde panic
olarak çağırıldığında gerçekleşir. Ayrıca dizi sınırları dışına erişim hataları gibi bazı hatalar da panic
sebebi olabilir.
Recover
(kurtarmak) goroutine
leri panik halinden kurtarmak için kullanılır. defer
fonksiyonlarının içinde recover
çağırmak yararlıdır çünkü panik halinde normal fonksiyonlar çalışmayı durdurur. Çağırıldığında varsa panic
değerlerini yakalar yoksa nil
yakalar.
Aşağıdaki örnekte panic
nasıl kullanılır gösterilmiştir.
<<<<<<< HEAD var kullanıcı = os.Getenv("KULLANICI")
func init() {
if kullanıcı == "" {
panic("$KULLANICI için bir değer bulunamadı")
======= var user = os.Getenv("USER")
func init() {
if user == "" {
panic("no value for $USER")
eead24cf064976b648de5826eab51880c803b0fa } }
Bu örnek de panic
kontrolü yapılmasını gösterir.
func throwsPanic(f func()) (b bool) {
eead24cf064976b648de5826eab51880c803b0fa defer func() { if x := recover(); x != nil { b = true } }() <<<<<<< HEAD f() // eğer f() panic yaparsa recover yapılır ======= f() // if f causes panic, it will recover eead24cf064976b648de5826eab51880c803b0fa return }
init
fonksiyonu tüm paketlerde kullanılabilirken main
fonksiyonu sadece main
paketinde kullanılabilir. Bu iki fonksiyonun parametreleri yoktur ve değer döndürmezler. Bir paket içinde birden çok init
yazılabilse de sadece bir tane yazılmasını kesinlikle tavsiye ederim.
Go programları init()
ve main()
i otomatik çağırır. Her paket için init
fonksiyonu isteğe bağlı iken main
paketi için sadece bir tane main
fonksiyonu kesinlikle bulunmak zorundadır.
Programlar işleme main
paketinden başlar. Eğer main
başka paketler dahil (import) ediyorsa derleme sürecinde onlar da dahil edilir. Bir paket birden fazla kez dahil edildiyse bile sadece bir kere derlenir. Paketler dahil edildikten sonra program bu paketlerdeki değişkenleri ve sabitleri parafe eder ve sonra varsa init
çalıştırılır ve böyle devam eder. Bütün paketler parafe edildikten sonra program main
paketindeki değişkenleri ve sabitleri parafe eder ve varsa init
çalıştırılır. Alttaki şekil bu süreci gösterir.
Figure 2.6 Go da programların parafe edilmesinin akışı
eead24cf064976b648de5826eab51880c803b0fa
Go programlarında import
(dahil etmek) aşağıdaki gibi çok sık kullanılır
import(
"fmt"
)
Sonra dahil edilen bu paketteki fonksiyonlar aşağıdaki gibi kullanılır.
fmt.Println("hello world")
fmt
Go standart kütüphanesinde bulunur. Bilgisayarda $GOROOT/pkg da bulunur. Go üçüncü şahış paketlerini iki şekilde destekler.
- Göreceli yol import "./model" // load package in the same directory, I don't recommend this way.
- Kesin yol import "shorturl/model" // load package in path "$GOPATH/pkg/shorturl/model"
Paketler dahil edilirken kullanılan özel operatörler vardır ve bunlar genelde yeni başlayanların kafalarını kurcalar.
-
Nokta operatörü Bazen aşağıdaki gibi kullanıldığını görürüz.
import( . "fmt" )
Nokta operatörünün görevi, bir paketten fonksiyon çağırırken paketin adının yazılma gereksinimini kaldırmasıdır. Böylelikle
fmt.Printf("Hello world")
yerinePrintf("Hello world")
yazılır. -
Takma isim verme Pakete takma isim vererek fonksiyon çağırırken kullanılan ad değiştirilir.
import( f "fmt" )
Böylelikle
fmt.Printf("Hello world")
yerinef.Printf("Hello world")
yazılır. -
_
operatorü Bunu anlamak zordur özellikle biri size açıklamadıysa.import ( "database/sql" _ "github.com/ziutek/mymysql/godrv" )
Bu operatör dahil edilen paketin sadece
init
fonksiyonun çağrılıp çalıştırılması için kullanılır. Paketteki diğer fonksiyonları kullanacağınıza emin değilseniz kullanabilirsiniz.
<<<<<<< HEAD
- Rehber
- Önceki bölüm: Go temelleri =======
- Directory
- Önceki bölüm: Go foundation
eead24cf064976b648de5826eab51880c803b0fa
- Sonraki bölüm: struct