In Go, it is possible to send values of any type through channels: int, struct, pointers, interfaces, etc.
Code and example:
type Data struct { N int } c := make(chan Data) d := Data{N: 1} c <- d // the entire structure is copied p := &Data{N: 3} c2 := make(chan *Data) c2 <- p // a pointer to the same object was sent through the channel
If a structure is sent through the channel that contains a pointer field — will there be a race condition when modifying this field from both ends of the channel?
Answer:
Example:
type Box struct { Ptr *int } x := 10 chanBox := make(chan Box) chanBox <- Box{Ptr: &x} // both sender and receiver have access to x!
Story
In a distributed queue, there were frequent "random" crashes and mysterious values in the task structure. It turned out that pointers to shared structures were being passed through the channel, which were simultaneously modified in several goroutines. The decision was made to change to passing copies of the data.
Story
Asynchronous message processing worked with structures that contained slices-pointers to a shared array. During parallel passing through the channel, parts of the same memory were modified from different places, leading to hidden bugs and data corruption.
Story
In a push notification service, references to objects were passed through the channel, which were then processed by goroutines. When simultaneous completion and channel closure occurred, some structures were still being modified, causing panic or data race. Switching to copying the structure before sending helped.