Я пытаюсь использовать 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()
}
}
}
Мой вопрос: правильно ли обновлять переменную изнутри программы (с точки зрения синхронизации)?Может быть, есть более чистый способ добиться того, что я пытаюсь построить?
Обновление
На самом деле моя проблема не в кэшировании.Это больше о сокрытии «сложности» процесса прослушивания и обновления из Docker SDK.Я хотел предоставить что-то вроде индекса, чтобы легко позволить конечному пользователю зацикливаться и отображать запущенные в данный момент контейнеры.
Я знал о проблемах с гонкой данных в многопоточных программах, но я не осознавал, что на самом деле был в контекстео совпадении здесь (раньше я никогда не писал параллельных программ на Go).
Мне действительно нужно переосмыслить решение, чтобы оно было более идиоматичным.Насколько я могу видеть, у меня есть два варианта: либо защитить переменную с помощью мьютекса, либо переосмыслить схему интеграции каналов.
Что для меня больше всего значит - скрыть или инкапсулировать методиспользуется синхронизация, поэтому пользователям пакета не нужно беспокоиться о том, как защищено общее состояние.
У вас есть какие-либо рекомендации?
Большое спасибо за помощь, Лорик