├── README.md └── lecturenotes ├── 0x01.md └── 0x02.md /README.md: -------------------------------------------------------------------------------- 1 | # Golang for Hackers Türkçe Eğitimi 2 | MDISEC Twitch kanalında yapılan `Golang for Hackers` isimli eğitim serisine ait materyallerin bulunduğu repodur. Siber güvenlik ile ilgili diğer tüm eğitimlerin linklerine https://github.com/mdisec/mdisec-twitch-yayinlari adresinden erişebilirsin. 3 | 4 | Bu eğitim serisi, başta Orhun(https://github.com/obegendi) olmak üzere, Ege Balcı(https://github.com/EgeBalci) ve topluluğun golang ile ilgili bilgisi olan muhtelif diğer bireyleri tarafından birlikte üretilmektedir. 5 | 6 | ## Yayın kataloğu 7 | 8 | 1. 0x01 | Golang For Hackers - Hellooooooo ! 9 | * [https://www.twitch.tv/videos/1143860097](https://www.twitch.tv/videos/1143860097) 10 | * [https://www.youtube.com/watch?v=jR683fqYVOo](https://www.youtube.com/watch?v=jR683fqYVOo) 11 | * [0x01 Lecture Notes](lecturenotes/0x01.md) 12 | 2. 0x02 | Golang For Hackers - Show Must "Go" on ! 13 | * [https://www.twitch.tv/videos/1150652332](https://www.twitch.tv/videos/1150652332) 14 | * [https://www.youtube.com/watch?v=pd1KdCinFA4](https://www.youtube.com/watch?v=pd1KdCinFA4) 15 | * [0x02 Lecture Notes](lecturenotes/0x02.md) 16 | 17 | ## Table of Content 18 | 19 | 20 | * [Introduction](lecturenotes/0x01.md#giriş) 21 | * [Language characteristics](lecturenotes/0x01.md#go-nedir) 22 | * [What is Go good at it?](lecturenotes/0x01.md#go'yu-ön-plana-çıkaran-etkenler) 23 | * [Tools](lecturenotes/0x01.md#araçlar) 24 | * [Environment & Setup](lecturenotes/0x01.md#ortam-ve-kurulum) 25 | 26 | * [Getting Started](lecturenotes/0x01.md#başlangıç) 27 | * [Primitive Data Types](lecturenotes/0x01.md#primitive-veri-yapıları) 28 | * [Pointers](lecturenotes/0x01.md#pointerlar) 29 | * [Iota and Constants](lecturenotes/0x01.md#iota-ve-constant) 30 | * [Arrays, slices and map data types](lecturenotes/0x01.md#array,-slice,-map,-ve-struct) 31 | * [Functions and methods](lecturenotes/0x01.md#fonksiyonlar) 32 | * [Return types and interfaces](#) 33 | * [Loops and branching](#) 34 | 35 | * [Go CLI](#) 36 | * [Go command](#) 37 | * [Building and Running Programs](#) 38 | * [Testing](#) 39 | 40 | * [Go Standard Library](#) 41 | * [Creating CLI Applications](#) 42 | * [Using fmt](#) 43 | * [Using os](#) 44 | * [Using Log](#) 45 | * [Using Time](#) 46 | * [Strings](#) 47 | * [Reflections](#) 48 | 49 | * [Custom Data Types](#) 50 | * [Interfaces And Strucs](#) 51 | * [Type definitions and Aliases](#) 52 | * [Composition with Embeded Types](#) 53 | * [Comparable Types](#) 54 | * [Switching Types](#) 55 | 56 | * [Packing](#) 57 | * [Elements of package](#) 58 | * [Working with packages](#) 59 | * [Packages to be used](#) 60 | * [Import and aliasing](#) 61 | 62 | * [Concurrent Programming](#) 63 | * [Goroutines](#) 64 | * [Sync package](#) 65 | * [Channels](#) 66 | 67 | * [Web Services](#) 68 | * [Handling HTTP requests](#) 69 | * [Persisting Data](#) 70 | * [Using Websockets](#) 71 | 72 | * [Testing](#) 73 | * [Introduction to testing](#) 74 | * [Creating and running tests](#) 75 | * [Benchmarking and profiling](#) 76 | 77 | * [IO Operations](#) 78 | * [File operations](#) 79 | * [Read/write memory](#) 80 | 81 | * [Data structures and Algorithms](#) 82 | * [Binary Trees](#) 83 | * [Heap](#) 84 | * [Linked Lists](#) 85 | * [Stack](#) 86 | * [Queue](#) 87 | * [Recursion](#) 88 | * [Big(O)](#) 89 | * [Sorting Algorithms](#) 90 | 91 | * [Design Patterns](#) 92 | * [Creational Patterns](#) 93 | * [Structural Patterns](#) 94 | * [Behavioral Patterns](#) 95 | 96 | 97 | ## Useful Links 98 | 99 | * [Golang](https://golang.org/) 100 | * [Golang By Example](https://gobyexample.com/) 101 | * [Go Design Patterns](https://www.godesignpatterns.com/) 102 | -------------------------------------------------------------------------------- /lecturenotes/0x01.md: -------------------------------------------------------------------------------- 1 | ## Giriş 2 | 3 | #### Go Nedir? 4 | 5 | Go basit, güvenilir ve verimli yazılımlar tasarlamamızı sağlayan açık kaynak bir yazılım dilidir. Google'daki bir takım ve birçok açık kaynak destekçisinin katılımıyla ortaya çıkmıştır. 6 | 7 | **Tasarlayanlar:** 8 | 9 | - Rob Pike 10 | - Robert Griesemer 11 | - Ken Thompson 12 | 13 | #### Go'nun Ortaya Çıkışı 14 | 15 | Google ağırlıklı olarak C++, Java ve Python kullanırken zaman içerisinde her birinin farklı dezavantajlarının var olduğu görülmüş ve type-safe, hızlı derlenen ve yüksek performanslı bir dil ihtiyacı sonucunda ortaya çıkmıştır. 16 | 17 | Aynı zamanda temelde task automation yani iş otomasyonu ihtiyacı da Go'nun çıkışında etkili olmuştur. 18 | 19 | #### Go'yu Ön Plana Çıkaran Etkenler 20 | 21 | - Basit 22 | - Hızlı 23 | - Kolay geliştirme yapabilme 24 | - İstediğin gibi referans modellerini, value objelerini yönetebilme 25 | - Varsayılan olarak concurrent çalışması yani paralelleştirme bulundurması 26 | - Gelişmiş standart kütüphaneleri 27 | - Pointer kullanım kolaylığı 28 | - Kolay adapte olabilme 29 | - Garbage colection yapması 30 | - İçinde C kodu yazabilme 31 | 32 | #### Araçlar 33 | 34 | Editör: Visual Studio Code 35 | 36 | Eklenti: Go (Go Team at Google) 37 | 38 | #### Ortam ve Kurulum 39 | 40 | https://golang.org/dl/ adresine giderek Go'nun işletim sisteminiz için uygun olan versiyonunu indirerek Go'yu kullanmaya başlayabilirsiniz. 41 | 42 | ## Başlangıç 43 | 44 | Bilgisayarınızda bir klasör açıp bu klasörü VsCode üzerinde açarak çalışmaya başlayabiliriz.(Klasör yapısı ilerleyen süreçte incelenecektir.) 45 | 46 | Klasörümüz içinde örneğin main.go isimli bir file oluşturalım. İlk yazacağımız satır paketimizin ismi olacak. 47 | 48 | ```go 49 | package main 50 | ``` 51 | 52 | Go packagelar ile çalışıyor yani dosyada package olmak zorunda. Main package ise diğer packagelardan farklı olarak bizim default yani varsayılan olarak çalıştırmak istediğimiz kısmı ifade ediyor. Bu, C'deki main ile benzer bir durum. 53 | 54 | Ardından kütüphaneleri dahil ediyoruz ve varsayılan fonksiyonumuz olan main'i ekliyoruz. Fonksiyon içinde fmt kütüphanesindeki Println metodu ile Hello Security! yazdırıyoruz. 55 | 56 | ```go 57 | package main 58 | 59 | import ( 60 | "fmt" 61 | ) 62 | 63 | func main(){ 64 | fmt.Println("Hello Security!") 65 | } 66 | ``` 67 | 68 | Bu noktada önemli bir ayrıntı var. Örneğin bizim main package'ımız altında iki ayrı read ve Read fonksiyonu olsaydı, **küçük harfle başlayan private**, **büyük harfle başlayan public** olacaktı. **Dolayısıyla private olanı sadece main package kullanabilirken, public olanı diğer packagelar da kullanabilecekti.** Bu durum aynı şekilde değişkenler için de söz konusu. 69 | 70 | Şimdi programı çalıştırabiliriz. Bunun için terminali açıyoruz. 71 | 72 | Programımızı `go run .` veya `go run main.go` ile doğrudan çalıştırabiliriz. Nokta ile main package'ı arayıp çalıştıracaktır. `go run` komutu sayesinde derlenmeden çalışabiliyor ve bu da geliştirme hızımızın artmasını sağlıyor. 73 | 74 | Programımızı `go build .` komutu ile derleyebiliriz. Bu derleme sonucunda bir .exe dosyası çıkacaktır. Bu dosyayı `.\main.exe` komutu ile çalıştırabiliriz. 75 | 76 | Burada aynı zamanda Go'nun dezavantajlarından biriyle karşılaşıyoruz. Oluşan exe dosyasının boyutunu incelediğimiz zaman 2mb civarında bir şeyle karşılaşıyoruz. Bunun nedeni Go'nun fmt kütüphanesinin tamamını statik bir şekilde exe dosyasına dahil etmiş olması. 77 | 78 | #### Primitive Veri Yapıları 79 | 80 | Değişken tanımlama kısmında Go bize farklı alternatifler sunuyor. 81 | 82 | ```go 83 | var i int 84 | i=42 85 | println(i) 86 | 87 | var f float32 = 3.14 88 | println(f) 89 | 90 | name := "MDI" 91 | println(name) 92 | ``` 93 | 94 | **NOT.1:** Değişkeni `:=` ile tanımladığımız zaman derleyici derleme esnasında değişkenin yapısına karar veriyor. Fakat biz tanımlarken yapısını belirtirsek doğrudan sınır çizmiş oluyoruz. 95 | 96 | **NOT.2:** Veri yapısını belirtirken sadece float ya da int yazabileceğimiz gibi float32, float64 ve int8, int16, int32, int64 gibi daha spesifik şekilde de yazabiliriz. 97 | 98 | Kullanılabilecek bütün veri yapılarına ulaşabilmek için: https://golangbyexample.com/all-data-types-in-golang-with-examples/ 99 | 100 | #### Pointerlar 101 | 102 | ```go 103 | var lastName *string = new(string) 104 | *lastName = "Demir" 105 | 106 | fmt.Println(lastName) //lastName'in adresini yazar. 107 | 108 | fmt.Println(*lastName) //Demir değerini yazar. 109 | ``` 110 | 111 | Pointerlar bellekteki adresi işaret eder. Dolayısıyla yukarıda lastName ile işaret edilen bir adresi new(string) ile oluşturuyoruz ve buna Demir değerini atıyoruz. 112 | 113 | Pointerları dinamik bellek yönetimi yapmak için kullanırız. Yani birden fazla paket aynı veri üzerinde çalışacaksa, bu verileri kopyalamak yerine verilerin adresine işaret ederek tek veri üzerinden bellek kullanımında verim sağlamış oluruz. Elbette bu aynı zamanda verinin değişmesi halinde bütün paketlerde verinin değişmesi demektir. 114 | 115 | ```go 116 | name := "MDI" 117 | 118 | var lastName *string = &name 119 | 120 | fmt.Println(*lastName, lastname, &name) //Çıktısı: MDI, lastname'in adresi, name'in adresi olur. 121 | ``` 122 | 123 | Yukarıdaki kodda name değişkeninin adresini alarak lastName'e veriyoruz. Dolayısıyla artık lastName, name'in değerine sahip oluyor. 124 | 125 | **NOT:** &, 'address of' demek oluyor. 126 | 127 | #### Iota ve Constant 128 | 129 | ```go 130 | const c int = 3 131 | println(c) 132 | ``` 133 | 134 | Constant derleme zamanında kullanılıyor. Derlenmiş bir çıktı alınıyor ve artık sabit bir şekilde kalıyor. Bir daha değiştirilemiyor. 135 | 136 | ```go 137 | package main 138 | 139 | func main(){ 140 | println(first,second,third) //Çıktısı: 0 1 2 141 | } 142 | const( 143 | first = iota 144 | second 145 | third 146 | ) 147 | ``` 148 | 149 | iota kullandığımız takdirde artan bir yapı oluşturuyor. 150 | 151 | ```go 152 | const( 153 | first = iota + 1 154 | second = 2 << iota 155 | third 156 | ) 157 | ``` 158 | 159 | Bu durumda çıktımız: 1 4 8 olur. `<<` shift yapıyor ve işlemci aritmetiği yapıyoruz. 160 | 161 | #### Array, Slice, Map ve Struct 162 | 163 | ##### Array 164 | 165 | ```go 166 | var arr [3]int 167 | arr[0] = 1 168 | 169 | fmt.Println(arr) 170 | ``` 171 | 172 | Array'in diğer elemanlarına atama yapmadığımız takdirde çıktımız: [1 0 0] şeklinde oluyor. 173 | 174 | Golang arrayle sabit boyutludur. Yani yukarıdaki array'e arr[3] diyerek 4. bir eleman atayamayız. Dinamik array diye bir şey yok. Bunun için farklı bir yapı var. 175 | 176 | ```go 177 | var arr [3]int 178 | arr[0] = 1 179 | 180 | arr2 := [3]int{1,2,3} 181 | fmt.Println(arr, arr2) 182 | ``` 183 | 184 | Array aynı zamanda `:=` işaretiyle de tanımlanabilmektedir. 185 | 186 | ##### Slice 187 | 188 | ```go 189 | slice := []int{1,2} 190 | 191 | fmt.Println(slice) 192 | ``` 193 | 194 | Slicelar bir nevi dinamik arraylerdir. Yani boyut belirtmek zorunda değiliz. 195 | 196 | **NOT:** Normal şartlarda tavsiye edilen boyutu belirlenmiş arrayler kullanmaktır. Çünkü sonrasında yapılacak işlerdeki performans açısından bakılınca boyutu belli olan arrayler, boyutu belli olmayan slicelara göre çok ciddi farklar yaratıyor. 197 | 198 | ```go 199 | slice2 := arr[1:2] 200 | fmt.Println(slice2) 201 | ``` 202 | 203 | Slice ile arrayde bölme işlemi yapıyoruz. Örneğin, yukarıda arrayin 1. elemanından ikinci elemanına kadar alıyoruz. 204 | 205 | ##### Map 206 | 207 | ```go 208 | m := map[string]int{"orhun",42} 209 | fmt.Println(m["orhun"]) //Çıktı: 42 210 | ``` 211 | 212 | Burada bir map tanımlıyoruz. Bu map'in key'inin string, value'sunun int olacağını belirtiyoruz. Aynı key'den sadece bir tane olabilir. 213 | 214 | ##### Struct 215 | 216 | ```go 217 | type person struct{ 218 | id int 219 | Name string 220 | } 221 | 222 | p := person{ 223 | id: 1, 224 | Name: "Orhun" 225 | } 226 | 227 | fmt.Println(p) //Çıktısı: {1 Orhun} olur. 228 | ``` 229 | 230 | Şimdi dosyalarımızı biraz daha düzenleyip farklı bir paket üzerinden çalışıyoruz. 231 | 232 | Bunun için önce bir models klasörü açıyoruz.. 233 | 234 | Models klasörü altında person.go dosyamızı oluşturuyoruz. person.go dosyası içerisinde bir Person struct'ı oluşturuyoruz. 235 | 236 | ```go 237 | package models 238 | 239 | type Person struct{ 240 | Id int64 241 | FirstName string 242 | LastName string 243 | } 244 | ``` 245 | 246 | Şimdi bu package'a main.go üzerinden ulaşmak istiyoruz. Bunun için önce dosya organizasyonuna dikkat ediyoruz. 247 | 248 | **NOT:** Golang için **gopath\src\github.com\github_isminiz\hello** şeklinde bir dosyalama ile çalışmanız tavsiye ediliyor. Bu şekilde diğer projelerinizdeki paketlere ulaşmanız da mümkün olmuş olacak. GOPATH ayarlama konusunda ve dosya ile kod organizasyonuna dair daha detaylı bilgi için https://golang.org/doc/code linkindeki dökümantasyonu incelemenizi tavsiye ederim. 249 | 250 | Ardından bir module oluşturuyoruz. Module bütün packagelarımızın bulunduğu yer oluyor. 251 | 252 | Module oluşturmak için`go mod init "github.com/github_isminiz/hello"` komutunu kullanıyoruz. 253 | 254 | Sonrasında main.go dosyamız içerisinde models package'ımızı import ediyoruz ve ardından bir user yaratıyoruz. 255 | 256 | ```go 257 | package main 258 | 259 | import ( 260 | "fmt" 261 | "github.com/github_isminiz/models" 262 | ) 263 | 264 | func main(){ 265 | u := models.Person{ 266 | Id: 2, 267 | FirstName: "Mehmet", 268 | LastName: "İnce" 269 | } 270 | 271 | fmt.Println(u.FirstName) 272 | } 273 | ``` 274 | 275 | ##### Go Constructor Çözümü 276 | 277 | Burada newPerson adında bir fonksiyon oluşturuyoruz. Bu fonksiyon aldığı parametrelerden bir Person struct'ı oluşturacak ve bunu return edecek. 278 | 279 | **NOT: Bunu yapmamızın sebebi Golang'de class olmaması ve dolayısıyla constructor olmaması. Object Oriented taktiklerini Golang'de bu şekilde çözüyoruz.** 280 | 281 | İkinci olarak SetNickName adında ikinci bir fonksiyon oluşturuyoruz ve bu sayede Person struct'ının nickName parametresine ulaşıp değiştirebilmeyi sağlıyoruz. 282 | 283 | ```go 284 | package models 285 | 286 | type Person struct { 287 | id int64 288 | firstName string 289 | lastName string 290 | nickName string 291 | } 292 | 293 | func NewPerson(id int64, firstName, lastName string) Person { 294 | return Person{ 295 | id: id, 296 | firstName: firstName, 297 | lastName: lastName, 298 | } 299 | } 300 | 301 | func (p Person) SetNickName(nickName string) { 302 | p.nickName = nickName 303 | } 304 | ``` 305 | 306 | Bu durumda main.go dosyasını da şu şekilde düzenlememiz gerekiyor: 307 | 308 | ```go 309 | package main 310 | 311 | import ( 312 | "github.com/github_isminiz/hello/models" 313 | "fmt" 314 | ) 315 | 316 | func main() { 317 | u := models.NewPerson("Mehmet", "İnce") 318 | u.SetNickName("mdisec") 319 | 320 | fmt.Println(u) 321 | } 322 | ``` 323 | 324 | **Fakat bu şekilde hâlâ user'ımızın nickName değişkenine ulaşamıyoruz. Çünkü SetNickName fonksiyonumuz hangi person'ın nickName'ini değiştirmek istediğimizi bilmiyor bunun için SetNickName fonksiyonumuzu pointer olacak şekilde düzenlememiz gerekiyor.** 325 | 326 | ```go 327 | func (p *Person) SetNickName(nickName string) { 328 | p.nickName = nickName 329 | } 330 | ``` 331 | 332 | Artık doğrudan değiştirmek istediğimiz user'ın adresini işaret etmiş oluyoruz. 333 | 334 | Aynı zamanda nickName'in hata kontrolünü de yapmak istersek kodumuzu tekrar düzenleyebiliriz. 335 | 336 | ```go 337 | func (p *Person) SetNickName(nickName string) error{ 338 | if len(nickName) == 0{ 339 | return errors.New("NickName must not be empty") 340 | } 341 | p.nickName = nickName 342 | return nil 343 | } 344 | ``` 345 | 346 | ve main.go'da da main fonksiyonumuzda değişiklik yaparak hatayı gösterebiliriz. 347 | 348 | ```go 349 | func main() { 350 | u := models.NewPerson("Mehmet", "İnce") 351 | err := u.SetNickName("mdisec") 352 | if err != nil{ 353 | fmt.Printf(err.Error()) 354 | } 355 | fmt.Println(u) 356 | 357 | } 358 | ``` 359 | 360 | #### Fonksiyonlar 361 | 362 | Fonksiyonlarımız hiçbir argüman almayabilir veya birden fazla argüman alabilir. https://tour.golang.org/basics/4 linkinde verilen örnek üzerinden gidersek: 363 | 364 | ```go 365 | package main 366 | 367 | import "fmt" 368 | 369 | func add(x int, y int) int { 370 | return x + y 371 | } 372 | 373 | func main() { 374 | fmt.Println(add(42, 13)) 375 | } 376 | ``` 377 | 378 | - add adından bir fonksiyon oluşturuyoruz. Önceden dediğimiz gibi büyük veya küçük harfle başlayarak private veya public olacağına da karar vermiş oluyoruz aynı zamanda. 379 | - Ardından parantez içerisinde var ise argümanlarımızı ve veri tiplerini yazıyoruz. Önce değişken ismini sonrasında tipini yazdığımıza dikkat ediyoruz. 380 | - Parantezden sonra eğer return edeceksek return tipini belirtiyoruz. Örneğin add fonksiyonu int tipinde return ediyor. Main fonksiyonu ise herhangi bir return yapmıyor. -------------------------------------------------------------------------------- /lecturenotes/0x02.md: -------------------------------------------------------------------------------- 1 | #### Interface 2 | 3 | Interfaceler, bizim structlarla ya da packagelarla iletişime geçmemizi sağlayacak fonksiyonlardır ve aslında bütün yapılar interfacelerle iletişime geçiyor. 4 | 5 | Interface, gerçek hayattan bir örnek olarak asansördeki tuş takımına benzetilebilir. Biz istediğimiz tuşa basıyoruz ve aslında onun arka planındaki işlemlerle uğraşmadan tuş üzerinden işimizi hallediyoruz. 6 | 7 | Bir önceki derste person.go adında bir dosyamız vardı ve package ismi models idi. Şimdi bu package altında bir interface tanımlayacağız. 8 | 9 | ```go 10 | package models 11 | 12 | type Identify interface{ 13 | Id() int64 14 | } 15 | ``` 16 | 17 | Bu şekilde Identify adında bir interface oluşturmuş olduk ve bu interface Id adlı bir fonksiyon barındırıyor. 18 | 19 | Ardından person'ın id'sini dönen Id fonksiyonumuzu oluşturuyoruz. 20 | 21 | ```go 22 | func (p *Person) Id() int64{ 23 | return p.id 24 | } 25 | ``` 26 | 27 | Interfacelere neden ihtiyacımız olsun ki gibi bir soru aklımıza gelebilir fakat bu özellikle kod kalabalığı arttığı zaman önemini gösterecektir. 28 | 29 | Interface aslında Go'da dile metamorphism katması için üretilmiş bir yapıdır. Interfaceleri bu şekilde blueprint olarak kullanabileceğimiz gibi aynı zamanda değişken tanımlarken de kullanabiliyoruz. Bu değişkenler runtime'da type casting yani çalışma sırasında tip dönüşümü yapmamızı sağlıyor. 30 | 31 | Örneğin bir kaynaktan json veri okuyoruz ve unmarshal ediyoruz. Json içerisindeki veri tipleri integer olabilir, string olabilir, object olabilir. Bu değişkeni interface olarak tanımlamamız runtime'da gelen verinin tipini kontrol etmemize olanak sağlıyor 32 | 33 | ##### Interface Örneği 34 | 35 | Bu örnekte interface'i tam anlamıyla kullanmış olmayacağız. Interface farklı packagelar ile çalışıldığında değer kazanmakta ve package konusunda ilerleyen derslerde daha detaylı değinilecek ve interfaceler de o noktada daha iyi anlaşılacaktır. 36 | 37 | Şimdi area.go isimli bir dosya oluşturalım. 38 | 39 | ```go 40 | package main 41 | 42 | import "math" 43 | 44 | type Circle struct{ 45 | Radius float64 46 | } 47 | 48 | func (c *Circle) Area() float64{ 49 | return math.Pi * math.Pow(c.Radius, 2) 50 | } 51 | 52 | type Square struct{ 53 | Width float64 54 | Height float64 55 | } 56 | 57 | func (s *Square) Area() float64{ 58 | return s.Width * s.Height 59 | } 60 | 61 | type Sizer interface{ 62 | Area() float64 63 | } 64 | 65 | func main(){ 66 | c := Circle{Radius: 10} 67 | fmt.Println(c) 68 | 69 | s := Square{Width: 10, Height: 8} 70 | fmt.Println(s) 71 | 72 | if c.Area() < s.Area(){ 73 | println("Circle less") 74 | }else{ 75 | fmt.Println(c.Area) 76 | } 77 | } 78 | ``` 79 | 80 | Burada circle ve square isimli iki struct oluşturduk ve bu structları referans alan iki adet Area fonksiyonu oluşturduk. Aynı zamanda Sizer isimli bir interface oluşturduk fakat aynı package içerisinde olduğumuz için kullanmadık. Eğer interface kullansaydık, örneğin area fonksiyonlarının float64 dönmesi noktasında limit çizebilirdik. 81 | 82 | Ayrıca parametre olarak interface alan bir fonksiyon yazabilirdik. Örneğin, 83 | 84 | ```go 85 | func Eq(s1, s2 Sizer){ 86 | if s1.Area() < s2.Area(){ 87 | println("Circle less") 88 | }else{ 89 | println("Square less") 90 | } 91 | } 92 | ``` 93 | 94 | Bu konulara ilerleyen derslerde daha detaylı değinilecek. 95 | 96 | **NOT:** Çok performans gerektiren durumlarda interface'den kaçınılır. Çünkü arka planda reflection denen bir yapı kullanır. 97 | 98 | #### Branching - If/Else 99 | 100 | If else genel yazılım dilleriyle aynı mantığa sahp. 101 | 102 | Yukarıdaki örneği alalım ve bir şart daha ekleyelim, 103 | 104 | ```go 105 | if s1.Area() < s2.Area(){ 106 | println("Circle less") 107 | } else if s2.Area() > s1.Area(){ 108 | println("Square less") 109 | } else{ 110 | println("Equal") 111 | } 112 | ``` 113 | 114 | Burada hangi şart durumu karşılarsa o şartın altındaki işlem uygulanacak, diğer işlemler uygulanmayacak. Eğer hiçbir şart karşılamazsa else kısmında belirtilen işlem uygulanacak. 115 | 116 | #### Döngüler 117 | 118 | Go'da farklı şekillerde for döngüsü yazabiliyoruz. 119 | 120 | ```go 121 | func main(){ 122 | i := 0 123 | for i <= 3{ 124 | i = i+1 125 | } 126 | 127 | for j := 7; j <= 10; j++{ 128 | 129 | } 130 | 131 | for{ 132 | 133 | } 134 | } 135 | ``` 136 | 137 | Son for döngüsü bir sonsuz döngü oluşturuyor. Go'da while vs. yok. Dolayısıyla neredeyse her şeyi for, switch ile hallediyoruz. 138 | 139 | For ile slice üzerinde dönerek elemanlarına ulaşabiliriz. 140 | 141 | ```go 142 | func main(){ 143 | hocalar := []string{} 144 | 145 | hocalar = append(hocalar, "Ege") 146 | hocalar = append(hocalar, "Orhun") 147 | 148 | for i := 0; i < len(hocalar); i++{ 149 | fmt.Println(hocalar[i]) 150 | } 151 | 152 | for _, v := range hocalar{ 153 | fmt.Println(v) 154 | } 155 | } 156 | ``` 157 | 158 | Burada ilk for döngüsünde klasik mantıkla elemanlara ulaşıyoruz. İkinci for dögüsünde ise range ile ulaşıyoruz. 159 | 160 | **NOT:** _ (alt çizgi), fonksiyondan kullanmak istemediğimiz şeyler dönmesin diye kullanılıyor. Modern dillerde bu kullanım yaygın. 161 | 162 | Range aynı zamanda maplerde de kullanılabiliyor. 163 | 164 | ```go 165 | haritalar := map[string]int{} 166 | 167 | haritalar["Ankara"] = 6 168 | haritalar["Bolu"] = 14 169 | 170 | for k, v := range haritalar{ 171 | fmt.Printf("Key: %s, value: %d\n", k,v) 172 | } 173 | ``` 174 | 175 | Eğer mapimizde herhangi bir key'in olup olmadığını kontrol etmek istersek, 176 | 177 | ```go 178 | if _, ok := haritalar["Bolu"]; ok{ 179 | fmt.Println("Bolu cok guzel") 180 | } 181 | ``` 182 | 183 | 184 | 185 | #### Switch-case 186 | 187 | Switch'te bir input, caseler üzerinden kontrol edilir ve girdiği case altındaki işlemler yapılır. Eğer hiçbir case'e girmezse en sonda belirtilen **default** altındaki işlemi yapar. Bir case tamamlandıktan sonra diğer caselere de bakmasını istiyorsak case sonuna **fallthrough** yazabiliriz. 188 | 189 | Aşağıdaki örnekte hem iota hem de switch case kullanımını görüyoruz. 190 | 191 | ```go 192 | package main 193 | 194 | import "fmt" 195 | 196 | const{ 197 | OCAK = iota 198 | SUBAT 199 | MART 200 | NISAN 201 | } 202 | 203 | func main(){ 204 | input = 0 205 | 206 | switch input{ 207 | case OCAK: 208 | fmt.Println("Kış kapıdan baktırır") 209 | } 210 | fallthrough 211 | case SUBAT, NISAN: 212 | fmt.Println("Kazma kürek yaktırır") 213 | } 214 | ``` 215 | 216 | --------------------------------------------------------------------------------