mercredi 4 septembre 2019

Golang embedding interfaces in struct with private access

I want to replicate the following Java code in Golang in the most idiomatic way possible:

public class Handler {

    private Storage storage;
    private Mapper mapper;

    public Handler(Storage storage, Mapper mapper) {
        this.storage = storage;
        this.mapper = mapper;
    }

    public void handleKey(String k) {
        storage.put(k, mapper.map(k));
    }

}

interface Storage {
    public void put(String k, String v);
    public String get(String k);
}

@FunctionalInterface
interface Mapper {
    public String map(String a);
}

private static class InMemoryStorage implements Storage {
    private Map<String, String> table;

    public InMemoryStorage() {
        table = new HashMap<>();
    }

    public void put(String k, String v) {
        table.put(k, v);
    }

    public String get(String k) {
        return table.get(k);
    }
}

Handler class only exposes the method handleKey. The behaviour of this class is parametrized by passing different concrete Storage and Mapper implementations.

After reading Effective Go - Embedding, I thought this would be a good use of embedding interfaces intro structs. But I can't figure out how to avoid exposing the embedded interfaces' methods to Handler users. I can do something like

type Handler struct {
    store  Storage
    mapper Mapper
}

func (h Handler) Handle(k string) {
    h.store.Put(k, h.mapper.Map(k))
}

type Storage interface {
    Put(k string, v string)
    Get(k string) string
}

type Mapper interface {
    Map(k string) string
}

type inMemoryStorage {
    table map[string]string
}

func NewInMemoryStorage() Storage {
    return &inMemoryStore{table: make(map[string]string)}
}

but then I cannot pass concrete implementations to the Handler (creating struct literal) because store and mapper are unexported. And I do not want to create factory methods for each possible combination... Any suggestions?

Aucun commentaire:

Enregistrer un commentaire