英文:
Adding "static" functions to a struct
问题
encoding/base64
和encoding/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
)。有没有更好的方法来做到这一点?最终的目标是能够在编码/解码时可以互换使用hex
和base64
,就像下面这样:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论