Go 是否可以使用较大结构项的子集作为函数的参数(映射到较小结构)?

Go 是否可以使用较大结构项的子集作为函数的参数(映射到较小结构)?,go,Go,假设我有以下结构 package foobar type Foo struct{} type Bar struct{} func (*Bar) Read(p []byte) (n int, err error) { return 0, nil } 在我的应用程序中的某个地方,我打算使用这样的结构之一 package consumer type DoOptions struct { bar io.Reader } func Do(opts *DoOptions) {

假设我有以下结构

package foobar

type Foo struct{}

type Bar struct{}

func (*Bar) Read(p []byte) (n int, err error) { 
    return 0, nil 
}
在我的应用程序中的某个地方,我打算使用这样的结构之一

package consumer

type DoOptions struct {
    bar io.Reader
}

func Do(opts *DoOptions) {
    fmt.Println(opts)
}
我的目标是拥有一个通用的依赖容器,并让客户机规定他们希望从中获取哪些依赖

package main

type dependencyContainer struct {
    foo *Foo
    bar *Bar
}

func main() {
    s := &dependencyContainer{
        foo: &foobar.Foo{},
        bar: &foobar.Bar{},
    }
    consumer.Do(s)
}
但这当然不起作用:

cannot use s (variable of type *dependencyContainer) as *DoOptions value in argument to consumer
我有没有办法做到这一点

看看其他的选择,他们都很讨厌

接口中只能有方法 context意味着大量不必要的强制转换,函数的API变得混乱 具有多个函数参数可能是高维护,因为导入顺序很重要,并且在您向下钻取依赖关系图中的属性时会重复 我有没有办法做到这一点


不需要。重新设计。

您想要的与图案非常相似。请记住,函数是Go中的一级公民,因此您可以使用apply方法通过函数或函子-结构传递数据

例如:

package main

import "fmt"

type do struct{}

type DoOption func(*do)

func Do(opts ...DoOption) {
    do := do{}
    for _, opt := range opts {
        opt(&do)
    } // "apply" the options
    // use the values...
}

type Foo struct{ value string }

type Bar struct{ value string }

func WithFoo(x Foo) func(*do) {
    return func(*do) { fmt.Println(x.value) }
}

func WithBar(x Bar) func(*do) {
    return func(*do) { fmt.Println(x.value) }
}

type dependencyContainer struct {
    foo Foo
    bar Bar
}

func main() {
    s := dependencyContainer{Foo{"foo"}, Bar{"bar"}}
    Do(WithFoo(s.foo), WithBar(s.bar))
}

此外,许多人认为,显式依赖项注入(即通过构造函数公开所有依赖项,而不是将它们隐藏在使用者的代码中)会产生更好的可维护代码。

您是否考虑过将依赖项容器传递给Do方法,让每个使用者明确地从容器中选择他们的依赖项?@mkopriva问题是,我希望使用者像库一样不知道它的环境上下文。虽然使用结构作为参数不如参数标准,但它仍然比硬编码orchestrator的依赖关系上下文更抽象。如果需要向使用者隐藏不相关的依赖关系,并且与orchestrator的初始设计非常接近,我唯一能想到的就是使用接口。接口仅为行为而没有数据的限制,即没有字段可以通过getter来克服。例如:虽然我同意您的观点,但目标是通过构造函数显式地注入所有依赖项。使用对象作为参数保留了优点,并确保依赖顺序无关紧要。