Short notes about Golang
Oct 10, 2022/
#golang
/-7 minBasics
- Golang, C'ye benzer ancak sözdizimi daha basit, hızlıca derlenebilen ve multithread desteği sunan bir programlama dilidir. Çoğunlukla mikroservis uygulamalarında kullanılır.
- Paketlerin dökümantasyonlarını görmek için
, bir metodunun dökümantasyonu için dego doc fmt
komutları kullanılabilir.go doc fmt.Println
1func Fprint(w io.Writer, a ...any) (n int, err error)
2func Fprintf(w io.Writer, format string, a ...any) (n int, err error)
3func Fprintln(w io.Writer, a ...any) (n int, err error)
4func Print(a ...any) (n int, err error)
5func Printf(format string, a ...any) (n int, err error)
6func Println(a ...any) (n int, err error)
7func Sprint(a ...any) string
8func Sprintf(format string, a ...any) string
9func Sprintln(a ...any) string
10...
Hello World
- En basit Golang dosyasının yapısı aşağıdaki gibidir (kodu çalıştırmak için
):go run main.go
1// kod organizasyonu paketler ile sağlanır.
2// aynı klasör içinde bulunan dosyalarda paket ismi aynı olmalıdır.
3package main
4
5// kütüphaneler klasik şekilde dahil edilir.
6import "fmt"
7
8// programın giriş noktasıdır.
9// her pakette bir main fonksiyonu olabilir.
10func main() {
11 fmt.Println("Hello World")
12}
Print Methods
- Farklı yazdırma fonksiyonları mevcuttur.
ile başlayanlar stdout'a yani konsola çıktı verir ve byte sayısını döndürür.Print
olanlar dosya ve tarayıcı gibi dış bir kaynağa,Fprint
olanlar ise çıktıyı character buffer'da saklar. Yani değişkene çevirir.Sprint
1package main
2
3import "fmt"
4
5func main(){
6 fmt.Println("Hello!")
7 fmt.Print("Hello!\n")
8 fmt.Printf("Hi! My name is %s. I have lived in %s for %d years. They say the weather is amazing, which is %t", "Enes", "Bursa", 23, true)
9
10 // "Hello Enes!" metnini döndürür fakat konsola çıktı vermez.
11 result := fmt.Sprintf("Hello %s!", "Enes")
12}
Variables
- Veri tipleri şunlardır:
- Integer: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
- Float: float32, float64
- String: string
- Boolean: bool
- Null: nil
- Birçok farklı şekilde değişken tanımlayabiliriz. Değişkene tip verebilir yada tahmin ettirebiliriz.
1// yöntem 1
2count := 10
3// yöntem 2
4var age = 21
5// yöntem 3
6var minute int = 60
7// yöntem 4: constant
8const MAX_COUNT = 10
9// yöntem 5
10var city string
11city = "Bursa"
- Bir değişkenin türünü görmek için
kullanabiliriz.reflect.TypeOf()
1stringVar := "string"
2intVar := 10
3floatVar := 1.2
4boolVar := false
5arrayVar := []string{"foo", "bar", "baz"}
6objectVar := map[string]int{"apple": 23, "tomato": 13}
7nilVar := nil
8
9fmt.Println(reflect.TypeOf(stringVar))
10fmt.Println(reflect.TypeOf(intVar))
11fmt.Println(reflect.TypeOf(floatVar))
12fmt.Println(reflect.TypeOf(boolVar))
13fmt.Println(reflect.TypeOf(arrayVar))
14fmt.Println(reflect.TypeOf(objectVar))
15fmt.Println(reflect.TypeOf(nilVar))
string
int
float64
bool
[]string
map[string]int
- Golang'da değişken tip dönüşümleri için aynı isimde metodlar bulunur.
1floatNumber := 5.2
2intNumber := int(floatNumber)
3fmt.Println(intNumber)
5
Conditional Statements and Loops
koşulunda JavaScript'in aksine parantez kullanılmaz.if-else
1if num > 50 {
2 // ...
3} else if num > 20 {
4 // ...
5} else {
6 // ...
7}
- Fonksiyonun hatasız çalıştığı durumlarda bir kod çalıştırmak için özel bir sözdizimi var.
1// err değişkeni sadece bu blok içinden erişilebilir.
2if err := someFunction(); err != nil {
3 fmt.Println(err.Error())
4}
yapısının iki kullanımı vardır. Eğer altındakiswitch
ile ilerletmek istersekcase
kullanabiliriz.fallthrough
1// birinci yol
2var status string = "ERROR"
3
4switch status {
5 case "WARN":
6 // ...
7 case "ERROR":
8 // ...
9 default:
10 // ...
11}
12
13// ikinci yol:
14var num int = 25
15
16switch {
17 case num < 50:
18 // ...
19 case num < 100:
20 // ...
21 default:
22 // ...
23}
yapısının farklı kullanımları mevcuttur. Golang'defor
yapısı mevcut değildr.while
1for i := 1; i <= 100; i++ {
2 fmt.Println(i)
3}
Function
- Fonksiyon tanımlamak için
anahtar kelimesi kullanılır. Parametre veyahut dönüş tipini tanımlarken TypeScript'ten farklı olarak iki nokta kullanmayız.func
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func main() {
9 fmt.Println(getAgeByYear(1999))
10}
11
12func getAgeByYear(yearOfBirth int) int {
13 return time.Now().Year() - yearOfBirth
14}
- Fonksiyonlarda birden fazla değer döndürebiliriz.
1func getNumArray() (int, int) {
2 return 4, 5
3}
- Belirsiz sayıda argümanı koleksiyon olarak almak için
operatörünü kullanabiliriz. Bu fonksiyonlara variadic function denir....
1func printNames(names ...string) {
2 for _, name := range names {
3 fmt.Println(name)
4 }
5}
Array
- Array'ler sabit boyutlu olmalıdır ya da başlangıç değeri tanımlanmalıdır.
Yani
. Eğer girdiğimiz eleman kadar boyut alsın istersek yine[5]int != [4]int
operatörünü kullanabiliriz....
1var nums [5]int
2fmt.Println(nums)
3
4var nums2 [2]float64 = [2]float64{2.2, 3.8}
5fmt.Println(nums2)
6
7names := [4]string{"Ali", "Veli"}
8fmt.Println(names)
9
10names2 := [...]string{"Ali", "Veli", "Ahmet"}
11fmt.Print(names2)
12fmt.Println(" - type: ", reflect.TypeOf(names2))
[0 0 0 0 0]
[2.2 3.8]
[Ali Veli ]
[Ali Veli Ahmet] - type: [3]string
- Dizilerin elemanlarını iterate etmek istersek
kullanabiliriz.range
1nums := [5]int{1, 2, 3, 4, 5}
2
3for _, num := range nums {
4 fmt.Print(num)
5}
12345
- String değerleri iterate ederken de
kullanabiliriz. Ancak öğeyi değil, byte değerini döner. Dolayısıyla stringe çevirmemiz gerekir.range
1var mySentence = "Sentence"
2
3for index, letter := range mySentence {
4 fmt.Println("Index:", index, "Byte:", letter, "Letter:", string(letter))
5}
Index: 0 Byte: 83 Letter: S
Index: 1 Byte: 101 Letter: e
Index: 2 Byte: 110 Letter: n
Index: 3 Byte: 116 Letter: t
Index: 4 Byte: 101 Letter: e
Index: 5 Byte: 110 Letter: n
Index: 6 Byte: 99 Letter: c
Index: 7 Byte: 101 Letter: e
- Dinamik boyutlu array'ler de tanımlanabilir.
ifadesimake(type, len, cap)
,slice
ya damap
türünden nesne oluşturmak için kullanılır.channel
1// ilk parametre: eleman türü
2// ikinci parametre: başlangıç boyutu
3// üçüncü parametre: maksimum kapasite
4var mySlice []int = make([]int, 5, 10)
5
6fmt.Println(len(mySlice))
7fmt.Println(cap(mySlice))
5
10
- Diziyi bölmek istersek iki nokta sözdizimi kullanırız.
1nums := [5]int{1, 2, 3, 4, 5}
2someNums := nums[2:4]
3fmt.Println(reflect.TypeOf(someNums))
4fmt.Println(someNums)
[]int
[3, 4]
- Dinamik diziye eleman eklemek için built-in
metodunu kullanırız. Ekleme yapılacak diziyi ve elemanları alır.append()
1var arr []int = make([]int, 3, 10)
2newArr := append(arr, 5, 2, 7, 12)
3
4fmt.Println(newArr)
[0 0 0 5 2 7 12]
Map
- JavaScript'ten bildiğimiz obje gibi anahtar değer çifti tutan veri tipidir. Üç farklı şekilde tanımlayabiliriz.
1// birinci yol
2userInfo1 := map[string]string{
3 "name": "Cem",
4 "surname": "Yılmaz",
5}
6fmt.Println(userInfo1)
7
8// ikinci yol
9userInfo2 := map[string]string{}
10userInfo2["name"] = "Cem"
11userInfo2["surname"] = "Yılmaz"
12fmt.Println(userInfo2)
13
14// üçüncü yol
15var userInfo3 map[string]string = make(map[string]string)
16userInfo3["name"] = "Cem"
17userInfo3["surname"] = "Yılmaz"
18fmt.Println(userInfo3)
map[name:Cem surname:Yılmaz]
map[name:Cem surname:Yılmaz]
map[name:Cem surname:Yılmaz]
- Golang'de fonksiyonlar ve objeler genellikle iki değer döndürür. İkinci değer, işlemin başarılı olup olmadığını belirtir ve objede bir key olup olmadığını kontrol etmek için de kullanılabilir.
1userInfo := map[string]string{
2 "name": "Cem",
3 "surname": "Yılmaz",
4}
5
6city, hasCityKey := userInfo["city"]
7fmt.Println("value:", city)
8fmt.Println("hasCityKey:", hasCityKey)
9
10// yalnızca anahtar mevcut olduğunda bir işlem yapmak istersek
11userInfo["city"] = "Istanbul"
12if city, hasCityKey := userInfo["city"]; hasCityKey {
13 fmt.Printf("%s live in %s", userInfo["name"], city)
14}
value:
hasCityKey: false
Cem live in Istanbul
- Herhangi bir anahtarı silmek istersek
kullanabiliriz.delete()
1userInfo := map[string]string{
2 "name": "Cem",
3 "surname": "Yılmaz",
4}
5
6delete(userInfo, "surname")
7fmt.Println(userInfo)
map[name:Cem]
Package
- Built-in paketlerin yanında kendi paketimizi de oluşturabiliriz.
1package utils
2
3func Add(nums ...int) int {
4 total := 0
5
6 for _, num := range nums {
7 total += num
8 }
9
10 return total
11}
1package main
2
3import (
4 "fmt"
5 "{workspaceFolderName}/utils"
6)
7
8func main() {
9 utils.Add(2, 21)
10}
Unit Testing
- Dosyaların testleri aynı dizinde ve ilgili dosya isminin sonuna
eklenmiş şekilde olmalıdır._test
1package utils
2
3func Average(nums ...int) int {
4 total := 0
5
6 for _, num := range nums {
7 total += num
8 }
9
10 return total
11}
1package utils
2
3import (
4 "testing"
5)
6
7func TestAverage(t *testing.T) {
8 expected := 4
9 actual := Average(3, 2)
10
11 if actual != expected {
12 t.Errorf(
13 "Add function does not add up: Expected: %d, Actual: %d",
14 expected,
15 actual
16 )
17 }
18}