Konstantat

Konstantat në Go emërtohen njëjtë sikurse edhe variablat, pra nuk bëhet si p.sh. në PHP ku për emërtimet e konstantave përdoret vetëm shkronjat kapitale dhe nënvizimi (sikurse që është FILTER_SANITIZE_STRING).

Duhet marrë parasysh se të gjitha variablat dhe konstantat që fillojnë me shkronjë kapitale, në Go e kanë kuptimin se ato variabla/konstanta do të eksportohen, ndërsa nëse janë me të vogla – do të jenë variabla/konstanta lokale në raport me pakon.

Kontantat deklarohen me fjalën const.

package main

import (
    "fmt"
)

func main() {
    // numriPi nuk eksportohet
    const numriPi float64 = 3.141592653589793
    fmt.Println(numriPi)

    // NumriPi eksportohet
    const NumriPi float64 = 3.141592653589793
    fmt.Println(NumriPi)
}

https://play.golang.org/p/VK3ar1gF60i

Rezultati:

3.141592653589793
3.141592653589793

Programi vijues nuk do të kompajlohet, për shkak se në rreshtin 11 përpiqemi t’ia ndryshojmë vlerën konstantës, me ç’rast lajmërohet gabimi cannot assign to numriPi.

package main

import (
    "fmt"
)

func main() {
    const numriPi float64 = 3.141592653589793
    fmt.Println(numriPi)

    numriPi = 3.14
    fmt.Println(numriPi)
}

https://play.golang.org/p/oUNUv_8-Sbr

Rezultati:

./prog.go:11:10: cannot assign to numriPi

Karakteristikë e konstantave është se caktimi i vlerave të tyre duhet të jetë i verifikueshëm qysh në fazën e kompajlimit. Kjo do të thotë se konstantës nuk mundemi t’i japim vlerë që kthehet nga një funksion gjatë ekzekutimit të programit (runtime).

package main

import (
    "fmt"
    "math"
)

func main() {
    const n = math.Sqrt(9)
    fmt.Println(n)
}

https://play.golang.org/p/tvBSOxAdml4

Rezultati:

./prog.go:9:8: const initializer math.Sqrt(9) is not a constant

Edhe pse e dijmë që vlera do të ishte 3, konstanta n nuk e merr atë vlerë dhe lajmërohet gabimi const initializer math.Sqrt(9) is not a constant, sepse ajo vlerë është rezultat kthyes i një funksioni gjatë ekzekutimit të programit dhe kompajleri nuk mund ta “dijë” paraprakisht atë vlerë.

Po ashtu, nuk lejohen as shprehjet, rezultati i të cilave mund të dihet vetëm gjatë kohës së ekzekutimit, siç është rasti me krahasimin e vlerave të dy variablave si në shembullin vijues:

package main

import (
    "fmt"
)

func main() {
    var a, b = 5, 7
    const n = a < b
    fmt.Println(n)
}

https://play.golang.org/p/WdCrkF70PIB

Rezultati:

./prog.go:9:8: const initializer a < b is not a constant

Konstantave mund t’iu caktohen vetëm vlera primitive:

  • int
  • float
  • boolean
  • string

Nuk mund të përdoren tipet më komplekse siç janë:

  • vargjet
  • segmentet
  • struktet
  • mapat

sepse këto për nga natyra janë variabile.

E përbashkëta e variablave dhe konstantave është se me të dyja mund të zbatohet “shadowing”, që do të thotë ridefinimi i një vlere të re të variablit/konstantës brenda një blloku që është brenda një blloku tjetër ku tashmë është deklaruar po ai variabël apo konstantë. Blloku që është me hiearki më të ultë mund të bëjë “shadow” (t’i zëvendësojë vlerat) një variable/konstante tashmë të definuar në bllokun me hierarki më të lartë.

package main

import (
    "fmt"
)

const n = 7

func main() {
    const n = 5
    fmt.Println(n)
}

https://play.golang.org/p/bv_obpquhTf

Rezultati:

5

