FREE

ΕΝΟΤΗΤΑ 9 GO - Accepting Input from User

Στο σημερινό δωρεάν μάθημα GO θα δούμε πως μπορούμε να δώσουμε τιμές στο πρόγραμμα μας ενώ ο κώδικας μας εκτελείται. Με άλλα λόγια θέλουμε το πρόγραμμα μας να έχει την δυνατότητα να δέχεται τιμές από τον χρήστη ενώ τρέχει.

Για να μπορέσουμε να δώσουμε μια τέτοια ικανότητα στο πρόγραμμα μας, θα πρέπει να προσθέσουμε κάποια επιπλέον πακέτα εκτός από το “fmt”. Επίσης, καλό θα είναι να αρχίζουμε να ψάχνουμε και το documentation της GO για επιπλέον δυνατότητες στο ίδιο θέμα. Οι δυνατότητες στις οποίες αναφερόμαστε δεν είναι τίποτα άλλο από μεθόδους που μας προσφέρει η GO και η εξοικείωση σας με το documentation θα είναι μια πολύτιμη επένδυση χρόνου.

Στην Ενότητα 6 των δωρεάν μαθημάτων GO είχαμε χρησιμοποιήσει ένα απλό πρόγραμμα για να δείξουμε την λογική του if else. Θα χρησιμοποιήσουμε λοιπόν το ίδιο πρόγραμμα και θα το τροποποιήσουμε έτσι ώστε να ζητάει από τον χρήστη να γράψει έναν ακέραιο αριθμό αντί να είναι μόνιμα γραμμένος μέσα στον κώδικα. Ας θυμηθούμε ξανά το πρόγραμμα μας πριν μιλήσουμε για το πως δεχόμαστε input στην GO.

main.go

            
package main

import "fmt"

func main() {
    var score int = 79
    var grade string

    if score >= 90 {
        grade = "A"
        fmt.Println("Way to go!")
    } else if score >= 80 {
        grade = "B"
        fmt.Println("Good job!")
    } else if score >= 70 && score < 80 {
        grade = "C"
    } else if score >= 60 {
        grade = "D"
    } else {
        grade = "F"

        fmt.Println("Try again")
    }

    fmt.Println("Your grade is a ", grade)

}

    
    

Output


Your grade is a  C

Για αρχή, θα πρέπει να αφαιρέσουμε την γραμμή var score int = 79 από τον κώδικα μας, αφού το input θα προέρχεται από τον χρήστη κατά την διάρκεια εκτέλεσης του προγράμματος. Τώρα πρέπει να προσθέσουμε μια fmt.Print( ) function που να δείχνει ένα μήνυμα στον χρήστη ενημερώνοντας τον για το τι θα πρέπει να εισάγει σαν σωστή τιμή στο πρόγραμμα.

fmt.Println(“Enter a grade: ”)

