为什么Go的panic()函数接受interface{}而不是…interface{}作为参数?

huangapple go评论91阅读模式
英文:

Why does Go panic() take interface{} instead of ...interface{} as argument?

问题

我注意到panic函数接受interface{}作为参数,而fmt.Print等函数接受...interface{}。如果panic也接受...interface{}作为参数,会不会更方便呢?

为什么Go语言的作者将panic定义为func panic(v interface{}),而不是像fmt那样定义为func panic(v ...interface{})

英文:

I noticed panic takes interface{} as an argument, while fmt.Print and the likes take ...interface{}. Wouldn't it be more convenient if panic took ...interface{} as well?

Why did the Go authors define panic as func panic(v interface{}) rather than func panic(v ...interface{}) (like they did with fmt)?

答案1

得分: 5

panic在最初并不只接受一个参数。你可以追溯到2010年3月30日的实现,提交记录01eaf78中添加了panicrecover(在运行时中仍未实现)。

> 主要的语义变化是强制panic只接受一个参数。

提交记录5bb29fb中修复了规范,并且提交记录00f9f0c说明了在多个参数之前panic的用法:

src/pkg/bufio/bufio.go

b, err := NewWriterSize(wr, defaultBufSize)
if err != nil {
    // 不可能发生- defaultBufSize是有效的大小
    - panic("bufio: NewWriter: ", err.String())
    + panic(err)
}

这是根据2010年3月25日的提案

> 我们不希望鼓励像Java这样的语言中错误和异常混淆的情况。
>
> 相反,该提案对defer的定义进行了轻微更改,并使用了一些运行时函数,以提供一种处理真正异常情况的清晰机制。
>
> 在发生恐慌时,如果延迟函数调用了recoverrecover会返回传递给panic的值并停止恐慌。
在其他任何时间,或者在被延迟调用的函数内部,recover返回nil
在停止恐慌之后,延迟调用可以使用新的参数或相同的参数继续恐慌。
或者,延迟调用可以编辑其外部函数的返回值,例如返回一个错误。

在这些不同的情况下,处理一个传递的值似乎比处理可变数量的参数更容易(特别是在C中实现recover时)。

英文:

panic didn't take just one argument at first.
You can trace back the one argument implementation back to 30th March 2010:
commit 01eaf78 gc: add panic and recover (still unimplemented in runtime)

> main semantic change is to enforce single argument to panic.

The spec is fixed in commit 5bb29fb, and commit 00f9f0c illustrates how panic could took before multiple arguments:

src/pkg/bufio/bufio.go

b, err := NewWriterSize(wr, defaultBufSize)
if err != nil {
    // cannot happen - defaultBufSize is valid size
    - panic("bufio: NewWriter: ", err.String())
    + panic(err)
}

That follows a proposal from March 25th, 2010:

> We don't want to encourage the conflation of errors and exceptions that occur in languages such as Java.
>
> Instead, this proposal uses a slight change to the definition of defer and a couple of runtime functions to provide a clean mechanism for handling truly exceptional conditions.
>
> During panicking, if a deferred function invocation calls recover, recover returns the value passed to panic and stops the panicking.
At any other time, or inside functions called by the deferred call, recover returns nil.
After stopping the panicking, a deferred call can panic with a new argument, or the same one, to continue panicking.
Alternately, the deferred call might edit the return values for its outer function, perhaps returning an error.

In those various scenario, dealing with one value to pass around seems easier than dealing with an variable number of arguments (especially when it comes to implement recover in C).

答案2

得分: 2

因为您传递给panic的值是您想要引发的值,并且可以使用recover进行检索。拥有多个panic值并没有太多意义。

package main

import "fmt"

func main() {
    defer func() {
        if v := recover(); v != nil {
            fmt.Println(v.(int))
        }
    }()
    panic(3)
}

使用recover值的示例:

有关panic和recover的真实示例,请参阅Go标准库中的json包。它使用一组递归函数解码JSON编码的数据。当遇到格式错误的JSON时,解析器调用panic来展开堆栈到顶级函数调用,该函数从panic中恢复并返回适当的错误值(请参阅decode.go中decodeState类型的'error'和'unmarshal'方法)。

来源:http://blog.golang.org/defer-panic-and-recover

英文:

Because the value you pass to panic is a value you want to panic with and can be retrieved using recover. Having multiple panic values doesn't really make sense.

package main

import "fmt"

func main() {
	defer func() {
		if v := recover(); v != nil {
			fmt.Println(v.(int))
		}
	}()
	panic(3)
}

Example on using recover values:

> For a real-world example of panic and recover, see the json package
> from the Go standard library. It decodes JSON-encoded data with a set
> of recursive functions. When malformed JSON is encountered, the parser
> calls panic to unwind the stack to the top-level function call, which
> recovers from the panic and returns an appropriate error value (see
> the 'error' and 'unmarshal' methods of the decodeState type in
> decode.go).

Source: http://blog.golang.org/defer-panic-and-recover

huangapple
  • 本文由 发表于 2015年1月11日 04:39:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/27880988.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定