Можно ли использовать подмножество элементов большей структуры в качестве параметра функции (отображение на меньшую структуру)? - PullRequest
1 голос
/ 03 апреля 2020

Скажем, у меня есть следующие структуры

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

Моя цель - создать контейнер общих зависимостей и пусть клиенты определяют, какие зависимости они будут sh извлекать из него.

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.Context означает много ненужного приведения и API функции становится беспорядочным
  • Наличие нескольких аргументов функции может быть высоким Поддерживайте значение порядка импорта и повторения, пока вы детализируете свойства вниз по вашему графику зависимостей

Ответы [ 2 ]

0 голосов
/ 11 апреля 2020

То, что вы хотите, очень похоже на шаблон Functional Options . Помните, что функции являются * первоклассными гражданами в Go, поэтому вы можете передавать данные через функции (или функторы - struct s с помощью метода * 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))
}

https://play.golang.org/p/48rCTwn1f9C

Кроме того, многие утверждают, что явное внедрение зависимостей (то есть предоставление всех зависимостей через конструктор вместо того, чтобы скрывать их в коде потребителя) приводит к лучше обслуживаемый код.

0 голосов
/ 03 апреля 2020

Есть ли какой-нибудь способ для меня этого добиться?

Нет. Редизайн.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...