Какой идиоматический способ справиться с нулем и ошибкой в ​​Голанге? - PullRequest
0 голосов
/ 23 сентября 2018

У меня есть две функции go:

func sampleFunction () {
    u, err := findDog(1)
    if err != nil {
        // We couldn't find the dog, print a message.
        fmt.Println(err)
        // Custom error types.
        if _, ok := err.(*dneError); ok {
            fmt.Println("Custom dog dne error for the end-user here.")
        }
    } else {
        // Do something with u.
        u.doSomething() // Is this idiomatic in Go?
                        // Should we explicility check for u != nil?
                        // Or does the if check above need to return?
                        // (even if I would like the function to be longer)

    }
}

// findDog returns a dog with a given ID. If not found, returns an error.
func findDog(id int) (*models.Dog, error) {
    found, err := models.FindDog(id)
    // Is this return scheme/flow too brittle?
    if err != nil {
        return nil, &dneError{fmt.Sprintf("Dog %d does not exist in the" +
            "database: %s", id, err.Error())}
    }
    return found, nil
}

Я просто хочу убедиться, что я правильно обрабатываю ошибки и нули, поэтому мои 2 основных вопроса:

  1. В findDog я правильно возвращаю nil в обоих случаях?

  2. В sampleFunction не имеет смысла явно не проверять u! = Nil, или я просто делаю это совершенно неправильно?

Моя цель - правильно показывать ошибки / проблемы программистам, когда им это нужно, и показывать ошибки / проблемы пользователям, когда они в этом нуждаются, и в то же время придерживаться идиоматических стандартов.Спасибо за ваше время.

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Да, это идиоматический Go.Поскольку ошибки обрабатываются заранее, ошибка означает, что что-то не удалось, и в результате получается либо nil, либо, например, возможно, частично записанный буфер, который не нужен.

PS У меня также есть предложение, которое бысделать вещи более идиоматичными.Идиома звучит примерно так: «Отступать блоки ошибок, а не код».В вашем sampleFunction определенно есть if / else, но в большинстве случаев проверки ошибок (не во всех) вы обрабатываете его и возвращаете, затем пропускаете else и поток просто продолжается.Зачем отступать, когда не нужно?Это позволяет легко читать даже длинные функции, потому что предполагаемый поток функции может быть прочитан сверху вниз и без необходимости отскакивать назад и вперед между блоками if / else.По крайней мере, во многих случаях.

У меня был запрос на внесение изменений в чей-то репозиторий, исправленный, потому что у меня было if / else, где if с return было достаточно.

EDIT Итакмой ответ немного беспокоил меня, и теперь я помню почему.Обычно возвращение не nil error обычно указывает на то, что другие возвращаемые значения бесполезны, но действительно есть исключения. Обязательно ознакомьтесь с отдельной документацией.

В качестве конкретного примера см. bytes.Buffer.ReadBytes

Если ReadBytes обнаружит ошибку перед поискомразделитель, он возвращает данные, прочитанные до ошибки, и саму ошибку (часто io.EOF).

0 голосов
/ 23 сентября 2018

По моему личному мнению, вы справляетесь с этим очень хорошо, просто рекомендация, так как я не знаю, что models.FindDog(id) сделает, я бы дважды проверил found, и если это nil ошибка возврата, суммируя if err != nil || found == nil {

Примечание: при этом return err.Error() может произойти сбой

...