golang 和指针接收器中的自定义错误 [英] Custom errors in golang and pointer receivers

查看:26
本文介绍了golang 和指针接收器中的自定义错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过网络和 stackoverflow 阅读有关值接收器与指针接收器的信息,我理解基本规则是:如果您不打算修改接收器,并且接收器相对较小,则不需要指针.

Reading about value receivers vs pointer receivers across the web and stackoverflow, I understand the basic rule to be: If you don't plan to modify the receiver, and the receiver is relatively small, there is no need for pointers.

然后,阅读有关实现 error 接口的信息(例如 https://blog.golang.org/error-handling-and-go),我看到 Error() 函数的例子都使用指针接收器.

Then, reading about implementing the error interface (eg. https://blog.golang.org/error-handling-and-go), I see that examples of the Error() function all use pointer receiver.

然而,我们没有修改接收器,而且结构非常小.

Yet, we are not modifying the receiver, and the struct is very small.

我觉得没有指针的代码更好(return &appError{} vs return appError{}).

I feel like the code is much nicer without pointers (return &appError{} vs return appError{}).

示例使用指针是否有原因?

Is there a reason why the examples are using pointers?

推荐答案

首先,您链接的博客文章并取自您的示例,appError 不是 >错误.它是一个包装器,携带示例的实现使用的错误值和其他相关信息,它们没有暴露,也没有appError*appError 曾经用作 error 值.

First, the blog post you linked and took your example from, appError is not an error. It's a wrapper that carriers an error value and other related info used by the implementation of the examples, they are not exposed, and not appError nor *appError is ever used as an error value.

所以您引用的示例与您的实际问题无关.但是要回答标题中的问题:

So the example you quoted has nothing to do with your actual question. But to answer the question in title:

一般来说,一致性可能是原因.如果一个类型有很多方法并且有些方法需要指针接收器(例如因为它们修改了值),通常用指针接收器声明所有方法是有用的,所以 方法集 类型和指针类型.

In general, consistency may be the reason. If a type has many methods and some need pointer receiver (e.g. because they modify the value), often it's useful to declare all methods with pointer receiver, so there's no confusion about the method sets of the type and the pointer type.

回答关于 error 实现:当您使用 struct 值来实现 error 值时,使用非指针指向实现error接口.为什么会这样?

Answering regarding error implementations: when you use a struct value to implement an error value, it's dangerous to use a non-pointer to implement the error interface. Why is it so?

因为error 是一个接口.并且接口值是可比.并且通过比较它们包装的值来比较它们.并且根据其中包含的值/类型得到不同的比较结果! 因为如果您在其中存储指针,如果它们存储相同的指针,错误值将相等.如果你在其中存储非指针(结构),如果结构值相等,它们也相等.

Because error is an interface. And interface values are comparable. And they are compared by comparing the values they wrap. And you get different comparison result based what values / types are wrapped inside them! Because if you store pointers in them, the error values will be equal if they store the same pointer. And if you store non-pointers (structs) in them, they are equal if the struct values are equal.

详细说明并举例说明:

标准库有一个 errors 包.您可以使用 errors.New() 函数.如果你看看它的实现 (errors/errors.go),很简单:

The standard library has an errors package. You can create error values from string values using the errors.New() function. If you look at its implementation (errors/errors.go), it's simple:

// Package errors implements functions to manipulate errors.
package errors

// New returns an error that formats as the given text.
func New(text string) error {
    return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}

该实现返回一个指向一个非常简单的结构值的指针.这样,如果您使用相同的 string 值创建 2 个错误值,它们将不相等:

The implementation returns a pointer to a very simple struct value. This is so that if you create 2 error values with the same string value, they won't be equal:

e1 := errors.New("hey")
e2 := errors.New("hey")
fmt.Println(e1, e2, e1 == e2)

输出:

hey hey false

这是故意的.

现在如果你要返回一个非指针:

Now if you would return a non-pointer:

func New(text string) error {
    return errorString{text}
}

type errorString struct {
    s string
}

func (e errorString) Error() string {
    return e.s
}

具有相同 string 的 2 个错误值将相等:

2 error values with the same string would be equal:

e1 = New("hey")
e2 = New("hey")
fmt.Println(e1, e2, e1 == e2)

输出:

hey hey true

尝试 Go Playground 上的示例.

为什么这很重要的一个闪亮的例子:查看存储在变量中的错误值 io.EOF:

A shining example why this is important: Look at the error value stored in the variable io.EOF:

var EOF = errors.New("EOF")

预计 io.Reader 实现会返回这个信号输入结束的特定错误值.因此,您可以和平地比较 Reader.Read() 返回的错误与 io.EOF 以判断是否到达输入结束.您可以确定,如果它们偶尔返回自定义错误,它们永远不会等于 io.EOF,这是 errors.New() 保证的(因为它返回一个指向未导出的结构值的指针).

It is expected that io.Reader implementations return this specific error value to signal end of input. So you can peacefully compare the error returned by Reader.Read() to io.EOF to tell if end of input is reached. You can be sure that if they occasionally return custom errors, they will never be equal to io.EOF, this is what errors.New() guarantees (because it returns a pointer to an unexported struct value).

这篇关于golang 和指针接收器中的自定义错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