E shohim që deklarimi i konstantës në rreshtin 10, “e mbulon” vlerën e konstantës së njëjtë të deklaruar në rreshtin 7. Kjo ndodh për shkak se blloku ku gjendet const n=7 me hierarki është më “sipër” prej bllokut ku gjendet const n = 5. Me fjalë të tjera, blloku i brendshëm ka prioritet më të lartë.

Megjithëse i mundur, ndryshimi i vlerës së konstantës në bllokun e brendshëm mund të jetë burim potencial i ndonjë “bug” , nëse rastësisht në ato dy blloqe kemi deklaruar dy konstanta me emër të njëjtë por me dedikime të ndryshme.

Për më tepër, “shadowing”, përveç vlerës lejon edhe ndryshimin e tipit të konstantës! Kjo potencialisht mund të shkaktojë probleme gjatë kompajlimit ose ekzekutimit të programit.

package main

import (
    "fmt"
)

const n int = 7

func main() {
    const n string = "test"
    fmt.Println(n)
}

https://play.golang.org/p/W_HO2UUq-TF

Rezultati:

test

Vërejmë se konstanta n, në rreshtin 7 është integer, ndërsa në rreshtin 10 është string.

Lirisht mund të kryejmë operacione ndërmjet variablave dhe konstantave nëse janë të tipit të njëjtë.

package main

import (
    "fmt"
    "math"
)

func main() {
    const a float64 = 7
    var b float64 = 9

    // Teorema e Pitagorës
    fmt.Println(math.Sqrt(math.Pow(a, 2) + math.Pow(b, 2)))
}

https://play.golang.org/p/2e8cbW5l-UZ

Rezultati:

11.40175425099138

Në Go, nuk lejohen operacione ndërmjet dy tipeve të ndryshme, as ndërmjet dy nëntipeve, si për shembull operacioni i mbledhjes ndërmjet int8 dhe int16.

package main

import (
    "fmt"
)

func main() {
    var a int8 = 7
    var b int16 = 12
    fmt.Println(a + b)
}

https://play.golang.org/p/hx5eKdK0orw

Rezultati:

./prog.go:10:16: invalid operation: a + b (mismatched types int8 and int16)

Gabim i ngjashëm paraqitet edhe kur lejojmë që Go ta konkludojë vetë tipin e një variabli, si në rreshtin 8 të shembullit vijues:

package main

import (
    "fmt"
)

func main() {
    var a = 7
    var b int16 = 12
    fmt.Println(a + b)
}

Rezultati:

./prog.go:10:16: invalid operation: a + b (mismatched types int and int16)

Dy shembujt e fundit i dhamë me variabla, për të potencuar dallimin me rastin kur përdorim konkludimin e tipit (type inference) të konstantë, me ç’rast Go nuk do të “ankohet” për faktin që janë dy nëntipe të ndryshme dhe vetë do ta bëjë konvertimin e nëntipeve asisoj që të përputhen.

package main

import (
    "fmt"
)

func main() {
    const a = 7
    var b int8 = 12
    fmt.Printf("%T, %T\n", a, b)

    c := a + b
    fmt.Printf("%T, %v\n", c, c)
}

https://play.golang.org/p/7cr_-7Exu7d

Rezultati:

int, int8
int8, 19

Pra, Go e sheh konstantën a si int, ndërsa variablin b si int8. Mirëpo, pas mbledhjes së vlerave të tyre, rezultati (19) është i tipit int8.

Pra, ndërmjet int dhe int8, për rezultat ka zgjedhur tipin int8, i cili ka diapazon më të ngushtë të vlerave. Kjo është në rregull për aq kohë sa vlera e rezultatit gjatë ekzekutimit të programit nuk e tejkalon vlerën 127, sa është vlera maksimale e tipit int8.

Nëse vlera e rezultatit e tejkalon vlerën maksimale të nëntipit të caktuar, ndodh overflow pa kurrfarë lajmërimi mbi tejkalimin e vlerës maksimale, që shpie drejt rezultateve të gabuara.

package main

import (
    "fmt"
)

func main() {
    const a = 12
    var b int8 = 120
    fmt.Printf("%T, %T\n", a, b)

    c := a + b
    fmt.Printf("%T, %v\n", c, c)
}

https://play.golang.org/p/tAkX2-YhJln

Rezultati:

int, int8
int8, -124

