En Go es posible enviar valores de cualquier tipo a través de canales: int, struct, punteros, interfaces, etc.
Código y ejemplo:
type Data struct { N int } c := make(chan Data) d := Data{N: 1} c <- d // se copia toda la estructura p := &Data{N: 3} c2 := make(chan *Data) c2 <- p // se envió un puntero al mismo objeto a través del canal
Si se pasa una estructura a través del canal que contiene un campo-puntero, ¿habrá condición de carrera al modificar este campo desde ambos extremos del canal?
Respuesta:
Ejemplo:
type Box struct { Ptr *int } x := 10 chanBox := make(chan Box) chanBox <- Box{Ptr: &x} // tanto el emisor como el receptor tienen acceso a x!
Historia
En la cola distribuida hubo frecuentes caídas "aleatorias" y valores misteriosos en la estructura de la tarea. Resultó que se estaban pasando punteros a estructuras comunes a través del canal, que se modificaban simultáneamente en varias gorutinas. Se decidió cambiar a pasar copias de los datos.
Historia
El procesamiento asíncrono de mensajes trabajaba con estructuras que contenían slices-punteros a un array común. Durante la transmisión paralela a través del canal, partes de la misma memoria eran modificadas desde diferentes lugares, causando errores ocultos y corrupción de datos.
Historia
En el servicio de notificaciones push, se pasaban referencias a objetos a través del canal, que luego eran procesadas por gorutinas. Al finalizar el trabajo y cerrar el canal simultáneamente, algunas estructuras aún se modificaban, provocando pánico o data race. La solución fue cambiar a la copia de la estructura antes del envío.