【问题标题】:Golang embedding interfaces in struct with private accessGolang 在具有私有访问权限的结构中嵌入接口
【发布时间】:2019-09-04 15:47:58
【问题描述】:

我想以最惯用的方式在 Golang 中复制以下 Java 代码:

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 类只公开方法handleKey。此类的行为通过传递不同的具体 StorageMapper 实现来参数化。

在阅读Effective Go - Embedding 之后,我认为这将是嵌入接口介绍结构的一个很好的用途。但我不知道如何避免将嵌入式接口的方法暴露给Handler 用户。我可以做类似的事情

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)}
}

但是我不能将具体实现传递给Handler(创建结构文字),因为storemapper 未导出。而且我不想为每个可能的组合创建工厂方法......有什么建议吗?

【问题讨论】:

  • public Handler(Storage storage, Mapper mapper) { 在 Go 中将是 NewHandler(storage Storage, mapper Mapper) *Handler {...

标签: oop go design-patterns dependency-injection interface


【解决方案1】:

那些不是嵌入的;嵌入在 Go 中具有特定含义,as outlined in the spec,如您链接到的有效 Go 部分中所述。它指的是未命名的字段,其字段和方法可以从它们的包含类型隐式访问。您的字段是命名的,而不是嵌入的。

也就是说,您的两个结构字段storemapper 不会被导出,因此它们不会暴露给定义Handler 的包之外的任何用户;在这方面你似乎已经有了你想要的行为。

当您说您必须“为每种可能的组合创建工厂方法”时,我不确定您的意思 - 我认为没有任何必要的理由。你只需要一种工厂方法:

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

通过将适当的值传递给函数,可以与StorageMapper 的任何实现组合一起使用。

【讨论】:

    猜你喜欢
    • 2013-10-27
    • 2023-03-23
    • 2014-11-24
    • 1970-01-01
    • 2021-12-15
    • 2016-05-23
    • 2020-05-07
    • 2020-03-01
    相关资源
    最近更新 更多