FREE

ΕΝΟΤΗΤΑ 5 GO - Understanding Data Types in GO (PART 2)

Στο σημερινό δωρεάν μάθημα προγραμματισμού GO (part 2), θα συνεχίσουμε να εξερευνούμε τα διάφορα data types (είδη δεδομένων) που υποστηρίζει η συγκεκριμένη γλώσσα όπως και πως ορίζουμε constants – δηλαδή μεταβλητές που η τιμή τους δεν μπορεί να αλλάξει μετά από την πρώτη ανάθεση τιμής. Επίσης θα δούμε τι σημαίνει το scope και πως επηρεάζει την πρόσβαση στις μεταβλητές. Επειδή η κάλυψη όλων αυτών των θεμάτων είναι αρκετά μεγάλη, την είχαμε χωρίσει σε δύο μέρη. Αυτό είναι το δεύτερο και τελευταίο μέρος.

Όπως ήδη έχουμε αναφέρει, μια σειρά από χαρακτήρες ονομάζονται strings. Για να αναθέσουμε ένα string σε μια μεταβλητή χρησιμοποιούμε τα double quotes “ “ όπως κάναμε και στα παραδείγματα μας στην προηγούμενη ενότητα. Αν και θα μιλήσουμε περισσότερο αργότερα για τις δυνατότητες που μας προσφέρει η GO σε σχέση με τα strings, ας δούμε ένα απλό παράδειγμα που μας δείχνει πως να παίρνουμε κάποιες χρήσιμες πληροφορίες από τα strings.

main.go

    package main

    import (
        "fmt"
    )
    
    func main() {
        fmt.Println(len("Michail Kassapoglou"))
        fmt.Println("Michail Kassapoglou"[1])
        fmt.Println("Michail, " + "Kassapoglou")
    }
         

Output

    19
    105
    Michail, Kassapoglou
         

Ας αναλύσουμε το output και ας εξηγήσουμε γιατί βλέπουμε τους αριθμούς 19 και 105. Στο πρώτο Println( ) χρησιμοποιούμε την len( ) function της GO να μας πει ποιος είναι ο ολικός αριθμός χαρακτήρων που περιέχονται μέσα στα “ ”. Αυτό συμπεριλαμβάνει και τυχόν κενό ή κενά που βρίσκονται ανάμεσα στους χαρακτήρες. Στο πρώτο Println( ) λοιπόν έχουμε 18 χαρακτήρες και ένα κενό ανάμεσα στα δύο ονόματα. Οπότε το σύνολο πολύ σωστά μας δίνεται σαν 19.

Στο δεύτερο Println( ) θέλουμε να βρούμε ποιος είναι ο χαρακτήρας στην θέση 1 του string. Έχει ανατεθεί σε κάθε string χαρακτήρα, εσωτερικά από την GO, ένας integer αριθμός που ονομάζεται index. Η αρίθμηση του index ξεκινάει από το 0 και όχι από το 1. Οπότε στο δικό μας παράδειγμα ζητάμε να βρούμε ποιος είναι ο χαρακτήρας που βρίσκεται στην θέση [1] του string. Λογικά θα περιμέναμε να δούμε το i, όμως το output είναι 105. Βασικά το 105 είναι η byte αντιπροσώπευση του χαρακτήρα i οπότε το αποτέλεσμα είναι σωστό.

Στο τελευταίο Println( ) δείχνουμε ότι όταν χρησιμοποιούμε το σύμβολο της πρόσθεσης με δύο strings ,επειδή είναι πρακτικά αδύνατον να προστεθούν αλγεβρικά τα strings, η GO αντί για πρόσθεση χρησιμοποιεί concatenation που στην ουσία πάει και “κολλάει” το ένα string δίπλα στο άλλο.

Ένα ακόμα χρήσιμο data type που υπάρχει σε όλες τις γλώσσες προγραμματισμού είναι το Boolean Type. Μια μεταβλητή που ορίζεται σαν Boolean μπορεί να πάρει μια από τις δύο τιμές – true ή false. Εάν δεν ορίσουμε εμείς κάποια αρχική τιμή τότε η τιμή της μεταβλητής θα είναι false. Για να ορίσουμε μια μεταβλητή σαν boolean χρησιμοποιούμε την λέξη bool.

main.go

    package main

    import (
        "fmt"
    )
    
    func main() {
        var b bool
        fmt.Println(b)
    }
         

Output

    false
         

Ας δούμε ένα ακόμα ένα παράδειγμα που χρησιμοποιεί boolean μεταβλητή.

main.go

    package main

    import (
        "fmt"
    )
    
    func main() {
        var b bool
        fmt.Println(b)
         b = true
         fmt.Println(b)
    }
         

Output

    false
    true
         

Υπάρχει τρόπος να μπορούμε να ελέγξουμε το data type της μεταβλητής? Ναι υπάρχει με την χρήση ενός πακέτου που ονομάζεται reflect. Ας δούμε ένα παράδειγμα όπου αναθέτουμε διαφορετικά είδη τιμών σε μερικές μεταβλητές και μετά ζητάμε να δούμε το data type των μεταβλητών.

main.go

    package main

    import (
        "fmt"
        "reflect"
    )
    
    func main() {
        var s string = "string"
        var i int = 10
        var f float32 = 1.2
        
        fmt.Println(reflect.TypeOf(s))
        fmt.Println(reflect.TypeOf(i))
        fmt.Println(reflect.TypeOf(f))
    }
         

Output

    string
    int
    float32
         

