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.

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

报告相同问题?

悬赏问题

  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥15 键盘指令混乱情况下的启动盘系统重装