Shohim se 120 + 12, në vend të 132 është -124. Kjo për shkak se është bërë një “rotacion” nëpër vlerat e int8 (-128 deri 127).

+0+1+2+3+4+5+6+7+8+9+10+11+12
120121122123124125126127-128-127-126-125-124

Enumerated constants

package main

import (
    "fmt"
)

func main() {
    const (
        x = iota
        y = iota
        z = iota
    )

    fmt.Printf("%T, %T, %T\n", x, y, z)
    fmt.Printf("%v, %v, %v\n", x, y, z)
}

https://play.golang.org/p/Kl5LHx9Uo0o

Rezultati:

int, int, int
0, 1, 2

Rezultat të njëjtë na jep edhe ky kod:

package main

import (
    "fmt"
)

func main() {
    const (
        x = iota
        y
        z
    )

    fmt.Printf("%T, %T, %T\n", x, y, z)
    fmt.Printf("%v, %v, %v\n", x, y, z)
}

https://play.golang.org/p/aKN4PxzypFD

Kjo për shkak se kompajleri nënkupton se edhe konstantat në vijim marrin vlerën iota.

Vlera iota është vlerë speciale për numërim duke filluar nga 0 dhe është e tipit int. Çdo konstantë vijuese brenda bllokut, merr vlerë për 1 më të madhe se konstanta paraprake.

Vlen vetëm për blloqe konstantash të deklaruara me:

const (

)

Por nuk vlen nëse konstantat janë deklaruar si vijon:

    const x = iota
    const y = iota
    const z = iota

Me këtë mënyrë te deklarimit, të tre konstantat (x, y dhe z) do të kenë vlerë 0.

Çdo bllok konstantash me vlerë iota, fillon prej zeros:

package main

import (
    "fmt"
)

func main() {
    const (
        x = iota
        y
        z
    )

    const (
        a = iota
        b
    )

    fmt.Printf("%v, %v, %v\n", x, y, z)
    fmt.Printf("%v, %v\n", a, b)
}

https://play.golang.org/p/ker4s4okHwW

Rezultati:

0, 1, 2
0, 1

Listë të tillë konstantash të paradefinuara me vlerë inkrementale mund të përdorim kur dëshirojmë në program të bëjmë krahasime.

package main

import (
    "fmt"
)

func main() {
    const (
        a = iota
        b
        c
    )

    x := 2

    fmt.Printf("%v\n", x == a)
    fmt.Printf("%v\n", x == b)
    fmt.Printf("%v\n", x == c)
}

https://play.golang.org/p/oYSJVpMUw1l

Rezultati:

false
false
true

Nëse fare s’na interson vlera 0, ndërsa këto konstanta gjithmonë fillojnë nga 0, atëherë vlerën e parë e vendosim në _, që është* write only variable*, pra variabël në të cilin mund të vendosim vlerë, por asaj vlere nuk mund t’i referohemi më pas, pra praktikisht ajo vlerë do të humbet.

package main

import (
    "fmt"
)

func main() {
    const (
        _ = iota
        a
        b
    )

    x := 1

    fmt.Printf("%v\n", x == a)
    fmt.Printf("%v\n", x == b)
}

https://play.golang.org/p/dsBbDsodtap

Rezultati:

true
false

Nëse numërimin dëshirojmë ta fillojmë nga një numër tjetër, atëherë konstantës së parë ia rrisim apo zvogëlojmë vlerën, në varësi prej vlerës së dëshiruar.

package main

import (
    "fmt"
)

func main() {
    const (
        _ = iota - 4
        a
        b
    )

    const (
        _ = iota + 4
        x
        y
    )

    fmt.Printf("a=%v, b=%v\n", a, b)
    fmt.Printf("x=%v, y=%v\n", x, y)
}

https://play.golang.org/p/PZ51jnTUzp7

Rezultati:

a=-3, b=-2
x=5, y=6

Vërejmë se kontanta a fillon nga -3, ndërsa konstanta x nga 5.

Përveç mbledhjes dhe zbritjes, mund të përdorim të gjithë operatorët që janë në dispozicion për vlerat primitive.

All Rights Reserved Theme by 404 THEME.