给一个结构体添加“static”函数。

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

Adding "static" functions to a struct

问题

encoding/base64encoding/hex几乎支持相同的一组函数,但是base64使用基于类的编码器,而hex在顶层导出方法。是否有一种简单的方法来创建一个包装器,使得你可以使用抽象的编码接口来处理hex?更一般地说,是否有一种方法可以实现将方法绑定到结构体上的等效操作?(例如,SomeStruct.Encode = hex.Encode

到目前为止,我不得不在一个名为hexEncoder的结构体上定义与hex函数具有相同签名的函数。我创建了这样一个接口:

type Encoding interface {
    Decode(dst, src []byte) (n int, err error)
    DecodedLen(n int) int
    Encode(dst, src []byte) // base64 返回空,hex 返回 int
    EncodedLen(n int) int
}

这个接口与base64.StdEncoding完美配合,但是我不清楚如何包装hex的方法。我创建了一个空的hexEncoder结构体:

// 包装 hex 编码/解码,以便可以与 base64 编码互换使用
type hexEncoder struct {}

func (h hexEncoder) Decode(dst, src []byte) (n int, err error) {
    return hex.Decode(dst, src)
}
func (h hexEncoder) DecodedLen(n int) int {
    return hex.DecodedLen(n)
}
func (h hexEncoder) Encode(dst, src []byte) {
    hex.Encode(dst, src) // 不返回 int,以匹配 Encoding
}
func (h hexEncoder) EncodedLen(n int) int {
    return hex.EncodedLen(n)
}

这个方法可以工作,但是有很多额外的样板代码(实际上只需要包装hex.Encode)。有没有更好的方法来做到这一点?最终的目标是能够在编码/解码时可以互换使用hexbase64,就像下面这样:

func convert(src []byte, decoder Encoding, encoder Encoding) ([]byte, error) {
    temp := make([]byte, decoder.DecodedLen(len(src)))
    n, err := decoder.Decode(temp, src)
    if err != nil {
        return temp, err
    }
    dst := make([]byte, encoder.EncodedLen(len(src)))
    encoder.Encode(dst, temp[:n])
    return dst, nil
}
英文:

encoding/base64 and encoding/hex both support nearly the same set of functions, but base64 uses a class-based encoder, whereas hex exports the methods at the top level. Is there a simple way to create a wrapper around hex so that you can work with an abstracted encoding interface? More generally, is there a way to do the equivalent of binding a method to a struct? (e.g., SomeStruct.Encode = hex.Encode)

So far, I had to define functions on a hexEncoder struct with the same signature as the hex functions. I created an interface like this:

type Encoding interface {
	Decode(dst, src []byte) (n int, err error)
	DecodedLen(n int) int
	Encode(dst, src []byte) // base64 returns nothing, hex returns int
	EncodedLen(n int) int
}

which works perfectly with base64.StdEncoding, but I wasn't clear on how to wrap the hex methods. I created an empty struct for hex:

// wrap hex encoding/decoding so that it can be used interchangeably with base64 encoding
type hexEncoder struct {}

func (h hexEncoder) Decode(dst, src []byte) (n int, err error) {
	return hex.Decode(dst, src)
}
func (h hexEncoder) DecodedLen(n int) int {
	return hex.DecodedLen(n)
}
func (h hexEncoder) Encode(dst, src []byte) {
	hex.Encode(dst, src) // don't return the int to match Encoding
}
func (h hexEncoder) EncodedLen(n int) int {
	return hex.EncodedLen(n)
}

This works, but it's a bunch of extra boiler plate (where all that really needs to be wrapped is hex.Encode). Is there a better way to do this? Ultimately, the goal is to be able to use hex and base64 interchangeably with encoding/decoding, like in something like this:

func convert(src []byte, decoder Encoding, encoder Encoding) ([]byte, error) {
	temp := make([]byte, decoder.DecodedLen(len(src)))
	n, err := decoder.Decode(temp, src)
	if err != nil {
		return temp, err
	}
	dst := make([]byte, encoder.EncodedLen(len(src)))
	encoder.Encode(dst, temp[:n])
	return dst, nil
}

答案1

得分: 2

不,目前没有更好的方法来实现将接口分派到另一个包中的函数,而且说实话,我真的无法想象出更好的方法会是什么样子。

你在包装器中所说的是:

type myType struct{}

func (myType) WhenCalledLikeThis() { DoThat() }

这似乎是最佳的方式。它不需要任何后备内存,允许对命名和返回值进行轻微更改(就像你对Encode所做的那样),并且通过单个调用进行分派。

英文:

No, there is no better way to implement an interface that dispatches to functions in another package, and to be honest I cannot really imagine how a better way would look like.

What you're saying in that wrapper is:

type myType struct{}

func (myType) WhenCalledLikeThis() { DoThat() }

Which seems optimal. It doesn't need any backing memory, allows slight changes in naming and return values (as you've done for Encode), and dispatches with a single call.

huangapple
  • 本文由 发表于 2013年9月3日 08:46:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/18582522.html
匿名

发表评论

匿名网友

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

确定