Go:始终返回nil错误以实现接口

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

Go: Returning always nil error to implement interface

问题

我有一个interface

type encoder interface {
	encode() ([]byte, error)
}

一些encoder的实现会返回一个error

type fooEncoder string

func (e fooEncoder) encode() ([]byte, error) {
	if isSomeValidityCheck(e) {
		return []byte(e), nil
	}
	return nil, fmt.Errorf("Invalid type!")
}

但对于其他实现,永远不会有错误:

type boolEncoder bool

func (e boolEncoder) encode() ([]byte, error) {
	if e {
		return []byte{0xff}, nil
	}
	return []byte{0x00}, nil
}

一个方法即使总是返回nil,为了符合interface,是否说它会返回一个错误是符合惯例/正确的?我让boolEncoder.encode返回一个error只是为了符合encoder并且可以作为encoder使用。

英文:

I have an interface:

type encoder interface {
	encode() ([]byte, error)
}

Some implementations of encoder return an error:

type fooEncoder string

func (e fooEncoder) encode() ([]byte, error) {
	if isSomeValidityCheck(e) {
		return []byte(e), nil
	}
	return nil, fmt.Errorf("Invalid type!")
}

But for others, there will never be an error:

type boolEncoder bool

func (e boolEncoder) encode() ([]byte, error) {
	if e {
		return []byte{0xff}, nil
	}
	return []byte{0x00}, nil
}

Is it idiomatic/correct to say a method will return an error, even if it will always be nil, so that it conforms to an interface? I have boolEncoder.encode returning an error only so that it conforms to encoder and can be used as such.

答案1

得分: 1

这是完全可以的/正常的。通常,实现接口比减少方法的代码更重要。

标准库中也有很多例子。

例如,bytes/Buffer.Write() 使用以下方式实现了 io.Writer

func (b *Buffer) Write(p []byte) (n int, err error)

但是,向内存缓冲区写入不会失败,它记录了它永远不会返回非nil错误:

> Write将p的内容附加到缓冲区,根据需要扩展缓冲区。返回值n是p的长度;err始终为nil。如果缓冲区变得太大,Write将使用ErrTooLarge引发panic。

Buffer.Write()可以有一个不返回任何内容的签名,因为它的返回值不包含任何信息(n始终是len(p)err始终是nil),但是这样你就无法将bytes.Buffer用作io.Writer,这更重要。

参考链接:https://stackoverflow.com/questions/40950877/is-unnamed-arguments-a-thing-in-go/40951013#40951013;和https://stackoverflow.com/questions/22549228/why-does-go-allow-compilation-of-unused-function-parameters/33759531#33759531

英文:

This is completely OK / normal. Often it's more important to implement an interface than to reduce the code (of the method).

There are numerous examples in the standard lib too.

For example bytes/Buffer.Write() implements io.Writer with

func (b *Buffer) Write(p []byte) (n int, err error)

But writing to an in-memory buffer cannot fail, it documents that it never will return a non-nil error:

> Write appends the contents of p to the buffer, growing the buffer as needed. The return value n is the length of p; err is always nil. If the buffer becomes too large, Write will panic with ErrTooLarge.

Buffer.Write() could have a signature that doesn't return anything because its return values carry no information (n is always len(p) and err is always nil), but then you couldn't use bytes.Buffer as an io.Writer, which is way more important.

See related: https://stackoverflow.com/questions/40950877/is-unnamed-arguments-a-thing-in-go/40951013#40951013; and https://stackoverflow.com/questions/22549228/why-does-go-allow-compilation-of-unused-function-parameters/33759531#33759531

huangapple
  • 本文由 发表于 2022年3月29日 21:55:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/71663388.html
匿名

发表评论

匿名网友

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

确定