Как работает ключевое слово defer в Go - PullRequest
0 голосов
/ 01 ноября 2019

При возникновении проблемы, когда пользователю предлагается ввести возраст для цены билета, но оператор if печатает только 9,99, если введенный возраст превышает 13:

Пробный := и fmt.Println(ticketPrice == 19.99).
Если у кого-то есть другое предложение, дайте мне знать.

package main

import "fmt"

func main() {
    var age int
    var ticketprice float64

    defer fmt.Println("Your age is:", getAge(age)) // calls getAge
    defer fmt.Println("Your ticket price is:", printTicket(age,
        ticketprice)) // calls printTicket
}
func printTicket(age int, ticketPrice float64) float64 {
    if age <= 13 {
        ticketPrice = 9.99 // only calls 9.99, not anything else
    } else if age > 13 && age < 65 {
        ticketPrice = 19.99 // not being called?
    } else if age >= 65 {
        ticketPrice = 12.99 // not being called?
    }
    return ticketPrice // returns ticket price
} // Whole function is not being used for some reason. Only returns 9.99, nothing else

func getAge(age int) int {
    fmt.Println("What is your age?")
    fmt.Scan(&age)
    for age < 0 || age > 100 {
        fmt.Println("That cannot be, please enter your age again")
        fmt.Scan(&age)
    }
    return age
}

func getName(name string) string {
    fmt.Println("What is your name?")
    fmt.Scan(&name)
    return name
}

1 Ответ

0 голосов
/ 01 ноября 2019

См. Defer_statements :

Каждый раз, когда выполняется оператор "defer", значение функции и параметры для вызова оцениваются как обычно и сохраняются заново, но фактическая функция не вызывается. Вместо этого отложенные функции вызываются непосредственно перед возвратом окружающей функции в обратном порядке. То есть, если окружающая функция возвращается через явный оператор возврата, отложенные функции выполняются после того, как этот оператор возврата установит какие-либо параметры результата, но до того, как функция вернется к своему вызывающему. Если значение отложенной функции имеет значение nil, выполнение вызывает панику при вызове функции, а не при выполнении оператора defer.

Также см. Пример для ключевого слова go


Чтобы понять порядок оценки, давайте попробуем это:

defer having()(fun("with Go."))

Давайте запустим this и прочитаем комментарии к коду для порядка оценки:

package main

import "fmt"

func main() {
    defer having()(fun("with Go."))
    fmt.Print("some ") // evaluation order: 3
}
func having() func(string) {
    fmt.Print("Go ") // evaluation order: 1
    return funWithGo
}
func fun(msg string) string {
    fmt.Print("have ") // evaluation order: 2
    return msg
}
func funWithGo(msg string) {
    fmt.Println("fun", msg) // evaluation order: 4
}

Вывод:

Go have some fun with Go.

Этот еще красивее, с тем же результатом, просто замените все функции на анонимные функции:

package main

import "fmt"

func main() {
    defer func() func(string) {
        fmt.Print("Go ") // evaluation order: 1
        return func(msg string) {
            fmt.Println("fun", msg) // evaluation order: 4
        }
    }()(func(msg string) string {
        fmt.Print("have ") // evaluation order: 2
        return msg
    }("with Go."))
    fmt.Print("some ") // evaluation order: 3
}

Надеюсь, это поможет вам понять, как работает defer:
A рабочая версия вашего кода с достаточным количеством документации внутри (Примечание: defer параметры оцениваются первыми на местеи вызов fmt.Println будет отложен до возврата функции в обратном порядке):

package main

import "fmt"

func printTicket(age int) float64 {
    fmt.Println("...order is 2...")
    switch {
    case age <= 13:
        return 9.99
    case age > 13 && age < 65:
        return 19.99
    default:
        return 12.99
    }
}

func main() {
    age := 999
    defer fmt.Println("...order is 4...Your age is:", getAge(&age))
    defer fmt.Println("...order is 3...Your ticket price is:", printTicket(age))
}

func getAge(age *int) int {
    fmt.Println("...order is 1...")
    fmt.Print("Enter age=")
    fmt.Scanln(age)
    return *age
}

Выход:

...order is 1...
Enter age=999
...order is 2...
...order is 3...Your ticket price is: 12.99
...order is 4...Your age is: 999
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...