Список обновлений работающих док-контейнеров, указанных в экспортированной переменной golang

Я пытаюсь использовать Golang SDK Docker, чтобы поддерживать переменную слайса с работающими в данный момент контейнерами на локальном экземпляре Docker. Этот фрагмент экспортируется из пакета, и я хочу использовать его для подачи веб-страницы.

Я на самом деле не привык к горутинам и каналам, и поэтому мне интересно, нашел ли я хорошее решение для моей проблемы.

у меня есть docker Пакет следующим образом.

https://play.golang.org/p/eMmqkMezXZn

Оно имеет Running переменная, содержащая текущее состояние запущенных контейнеров.

var Running []types.Container

Я использую reload функция для загрузки работающих контейнеров в Running переменная.

// Reload the list of running containers
func reload() error {
    ...
    Running, err = cli.ContainerList(context.Background(), types.ContainerListOptions{
        All: false,
    })
    ...
}

И тогда я начинаю горутин из init функция для прослушивания событий Docker и запуска reload функционировать соответственно.

func init() {
    ...
    // Listen for docker events
    go listen()
    ...
}

// Listen for docker events
func listen() {
    filter := filters.NewArgs()
    filter.Add("type", "container")
    filter.Add("event", "start")
    filter.Add("event", "die")

    msg, errChan := cli.Events(context.Background(), types.EventsOptions{
        Filters: filter,
    })

    for {
        select {
        case err := <-errChan:
            panic(err)
        case <-msg:
            fmt.Println("reloading")
            reload()
        }
    }
}

У меня вопрос, уместно ли обновлять переменную внутри goroutine (с точки зрения синхронизации)? Может быть, есть более чистый способ добиться того, что я пытаюсь построить?

Обновить

Мое беспокойство здесь не связано с кэшированием. Это больше о сокрытии "сложности" процесса прослушивания и обновления из Docker SDK. Я хотел предоставить что-то вроде индекса, чтобы легко позволить конечному пользователю зацикливаться и отображать запущенные в данный момент контейнеры.

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

Мне нужно переосмыслить решение, чтобы оно было более идиоматичным. Насколько я вижу, у меня есть два варианта: либо защитить переменную с помощью мьютекса, либо переосмыслить дизайн для интеграции каналов.

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

Есть ли у вас какие-либо рекомендации?

Большое спасибо за вашу помощь, Лорик

1 ответ

Нет, это не идиоматизм. Running переменная между двумя программами. Вы делаете это, разделяя это между рутиной, которая управляет вашим main функция и listen функция, которая начинается с go- который порождает другой горутин.

Почему, потому что это порывает с

Не общайтесь, разделяя память; вместо этого делитесь памятью, общаясь. ¹

Таким образом, дизайн API должен измениться, чтобы быть идиоматическим; вам нужно удалить Running переменная и заменить ее чем? Это зависит от того, чего вы пытаетесь достичь. Если вы пытаетесь кэшировать cli.ContainerList потому что вам нужно часто вызывать его, и это может быть дорого, вы должны реализовать кеш, который становится недействительным на каждом cli.Events,

Какова ваша мотивация?

Другие вопросы по тегам