3-bo‘lim

O'zgaruvchilar va turlar

var va qisqa e'lon, nol qiymatlar, son turlari va ularning chegaralari, turlar orasida o'tkazish, doimiylar va iota.

🕑 16 daqiqa o‘qish 📄 1 096 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. E'lon qilishning uch yo'li
  2. Nol qiymatlar
  3. Son turlari
  4. Turlar aralashmaydi
  5. Butun va kasr bo'linish
  6. Bir vaqtda bir nechta
  7. Doimiylar
  8. iota - avtomatik raqamlash
  9. Turni tekshirish
  10. Xulosa

Go - statik turlar tili: har bir o'zgaruvchining turi kompilyatsiya paytida ma'lum bo'ladi va keyin o'zgarmaydi.

Lekin turni har doim yozish shart emas - Go uni ko'pincha o'zi aniqlaydi.

E'lon qilishning uch yo'li #

Go
package main

import "fmt"

func main() {
    var ism string = "Malika"
    var yosh = 20
    shahar := "Namangan"

    fmt.Println(ism, yosh, shahar)
    fmt.Printf("%T %T %T\n", ism, yosh, shahar)
}
Natija
Malika 20 Namangan
string int string

%T - qiymatning turini chiqaradi. Uchala shakl ham bir xil natija beradi, farq faqat yozuvda.

ShaklQayerda ishlaydi
var ism string = "..."Hamma joyda
var yosh = 20Hamma joyda
shahar := "..."Faqat funksiya ichida
:= funksiyadan tashqarida ishlamaydi

Paket darajasida, ya'ni funksiyalardan tashqarida, faqat var yozish mumkin:

Go
var Versiya = "1.0"   // to'g'ri
Versiya := "1.0"      // xato: syntax error

Sababi oddiy: paket darajasidagi har bir qator var, const, func yoki type bilan boshlanishi kerak.

Nol qiymatlar #

Go da e'lon qilingan, lekin qiymat berilmagan o'zgaruvchi hech qachon "chiqindi" bo'lmaydi. U doim aniq boshlang'ich qiymat oladi.

Go
package main

import "fmt"

