英文:
Go error handling, what's the idiomatic way for making things DRY
问题
考虑以下在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语言中的错误的方式。
但是,我不明白的是,Go语言的开发者是否在每个语句上都检查错误?作为来自其他语言的开发者,我对这个概念有些难以理解。所以问题是:
- 在上述问题中,处理错误的惯用方式是什么?
- 如果我不检查错误,是否被认为是一种不好的做法?如果是的话,我应该在每次调用
push()
时检查输出吗?
基本上,我想知道一个有经验的Go语言开发者在上述程序中如何处理错误。
Play链接:https://play.golang.org/p/_AnZLvY-28
[更新]
添加了一个从数据库获取数据并输出为JSON的真实世界程序。http://play.golang.org/p/dDApCYprjU
英文:
Consider the following example program which is primitive stack implementation in 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)
}
Now, I read Error handling and Go & it seems the above way of returning multiple values is the way to handle errors in go.
But what I don't understand is that does do gophers check of errors on every statement? Coming from other languages this concept it bit hard for me to grok. So the question is
- What is the idiomatic way of handling errors in above problem?
- Is considered a bad practice if I don't check for errors? if yes, then I am supposed to check the output of
push()
everytime I call it?
Basically what I want to know if how would a experienced gopher do error handling in the above program?
Play URL: https://play.golang.org/p/_AnZLvY-28
[Update]
Added a real-world program where I fetch data from database & output to json. http://play.golang.org/p/dDApCYprjU
答案1
得分: 4
是的,产生错误的惯用方法是返回多个值。处理错误的惯用方法是这样的:
val, err := myFunc()
if err != nil {
// 处理 err
}
// 处理 val
总的来说,这是一个判断的问题,但通常最好处理错误。你编写的代码也有点不寻常,通常不会连续调用10次同一个函数,所以你需要做冗长的错误处理是由于原始代码造成的。例如,你可以使用循环:
for _, num := range []int{2, 24, 56, 87, 97, 47, 37, 31, 69} {
_, err := push(num)
if err != nil {
panic(err)
}
}
除了不处理 push 错误之外,你还有一些其他更严重的问题。一个小问题是 push
没有必要总是返回 0,为什么不只返回一个错误,而不是一个 int 和一个错误?更大的问题是 pop
不断减少 top
,而 getTop
只是访问 a[top]
,所以如果 top
由于 pop
太多而变为负数,很容易导致运行时 panic。你可能希望在 pop
和 getTop
函数中添加一些错误处理或其他保护措施。
英文:
Yes, the idiomatic way to produce errors is to return multiple values. The idiomatic way to handle errors is this:
val, err := myFunc()
if err != nil {
// do something with err
}
// do something with val
At the end of the day it's a judgement call, but it's almost always good practice to handle errors. The code you're writing is also a bit unusual, you normally don't have 10 calls to the same function back-to-back, so the verbose error handling you'd have to do is more a result of the original code. For instance, you could use a loop:
for _, num := range []int{2, 24, 56, 87, 97, 47, 37, 31, 69} {
_, err := push(num)
if err != nil {
panic(err)
}
}
You have some other things that are more problematic than not handling the push errors though. One minor thing is there is no reason for push
to always return 0, why not only have it return an error, instead of an int and an error? The bigger problem is that pop
keeps decrementing top
, and getTop
just accesses a[top]
, so you can easily get a runtime panic if top
becomes negative from having pop
ped too much. You probably want some error handling or other safeguards in your pop
and getTop
functions.
答案2
得分: 0
这是处理Go语言中错误的标准方式。在错误发生后,有两个选项可以选择。
-
记录错误并完全退出程序。
-
记录错误并执行一些相关任务。
选项一的示例:
func funcX() {
rtnval, err := funcY()
if err != nil {
fmt.Println("错误:", err)
os.Exit(1)
}
// rtnval
}
英文:
This is a standard way of handling the errors in go-lang. There are two options that can follow after an error took place.
1.log the error and entirely quit the program
- log the error and do some relevant task
Option one example :
func funcX() {
rtnval, err := funcY()
if err != nil {
fmt.Println("error: ", err)
os.Exit(1)
}
//rtnval
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论