Verilənlərin tipləri, dəyişənlər və sabitlər. (Golang)
Bu məqalədə biz Golang-də sadə verilənlərinin tiplərinə nəzər salacaq, dəyişən və sabitlərin necə təyin olunduğunu öyrənəcəyik.
Dəyişən nədir?
Dəyişənlər proqramlaşdırmadakı ən vacib konseptlərdən biridir. Yazdığımız proqram təminatlarında çox zaman müəyyən bir dəyərin müvəqqəti yaddaşda saxlanılmasına və həmin dəyərin proqram daxilində istifadəsinə ehtiyac duyulur. Bu zaman həmin dəyərin yaddaşdakı ünvanını adlandırmaq gərəklidir. Dəyişən informasiya üçün simvolik bir addır. Biz bu ad vasitəsilə dəyişənin kompüter yaddaşındakı ünvanına istinad edərək həmin dəyişəndən proqram daxilində istifadə edirik. Hər bir dəyişənin təməl olaraq aşağıdakı 6 özəlliyi vardır.
- Adı
- Tipi
- Dəyəri
- Əhatə dairəsi (Scope)
- Yaşam dövrü (A Life Time)
- Yaddaşdakı ünvanı
- Ad
Ad informasiyanın simvolik “başlığıdır”. Çox güman ki, ad proqramçı üçün ən önəmli atributdur, çünki dəyişən həmin ad vasitəsilə əlçatandır. Hər bir dəyişənin mövcud olduğu “əhatə dairəsi”-ndə unikal bir adı olmalıdır.
2. Tip
Tip dəyişənin hansı növ dəyərləri özündə saxlaya biləcəyini göstərir. Proqramlaşdırma dillərini statik və dinamik tipli olmaqla iki növə ayırmaq olar. Statik tipli dillərdə (C, C++, Golang, Java) dəyişənin tipi onu istifadə etməzdən öncə bildirilməlidir. Dinamik tipli dillərdə (Python, JavaScript) isə dəyişənin tipi icra zamanı (run time) təyin olunur.
3. Əhatə dairəsi (Scope)
Yaxşı bir proqram, romanın fəsillərə bölündüyü və fəslin də paraqraflara bölündüyü kimi kiçik hissələrə (funksiyalara) “parçalanmışdır”. Bir funksiya daxilində təyin olunmuş dəyişən bu funksiyanın xaricində əlçatmazdır. Bu da bizə imkan verir ki, biz eyniadlı dəyişəni fərqli məqsədlər üçün istifadə edək. Nümunə olaraq “name” dəyişəni bir funksiya daxilində tələbənin, digər bir funksiyada isə şərabın adını göstərə bilər. Hər bir dəyişənin aktiv olduğu təsir dairəsi vardır.
package main
import "fmt"
// getStudentName və getWineName ayrı-ayrı əhatə dairəsidir
func getStudentName() string {
name := "John"
return name
}
func getWineName() string {
name := "Cabernet Franc"
return name
}
func main() {
fmt.Println(getPersonName())
fmt.Println(getWineName())
}
4. Yaşam dövrü (A Life Time)
Bir dəyişənin yaşam dövrü birbaşa onun əhatə dairəsi ilə əlaqələdir. Dəyişənlər onların təyin olduğu sətirdən başlayaraq “həyata gözlərini açar” və proqram onun təyin olunduğu əhatə dairəsindən kənara çıxan kimi “ölər”.
5. Yaddaşdakı ünvanı
Hər bir proqram icra olunan zaman OS tərəfindən həmin proqramın icrasına görə tələb olunan dəyişənlərin saxlanılması üçün yaddaş ayrılır. Hər bir dəyişən yaşam dövründə onun üçün ayrılmış yuvada (slot) mövcud olur.
Verilənlərin tipi
Golang-də dəyişənlərin tipini 4 qrupa bölə bilərik.
Bunlar aşağıdakılardır:
- Sadə tiplər (Basic types)
- Aqreqat tiplər (array)
- İstinad tiplər (struct)
- İnterface tiplər
Golang-də verilənlərin sadə tipləri aşağıdakılardır.
Dəyişənlərin susmaya görə dəyərləri (Zero value)
Golang-də digər proqramlaşdırma dillərindən fərqli olaraq dəyişən təyin olunan zaman ona dəyər verilməzsə, onun dəyəri null və ya undefined olmur. Təyin olunan dəyişənin tipinə uyğun ilkin dəyər (zero value) verilir. Bu ilkin dəyərlər yuxarıdakı cədvəldə göstərilmişdir.
Dəyişənlərin elan olunması
Golang-də dəyişənlərin elan olunmasının bir neçə yolu vardır. Ümumi sintaksis aşağıdakı kimidir:
var dəyişəninAdı dataType = ilkinDəyər
ilkinDəyər məcburi deyildir. Əgər ilkin dəyər təyin edilməzsə, onda dəyişənə verilən tipə uyğun zero value mənimsədiləcəkdir.
Aşağıdakı nümunədə biz integer tipində i dəyişənini elan etmişik.
var i int
Gördüyünüz kimi elan etmə zamanı dəyişənə heç bir dəyər verməmişik bu zaman i dəyişəni elan olunduğu tipə uyğun ilkin dəyərə (zero value) sahib olacaqdır. Bizim nümunədə i-nin dəyəri 0 olacaqdır. Bir çox dildən fərqli olaraq Golang-də dəyişənin tipi dəyişənin adından sonra qeyd olunur buna ilk zamanlar uyğunlaşmaq çətin ola bilər. Amma diqqət yetirsəniz, bu yanaşma daha çox ingilis dilinə yaxındır (i is integer).
Golang-də dəyişənin elanı zamanı da dəyər verə bilərik.
var i int = 1
Yuxarıda qeyd olunan hər iki növ dəyişən elan etmə yanaşmasına Golang-də uzun dəyişən elanı (long variable declarations) deyilir.
Biz həmçinin qisa dəyişən elanından da istifadə edə bilərik (short variable declaration).
i := 1
Bu tip dəyişən elanı yalnız lokal çərçivədə (local scope) edilə bilər. Yəni aşağıdakı kod hissəsi emal olunmayacaqdır.
package main
import (
"fmt"
)
i := 1
func main() {
fmt.Println(i)
}
Bu kodu emal etməyə çalışdıqda aşağıdakı xəta ilə qarşılaşacaqsınız.
./prog.go:8:1: syntax error: non-declaration statement outside function body
Golang statik tipli dil olsa da, siz dəyişəni aşağıdakı formada da təyin edə bilərsiniz( type inference). Bu halda Golang uyğun tipi dəyərə əsasən seçəcəkdir.
var i = 1
Siz bir neçə dəyişəni bir sətirdə elan edə bilərsiniz.
var var1, var2, var3 int
Həmçinin ilkin dəyər və qısa dəyişən elanını da bir sətirdə edə bilərsiniz.
var var1, var2, var3 int = 1, 2, 3
var var3, var4, var5 = 1, 2.2, false
var6, var7, var8 := 1, 2.2, false
Bir var bloku vasitəsilə fərqli tiplərdə olan dəyişənləri elan edə bilərsiniz.
var (
var1 = 50
var2 = 25.22
var3 string = “Salam Dünya”
var4 bool
)
Dəyişənlərin adlandırılması qaydaları
Golang dəyişənlərin adlandırılmasında çoxlu qadağalar tələb etmir, amma nəzərə alınmalı bir neçə qayda var ki, onlar aşağıdakılardır:
- Dəyişənin adı bir sözdən ibarət olmalıdır, arada heç bir boşluq olmamalıdır.
- Dəyişənlərin adlarında yalnız rəqəm, hərf və _ istifadə edə bilərsiniz.
- Dəyişənlərin adı rəqəm ilə başlaya bilməz.
Golang case sensitive olduğundan dəyişənlərin adlandırılmasında bir qədər diqqətli olmağınızda fayda var. Nümunə olaraq qeyd edə bilərik ki, userName və USERNAME ayrı-ayrı dəyişən adlarıdır.
Golang-də tövsiyə olunur ki, dəyişənlərin adı sadə və bir sözdən ibarət olsun, əgər dəyişənin adı iki sözdən ibarətdirsə, bu zaman tövsiyə olunan stil camelCase-dir. Siz altdan xətt də (_) istifadə edə bilərsiniz, amma bu Golangvari (Golang idiomatic) deyildir. Əgər dəyişənin adı böyük hərflə başlarsa, onda bu dəyişən digər paketler tərəfindən də əlçatan olacaqdır.
Tip çevrilməsi
Golang-də iki fərqli tipdə olan dəyişənlər üzərində riyazi əməliyyatlar etmək mümkün deyildir. İlk öncə həmin dəyişənlər eyni tipə çevrilməlidir.
Golang-də tiplərin konvertasiyası çox sadədir. Sadəcə dəyişəni hansı tipə çevirmək istəyirsinizsə, önünə həmin tipi əlavə edərək mörtərizə daxilinə dəyişəni yazmaq kifayətdir.
var1 := 10 // int
var2 := 10.5 // float64
// yanlış
// var3 := var1 + var2
// doğru
var3 := var1 + int(var2) // var3 => 20
Xüsusi tip
Golang-in daxilində bir neçə tip mövcuddur, amma biz istəsək, xüsusi tip də yarada bilərik.
type xüsusiTip mövcudTip
Yuxarıdakı sintaksisdə xüsusiTip mövcudTipdən törədilmişdir. mövcudTipin bütün xüsusiyyətləri xüsusiTipdə də olacaqdır və əlavə olaraq yeni xüsusiyyətlər əlavə edə bilərsiniz. Bu halda xüsusiTip və mövcudTipdən olan iki dəyişəni müqayisə edə bilmərik.
package main
import "fmt"
type float float64
func main() {
var f float = 52.2
var g float64 = 52.2 fmt.Println("f == g", f == g)
}
Bu kodu icra etməyə çalışdıqda aşağıdakı error ilə qarşılaşacağıq.
./prog.go:10:29: invalid operation: f == g (mismatched types float and float64)t
Tip təxəllüsü (Type Alias)
Aşağıdakı sintaksisdən istifadə edərək hər hansısa bir mövcud tip üçün təxəllüs (alias) yarada bilərik.
type təxəllüs = mövcudTip
Xüsusi tipdən fərqli olaraq yuxarıdakı halda biz yeni bir tip yaratmırıq, sadəcə olaraq mövcud tip üçün yeni bir ad təyin edirik. Ona görə də aşağıdakı nümunədə biz f və g dəyişənlərini bir-biri ilə müqayisə edə bilərik.
package main
import "fmt"
type float = float64
func main() {
var f float = 52.2
var g float64 = 52.2 fmt.Println("f == g", f == g)
}
f == g true
Sabitlər (Constants)
Sabit olaraq təyin olunmuş bir dəyişənin dəyəri proqramın icrası zamanı dəyişdirilə bilməz. Sabit dəyişənin dəyərini dəyişməyə cəhd etdiyinizdə error ilə qarşılaşacaqsınız. Golang-də sabit yaratmaq üçün const
açar sözündən istifadə etməlisiniz.
const sabitAdı [tipi] = sabit_dəyər
tip-i qeyd etmək məcburi deyildir Golang dəyərə əsasan müvafiq tipi seçəcəkdir.
const pi = 3.14
Golang-də sabitin dəyəri emal zamanı bilinməlidir. Əgər siz bir sabitə dəyər olaraq hansısa bir funksiyadan qayıdan dəyəri vermək istəsəniz, bu zaman siz error ilə qarşılaşacaqsınız.
package main
import (
"fmt"
"math"
)
func main() {
const a = math.Sqrt(4)
fmt.Println(a)
}
./prog.go:9:12: math.Sqrt(4) (value of type float64) is not constant
Dəyişənlərin təyini zamanı istifadə etdiyimiz yanaşmaları sabitlərə də tətbiq ede bilərik.
const const_1, const_2 = value_1, value_2
const (
const_1 = value_1
const_2 = value_2
)
Bir mötərizə daxilindəki sabitlərə açıq-aşkar dəyər verməmişiksə, dolayı yolla özündən əvəlki sabiti təkrarlaya bilər .
const (
a = 1 // a == 1
b = 2 // b == 2
c // c == 2
d // d == 2
)
iota
ifadəsi
Golang sadalanan sabitləri bəyan etmək üçün iota
açar sözünü təklif edir. Bu açar söz hər istifadə olunduğu zaman sabitin dəyərini 1 vahid artırır və bu artımı 0-dan başlayaraq edir.
const (
a = iota // a == 0
b = iota // b == 1
c = iota // c == 2
d // d == 3 (dolayısı ilə d = iota)
)
_ (blank identifier)
istifadə edərək iota
-nın dəyərini boş keçmək olar.
const (
a = iota + 1 // a == 1
_ // (dolayısı ilə _ = iota + 1 )
b // b == 3 (dolayısı ilə b = iota + 1 )
c // c == 4 (dolayısı ilə c = iota + 1 )
)
iota
üçün bir neçə nümunə
type Direction int
const (
North Direction = iota
East
South
West
)
const (
Blue int = iota
Green
Indigo
Orange
Red
Violet
Yellow
)