func main() {
    var son int
    var kasr float64
    var matn string
    var bayroq bool

    fmt.Println(son, kasr, bayroq)
    fmt.Printf("matn: %q (uzunligi %d)\n", matn, len(matn))
}
Natija
0 0 false
matn: "" (uzunligi 0)
TurNol qiymati
int, float640
string"" (bo'sh satr)
boolfalse
Ko'rsatkich, slice, mapnil
Nol qiymat - bu Go ning asosiy g'oyalaridan biri

C da e'lon qilingan o'zgaruvchi ichida xotirada qolgan tasodifiy son bo'lardi. Bu dasturlash tarixidagi eng ko'p uchragan xatolar manbalaridan biri.

Go bu muammoni butunlay yo'q qildi. Bundan tashqari, ko'p turlar uchun nol qiymat foydali qilib tanlangan: bo'sh sync.Mutex darhol ishlaydi, bo'sh bytes.Buffer ga darhol yozish mumkin.

Buni "nol qiymat foydali bo'lsin" tamoyili deb atashadi.

Son turlari #

Go
package main

import "fmt"

func main() {
    var kichik int8 = 127
    var katta int64 = 9223372036854775807
    var musbat uint8 = 255

    fmt.Println(kichik, musbat)
    fmt.Println(katta)

    kichik++
    fmt.Println("127 ga 1 qo'shilgandan keyin:", kichik)
}
Natija
127 255
9223372036854775807
127 ga 1 qo'shilgandan keyin: -128

Oxirgi qatorga e'tibor bering. int8 eng kattasi 127; unga 1 qo'shilsa, u eng kichigiga aylanadi.

To'lib ketish jimgina sodir bo'ladi

Go son chegaradan oshganda hech qanday xato bermaydi. Qiymat shunchaki aylanib ketadi.

Bu C dan meros qolgan xatti-harakat va u tezlik uchun ataylab saqlangan: har bir qo'shishda tekshiruv qo'yish dasturni sekinlashtirardi.

Himoya usuli - to'g'ri tur tanlash. Amalda deyarli har doim oddiy int ishlatiladi: u 64 bitli tizimlarda 64 bitli bo'ladi va uni to'ldirish deyarli imkonsiz.

TurChegara
int8 / uint8-128..127 / 0..255
int16 / uint16-32768..32767 / 0..65535
int32 / uint32~2.1 milliard / ~4.3 milliard
int64 / uint64~9.2 kvintillion
intTizimga qarab 32 yoki 64 bit

byte - bu uint8 ning boshqa nomi, rune esa int32 niki. Ularni 4-bo'limda ko'ramiz.

Turlar aralashmaydi #

Bu Go ni ko'p tillardan ajratib turadigan qoida:

Go
package main

import "fmt"

func main() {
    var butun int = 7
    var kasr float64 = 2.5

    natija := float64(butun) * kasr
    fmt.Println(natija)

    yosh := 25
    fmt.Println("Yosh: " + fmt.Sprint(yosh))
}
Natija
17.5
Yosh: 25
Go avtomatik o'tkazmaydi

Ko'p tillarda 7 * 2.5 bemalol ishlaydi. Go da esa bu xato:

Go
var butun int = 7
var kasr float64 = 2.5
natija := butun * kasr   // mismatched types int and float64

Har bir o'tkazish ko'rinadigan bo'lishi kerak: float64(butun).

Bu ko'proq yozuv talab qiladi, lekin yashirin xatolarni yo'q qiladi - masalan, katta int64 ni float64 ga jimgina o'tkazib, aniqlikni yo'qotib qo'yishni.

Xuddi shunday, satr va sonni + bilan qo'shib bo'lmaydi: avval fmt.Sprint yoki strconv.Itoa bilan satrga aylantirish kerak.

Butun va kasr bo'linish #

Go
package main

import "fmt"

func main() {
    fmt.Println(7 / 2)
    fmt.Println(7 % 2)
    fmt.Println(7.0 / 2.0)
    fmt.Println(float64(7) / float64(2))

    fmt.Println(0.1 + 0.2)

    birinchi := 0.1
    ikkinchi := 0.2
    fmt.Println(birinchi + ikkinchi)
    fmt.Println(birinchi+ikkinchi == 0.3)
}
Natija
3
1
3.5
3.5
0.3
0.30000000000000004
false

Ikkita butun sonni bo'lsangiz, natija ham butun bo'ladi: 7 / 2 bu 3, 3.5 emas.

Oxirgi uch qator esa diqqat bilan qarashga arziydi. 0.1 + 0.2 aniq 0.3 chiqardi, lekin xuddi o'sha amal o'zgaruvchilar bilan bajarilganda boshqa natija berdi.

Doimiylar aniq, o'zgaruvchilar esa taxminiy

Sabab - Go ning kam tanilgan, lekin juda muhim xususiyati: turi belgilanmagan doimiylar cheksiz aniqlikda hisoblanadi.

fmt.Println(0.1 + 0.2) da ikkala son ham doimiy. Go ularni kompilyatsiya paytida, hech qanday yaxlitlashsiz qo'shadi va natijada aniq 0.3 hosil bo'ladi.

birinchi := 0.1 deb yozganingizda esa vaziyat o'zgaradi: endi bu haqiqiy float64 o'zgaruvchi. float64 sonlarni ikkilik kasr sifatida saqlaydi, o'nlik 0.1 ni esa ikkilikda aniq yozib bo'lmaydi - xuddi 1/3 ni o'nlikda aniq yozib bo'lmagani kabi. Shuning uchun qo'shishda farq ko'rinib qoladi.

Bu Go ga xos emas - float64 hamma tilda shunday ishlaydi. Go ning o'ziga xosligi - doimiylarning aniqligi.

Ikki amaliy qoida:

  1. Kasr sonlarni == bilan taqqoslamang. Yuqoridagi false aynan shuning natijasi.
  2. Pulni hech qachon float64 da saqlamang. Eng kichik birlikni butun son sifatida saqlang - so'mni emas, tiyinni. Buni 20-bo'limdagi loyihada shunday qilamiz.

Bir vaqtda bir nechta #

Go
package main

import "fmt"

func main() {
    ism, yosh, shahar := "Husanboy", 25, "Namangan"
    fmt.Println(ism, yosh, shahar)

    a, b := 10, 20
    a, b = b, a
    fmt.Println(a, b)

    var (
        sarlavha = "Hisobot"
        sahifa   = 12
        tayyor   = false
    )
    fmt.Println(sarlavha, sahifa, tayyor)
}
Natija
Husanboy 25 Namangan
20 10
Hisobot 12 false

a, b = b, a - ikki qiymatni almashtirishning eng qisqa yo'li. Vaqtinchalik o'zgaruvchi kerak emas.

var ( ... ) bloki esa bir nechta e'lonni bir joyga yig'adi.

Doimiylar #

Go
package main

import "fmt"

const Soliq = 0.12
const Shahar = "Namangan"

func main() {
    const MaxUrinish = 3

    maosh := 5000000.0
    fmt.Println("Soliq:", maosh*Soliq)
    fmt.Println(Shahar, MaxUrinish)
}
Natija
Soliq: 600000
Namangan 3

const qiymati kompilyatsiya paytida ma'lum bo'lishi kerak va keyin uni o'zgartirib bo'lmaydi.

Doimiylarning turi yo'q bo'lishi mumkin

const Soliq = 0.12 deganda Go unga tur bermaydi. U "turi belgilanmagan doimiy" bo'lib qoladi va kerak bo'lganda mos turga moslashadi.

Aynan shuning uchun maosh * Soliq ishlaydi, garchi maosh - float64 bo'lsa ham. Agar const Soliq float64 = 0.12 deb yozsak, u qat'iy float64 bo'lardi va int bilan ishlatib bo'lmasdi.

Bu kichik, lekin juda qulay imkoniyat.

iota - avtomatik raqamlash #

Go
package main

import "fmt"

const (
    Yangi = iota
    Jarayonda
    Bajarilgan
    Bekor
)

func main() {
    fmt.Println(Yangi, Jarayonda, Bajarilgan, Bekor)

    const (
        KB = 1 << (10 * (iota + 1))
        MB
        GB
    )
    fmt.Println(KB, MB, GB)
}
Natija
0 1 2 3
1024 1048576 1073741824

iota - const blokidagi qator raqami. U har bir yangi qatorda bittaga oshadi va blok boshida noldan boshlanadi.

Ikkinchi blokda ifoda takrorlanadi: qator bo'sh bo'lsa, Go yuqoridagi ifodani iota ning yangi qiymati bilan qayta hisoblaydi.

iota - Go dagi enum

Go da enum kalit so'zi yo'q. iota bilan yozilgan const bloki - uning o'rnini bosadigan odatiy usul.

Odatda unga o'z turi ham beriladi:

Go
type Holat int

const (
    Yangi Holat = iota
    Jarayonda
    Bajarilgan
)

Shunda Holat turi boshqa sonlar bilan aralashmaydi. Bu usulni 12-bo'limda, metodlar bilan birga ko'ramiz.

Turni tekshirish #

Go
package main

import "fmt"

func main() {
    qiymatlar := []any{42, "salom", 3.14, true}

    for _, q := range qiymatlar {
        fmt.Printf("%v -> %T\n", q, q)
    }
}
Natija
42 -> int
salom -> string
3.14 -> float64
true -> bool

any - istalgan turni saqlay oladigan tur. Uni 13-bo'limda, interfeyslar bilan birga tushunamiz.

%v - qiymatning odatiy ko'rinishi, %T esa turi.

ShablonNima chiqaradi
%vQiymat (odatiy shakl)
%TTur nomi
%dButun son
%sSatr
%qQo'shtirnoq ichidagi satr
%fKasr son
%ttrue yoki false
Amaliy topshiriq
  1. Bitta o'zgaruvchini uch xil usulda e'lon qiling.
  2. Har bir asosiy turning nol qiymatini chiqaring.
  3. int8 ni 127 dan oshirib, natijani ko'ring.
  4. int va float64 ni ko'paytirishga urinib, xatoni o'qing.
  5. Ularni float64(...) bilan to'g'ri ko'paytiring.
  6. 7 / 2 va 7.0 / 2.0 farqini ko'rsating.
  7. Ikki o'zgaruvchini bitta qatorda almashtiring.
  8. const qiymatini o'zgartirishga urinib ko'ring.
  9. iota bilan hafta kunlarini raqamlang.
  10. %v, %T, %q shablonlarini bitta dasturda sinang.

Xulosa #

  • Uch shakl bor: var turi bilan, var tursiz va :=. Oxirgisi faqat funksiya ichida ishlaydi.
  • E'lon qilingan o'zgaruvchi doim nol qiymat oladi - hech qachon chiqindi emas.
  • Son chegaradan oshganda jimgina aylanadi; odatda oddiy int ishlating.
  • Go turlarni avtomatik o'tkazmaydi: float64(butun) deb aniq yozish kerak.
  • Ikki butun sonning bo'linishi ham butun bo'ladi.
  • float64 da 0.1 + 0.2 aniq 0.3 bermaydi - pulni tiyinda, butun son sifatida saqlang.
  • const qiymati kompilyatsiya paytida ma'lum; turi belgilanmagan doimiy mos turga moslashadi.
  • iota - const blokidagi avtomatik raqamlash, Go dagi enum ning o'rnini bosadi.

Keyingi bo'limda satrlar, runalar va baytlarni o'rganamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.