Список обновлений работающих док-контейнеров, указанных в экспортированной переменной 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
,
Какова ваша мотивация?