去错误处理,什么是使事情干燥的惯用方法

时间:2015-11-08 14:34:15

标签: go

考虑以下示例程序,它是Go:

中的原始堆栈实现
package main

import "fmt"
import "errors"

const MAX_SIZE = 10

var a [10]int
var top int = -1

func main() {
    printStack()
    push(1)
    printStack()
    push(23)
    printStack()
    pop()
    push(2)
    push(24)
    push(56)
    push(87)
    push(97)
    push(47)
    push(37)
    push(31)
    push(69)
    printStack()
    push(75)
    println("Top element is", getTop())
}

func push(x int) (int, error) {
    if top >= (MAX_SIZE - 1) {
        return 0, errors.New("Error: Prevented Stackoverflow. Stack full")
    }
    top += 1
    a[top] = x
    return 0, nil
}

func pop() {
    top -= 1
}

func getTop() int {
    return a[top]
}

func printStack() {
    fmt.Println(top+1, "Stack: ", a, "Top", top)
}

现在,我读了Error handling and Go&似乎上面返回多个值的方法是在go中处理错误的方法。

但我不明白的是,是否确实会对每个声明中的错误进行检查?来自其他语言的这个概念对我来说很难理解。所以问题是

  1. 在上述问题中处理错误的惯用方法是什么?
  2. 如果我不检查错误,被认为是不好的做法?如果是的话,我应该在每次调用时检查push()的输出吗?
  3. 基本上我想知道一个经验丰富的gopher如何在上述程序中进行错误处理?

    播放网址:https://play.golang.org/p/_AnZLvY-28

    [更新] 添加了一个真实的程序,我从数据库和数据库中获取数据。输出到json。 http://play.golang.org/p/dDApCYprjU

2 个答案:

答案 0 :(得分:4)

是的,产生错误的惯用方法是返回多个值。处理错误的惯用方法是:

val, err := myFunc()
if err != nil {
    // do something with err
}

// do something with val

在一天结束时,这是一个判断调用,但处理错误几乎总是好的做法。您正在编写的代码也有点不寻常,您通常没有10次对同一函数的背靠背调用,因此您需要执行的详细错误处理更多是原始代码的结果。例如,您可以使用循环:

for _, num := range []int{2, 24, 56, 87, 97, 47, 37, 31, 69} {
    _, err := push(num)
    if err != nil {
        panic(err)
    }
}

你还有一些其他问题比不处理推送错误更有问题。一个小问题是push没有理由总是返回0,为什么不让它返回错误,而不是int和错误?更大的问题是pop不断递减top,而getTop只是访问a[top],因此如果top变为负数,您可以轻松获得运行时恐慌pop太多了。您可能希望在popgetTop函数中进行一些错误处理或其他安全措施。

答案 1 :(得分:0)

这是在 go-lang 中处理错误的标准方法。发生错误后有两种选择。

1.记录错误并完全退出程序

  1. 记录错误并执行一些相关任务

选项一示例:

func funcX() {
    rtnval, err := funcY()
    if err != nil {
        fmt.Println("error: ", err)
        os.Exit(1)
    }
    //rtnval 
}