Μια λίγο πιο δύσκολη αλλά πολύ χρήσιμη διαδικασία είναι εκείνη της μετατροπής ενός data type σε ένα άλλο. Μια τέτοια πράξη ίσως είναι απαραίτητη όταν δεχόμαστε πολλαπλά δεδομένα από μια βάση και θέλουμε τα στοιχεία να τα μετατρέψουμε έτσι ώστε να μπορέσει η GO να τα διαχειριστεί κατάλληλα. Για να το καταφέρουμε αυτό, πρέπει να χρησιμοποιήσουμε ένα διαφορετικό πακέτο με το όνομα strconv. Το συγκεκριμένο πακέτο προσφέρει πολλές μεθόδους για να καλύψει όλες τις περιπτώσεις μετατροπής από ένα data type σε ένα άλλο. Ας δούμε ένα απλό παράδειγμα.

main.go

    package main

    import (
        "fmt"
        "reflect"
        "strconv"
    )
    
    func main() {
        var a int = 3
        fmt.Println(reflect.TypeOf(a))
        fmt.Println(a)
        var b = strconv.Itoa(a)
        fmt.Println(reflect.TypeOf(b))
        fmt.Println(b)
    }
         

Output

    int
    3
    string
    3
         

Τώρα που είμαστε αρκετά εξοικειωμένοι με τις μεταβλητές και τα data types στην Go, μπορούμε να αναφερθούμε και στα default values που έχουν οι μεταβλητές όταν τις ορίζουμε αλλά δεν αναθέτουμε τιμές σε αυτές. Η Go, όποτε βλέπει να έχει οριστεί μια μεταβλητή χωρίς κάποια τιμή, της αναθέτει μια default τιμή σαν αρχική τιμή της μεταβλητής. Ας δούμε ένα απλό πρόγραμμα που δείχνει ποιες είναι οι default τιμές σε διάφορα data types.

main.go

    package main

    import (
        "fmt"
    )
    
    func main() {
    var i int
    var f float64
    var b bool
    var s string
    
    fmt.Println("The default value for an integer variable is: ", i)
    fmt.Println("The default value for a float64 variable is: ", f)
    fmt.Println("The default value for a boolean variable is: ", b)
    fmt.Println("The default value for a string variable is: ", s)
    }
         

Output

    The default value for an integer variable is:  0
    The default value for a float64 variable is:  0
    The default value for a boolean variable is:  false
    The default value for a string variable is:
         

Σε πολλές γλώσσες προγραμματισμού, αν όχι σε όλες, θα ακούσετε πολλές φορές την ορολογία scope ή scope of variable. Αυτό με λίγα και απλά λόγια σημαίνει από που μέσα στο πρόγραμμα μας έχουμε πρόσβαση στις μεταβλητές έτσι ώστε να τις χρησιμοποιήσουμε. Επειδή οι μεταβλητές σε ένα πρόγραμμα μπορεί να είναι όλες γραμμένες στο ίδιο αρχείο, αυτό δεν σημαίνει ότι όλα τα στοιχεία του κώδικα (που ανήκουν στο ίδιο αρχείο) μπορούν να τις δουν. Αυτή η έννοια θα γίνει πολύ πιο ξεκάθαρη σε λίγο εφόσον μιλήσουμε και ορίσουμε τι είναι το block κώδικα.

Αν προσέξετε τον ορισμό της function main() θα παρατηρήσετε ότι αμέσως μετά ανοίγουμε και κλείνουμε άγκιστρα ( { } ). Μέσα στα άγκιστρα γράφουμε τον κώδικα που μπορεί να τρέχει η main( ). Όλες οι μεταβλητές που ορίζουμε μέσα στην main( ) και κατά συνέπεια μέσα στο block κώδικα που ορίζεται από τα άγκιστρα, θεωρούνται local μεταβλητές της main( ) και κανένας άλλος έξω από την main( ) δεν μπορεί να έχει πρόσβαση σε αυτές και να τις καλέσει.

Οπότε αν θέλατε όλα τα functions από τα οποία θα αποτελείται ο κώδικας σας να έχουν πρόσβαση σε κάποια μεταβλητή τότε θα ήταν καλό να ορίσετε αυτή την μεταβλητή ένα επίπεδο πιο πάνω. Κατά κάποιο τρόπο ορίζεται την μεταβλητή να είναι global και οποιαδήποτε function ή λειτουργία του προγράμματος μπορεί να την καλέσει και να την χρησιμοποιήσει.

main.go

    package main

    import (
        "fmt"
    )
    
    var name string = "Michail"
    
    func main() {
    fmt.Println("Your name is:", name)
    }
         

Output

    Your name is: Michail
         

Το τελευταίο κομμάτι θεωρίας που μας έχει μείνει όσον αφορά τις μεταβλητές είναι η έννοια του constants. Στην ουσία μια constant variable μπορεί να δεχτεί τιμή για την πρώτη μόνο φορά και από εκεί και πέρα δεν μπορεί να αλλάξει η τιμή της. Αν προσπαθήσουμε να την αλλάξουμε προγραμματιστικά κατά την εκτέλεση του προγράμματος μας, θα λάβουμε μήνυμα λάθους από τον compiler της Go. Για να ορίσουμε μια μεταβλητή σαν constant γράφουμε const μπροστά από το όνομα της μεταβλητής.

main.go

    package main

    import (
        "fmt"
    )
    
    func main() {
    const name string = "Michail"
    fmt.Println("Your name is:", name)
    name = "Michail Kassapoglou"
    fmt.Println("Your new name is:", name)
    }
         

Output

    src\main.go:10:6: cannot assign to name