Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding "static" functions to a struct

Tags:

go

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
}
like image 967
Jeff Tratner Avatar asked Sep 03 '13 00:09

Jeff Tratner


People also ask

Can a struct have static methods?

A struct can have its own static and instance methods (or functions) but are not created within the struct itself. These methods exist in a separate block using impl and they can be either static or instance methods.

Can a struct have static members?

C++ 2. Static Members: C structures cannot have static members but are allowed in C++.

Can you have static in struct C++?

There is no such thing as a "static struct" in C++, static is a storage-class-specifier and applies to variables or functions, not types. You should not revert back to using a struct with named members instead an array of unnamed elements.. it should be the other way around..

Can structs have static variables?

Static variable isn't allowed in struct because C requires the whole stucture elements to be placed "together". To withdraw a element value from a structure is counted by the offset of the element from the beginning address of the structure. Note: You can have a static member in C++ structure.


1 Answers

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.

like image 123
Gustavo Niemeyer Avatar answered Nov 15 '22 05:11

Gustavo Niemeyer