duanji1043 2013-09-03 00:46
浏览 40

向结构添加“静态”功能

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条回答 默认 最新

  • dtv7174 2013-09-09 15:24
    关注

    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.

    评论

报告相同问题?

悬赏问题

  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线