В Go возможно отправлять по каналам значения любого типа: int, struct, указатели, интерфейсы и т. д.
Код и пример:
type Data struct { N int } c := make(chan Data) d := Data{N: 1} c <- d // копируется структура целиком p := &Data{N: 3} c2 := make(chan *Data) c2 <- p // по каналу ушёл указатель на тот же самый объект
Если по каналу передать структуру, содержащую поле-указатель — будет ли race condition при изменении этого поля с обеих концов канала?
Ответ:
Пример:
type Box struct { Ptr *int } x := 10 chanBox := make(chan Box) chanBox <- Box{Ptr: &x} // и отправитель, и получатель имеют доступ к x!
История
В распределённой очереди были частые "случайные" падения и загадочные значения в структуре задачи. Оказалось, по каналу гоняли указатели на общие структуры, которые параллельно изменялись в нескольких горутинах. Решили переводом передачи на копии данных.
История
Асинхронная обработка сообщений работала со структурами, внутри которых были срезы-указатели на общий массив. При параллельной передаче каналом части одной и той же памяти изменялись с разных мест, приводя к тайным багам и повреждению данных.
История
В сервисе пуш-уведомлений через канал передавались ссылки на объекты, которые потом обрабатывались горутинами. При одновременном завершении работы и закрытии канала часть структур еще модифицировались, вызывая панику или data race. Помог переход к копированию структуры перед отправкой.