Τώρα πρέπει να γράψουμε εκείνο το κομμάτι κώδικα που θα διαβάζει από το standard input δηλαδή το πληκτρολόγιο μας. Για αυτό το σκοπό θα χρησιμοποιήσουμε την function NewReader( ) από το πακέτο bufio. Μπορείτε να δείτε πληροφορίες σχετικά με αυτό το πακέτο στο documention της golang (https://golang.org/pkg/bufio/#NewReader) . Η γραμμή κώδικα που πρέπει να προσθέσουμε είναι η εξής:

reader := bufio.NewReader(os.Stdin)

Με βάση πάλι το documentation, η function NewReader επιστρέφει ένα αντικείμενο Reader.

Δωρεάν Μαθήματα και Σεμινάρια GO

Σαν παράμετρο μέσα στην function NewReader περνάμε την function Stdin που ανήκει στο πακέτο os.

Δωρεάν Μαθήματα και Σεμινάρια GO

Οπότε ολόκληρη η γραμμή κώδικα που γράψαμε δημιουργεί ένα αντικείμενο reader, που δημιουργήσαμε με την NewReader, και το οποίο θα δέχεται input από το πληκτρολόγιο. Γιατί όμως έπρεπε να δημιουργήσουμε πρώτα αυτό το αντικείμενο reader? Η απάντηση είναι πολύ απλή – αυτό το αντικείμενο έχει πολλές function να μας προσφέρει και μια από αυτές είναι η ReadString που χρειαζόμαστε. Με βάση πάλι το documentation η ReadString επιστρέφει την πληροφορία που έχει τυπώσει ο χρήστης σαν string.

Δωρεάν Μαθήματα και Σεμινάρια GO

Διαβάζοντας το documentation βλέπουμε ότι η ReadString διαβάζει την πληροφορία μέχρι και το delimiter. Για αυτό και πρέπει να βάλουμε στην παρένθεση της το delimiter \n το οποίο σημειώνει και το τέλος του input από τον χρήστη. Θέλουμε να διαβάσουμε ότι έχει γράψει ο χρήστης μέχρι να πατήσει Enter για αυτό και διαλέξαμε τον newline delimiter.

Αφού λοιπόν ο χρήστης μας δώσει το input, εμείς μπορούμε να προχωρήσουμε και να το αναθέσουμε σε μια δική μας μεταβλητή που την ονομάζουμε scorestr η οποία θα είναι είδος string. Αν προσέξουμε λίγο περισσότερο το documentation θα δούμε πως η ReadString επιστρέφει ένα string (το οποίο διάβασε από τον χρήστη) και ένα error. Επειδή δεν επιθυμούμε να διαχειριστούμε το λάθος ( για να κρατήσουμε απλό τον κώδικα μας) και απλά θέλουμε να κάνει σωστά compile το πρόγραμμα μας, γράφουμε το underscore ( _ ). Οπότε η γραμμή αυτή του κώδικα θα είναι:

scorestr, _ = reader.ReadString(‘\n’)

Πριν κάνουμε την μετατροπή από string σε int πρέπει να αφαιρέσουμε τους newline και carriage return delimiters για αυτό και χρησιμοποιούμε την TrimSuffix function από το πακέτο strings. Το αποτέλεσμα το αναθέτουμε πίσω στην scorestr.

scorestr = strings.TrimSuffix(scorestr, “\r\n”)

Το τελευταίο βήμα είναι να χρησιμοποιήσουμε την Atoi( ) function από το πακέτο strconv για να μετατρέψουμε την string τιμή σε int. Το αποτέλεσμα το αναθέτουμε σε μια καινούργια μεταβλητή score. Ολόκληρος ο κώδικας τώρα είναι ο εξής:

main.go

  
package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    fmt.Print("Enter a grade: ")
    reader :=bufio.NewReader(os.Stdin)

    var scorestr string

    scorestr, _ = reader.ReadString('\n')
    scorestr = strings.TrimSuffix(scorestr, "\r\n")
    score, _ := strconv.Atoi(scorestr)

    var grade string

    if score >= 90 {
        grade = "A"
        fmt.Println("Way to go!")
    } else if score >= 80 {
        grade = "B"
        fmt.Println("Good job!")
    } else if score >= 70 && score < 80 {
        grade = "C"
    } else if score >= 60 {
        grade = "D"
    } else {
        grade = "F"

        fmt.Println("Try again")
    }

    fmt.Println("Your grade is a ", grade)

}

  
  

Output


Enter a grade: 99
Way to go!
Your grade is a  A

Αν τώρα ο χρήστης δεν εισάγει την σωστή τιμή και το πρόγραμμα μας σταματάει να τρέχει, μπορούμε να αντικαταστήσουμε το underscore ( _ ) για το λάθος, με την λέξη err και να ελέγξουμε αν είναι nil δηλαδή αν περιέχει κάποιο λάθος. Αν δεν είναι nil, δηλαδή αν περιέχει λάθος, θέλουμε να το δούμε με τη μορφή log και να σταματήσει την εκτέλεση του προγράμματος μας. Αυτή την δυνατότητα μπορούμε να την αποκτήσουμε με την χρήση του function Fatal( ) από το πακέτο log (https://golang.org/pkg/log/#Fatalf ) . Δωρεάν Μαθήματα και Σεμινάρια GO

Ο κώδικας μας τώρα αλλάζει ως εξής:

main.go


package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
    "strconv"
    "strings"
)

func main() {
    fmt.Print("Enter a grade: ")
    reader :=bufio.NewReader(os.Stdin)

    var scorestr string

    scorestr, _ = reader.ReadString('\n')
    scorestr = strings.TrimSuffix(scorestr, "\r\n")
    score, err := strconv.Atoi(scorestr)
    if err != nil {
        log.Fatal(err)
    }

    var grade string

    if score >= 90 {
        grade = "A"
        fmt.Println("Way to go!")
    } else if score >= 80 {
        grade = "B"
        fmt.Println("Good job!")
    } else if score >= 70 && score < 80 {
        grade = "C"
    } else if score >= 60 {
        grade = "D"
    } else {
        grade = "F"

        fmt.Println("Try again")
    }

    fmt.Println("Your grade is a ", grade)

}
    

Output


Enter a grade: abc
2020/05/13 23:22:00 strconv.Atoi: parsing "abc": invalid syntax
exit status 1