dragon_9000 2019-09-04 15:47
浏览 121
已采纳

Golang在私有访问结构中嵌入接口

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?

  • 写回答

1条回答 默认 最新

  • dongmei9961 2019-09-04 15:58
    关注

    Those are not embedded; embedding has a specific meaning in Go, as outlined in the spec, and as explained in the Effective Go section you linked to. It refers to unnamed fields, whose fields and methods are accessible implicitly from their containing type. Your fields are named, not embedded.

    That said, your two struct fields, store and mapper, are not exported, so they will not be exposed to any user outside the package in which Handler is defined; you seem to already have your desired behavior in that regard.

    I'm not sure what you mean when you say you would have to "create factory methods for each possible combination" - I don't see any reason that would be necessary. You need only one factory method:

    func NewHandler(s Storage, m Mapper) Handler {
        return Handler{store: s, mapper: m}
    }
    

    Which could be used with any combination of implementations of Storage and Mapper by passing appropriate values to the function.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 PADS Logic 原理图
  • ¥15 PADS Logic 图标
  • ¥15 电脑和power bi环境都是英文如何将日期层次结构转换成英文
  • ¥20 气象站点数据求取中~
  • ¥15 如何获取APP内弹出的网址链接
  • ¥15 wifi 图标不见了 不知道怎么办 上不了网 变成小地球了