I hope this isn’t a boneheaded question. I have searched in this forum but haven’t seen quite what I am looking for. This post about possible race conditions seems a likely fit.
I’ve been looking at channels on golangdocs.com, sending custom data via channels. I have made one tiny change, adding a Printf statement to the called function. I’ll paste the whole code here so it is easy to see.
package main
import (
"fmt"
)
type Person struct {
Name string
Age int
}
func SendPerson(ch chan Person, p Person) {
ch <- p
fmt.Printf("SendPerson %v\n", p)
}
func main() {
p := Person{"John", 23}
ch := make(chan Person)
go SendPerson(ch, p)
name := (<-ch).Name
fmt.Println(name)
}
If I run this code a few times I usually see just John. Sometimes I see:
SendPerson {John 23}
John
I don’t quite understand why. I thought this was an error on my part as I should have put the Printf statement in the called function before the channel handling part because I wanted to see what I was receiving (that was the purpose of adding the Printf in the first place). But then I thought about it a bit more. Why do I see this sometimes? I would expect to see it always or never, but not sometimes seemingly at random. I am not sure if this is connected to being buffered or unbuffered.
You can change your approach to send message into channel to, because you guarantee that your message are logged, of course if your program running in background, if you only can just run and down, so you can block this wait the message into channel or use a sync.WaitGroup
package main
import (
"fmt"
)
type Person struct {
Name string
Age int
Message chan string
}
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
Message: make(chan string),
}
}
func (s *Person) Send(ch chan *Person) {
s.Message <- "The message was sent"
ch <- s
}
func (s *Person) ReadMessage() {
go func(){
for m := range s.Message {
fmt.Println(m)
}
}()
}
func main() {
p := NewPerson("John", 23)
p. ReadMessage()
ch := make(chan *Person)
go p.Send(ch)
fmt.Println((<-ch).Name)
}
Many thanks for the code. It does seem far more complicated than the original example.
I have been programming on and off with go for a while now, but haven’t really done anything with channels. I was a bit surprised at pretty much my first look at them that I was getting a race condition of some sort, or at least not expected behaviour.
I understand, yes, when you run fmt.Print etc. there is no guarantee that it will be executed because there is no order of execution of the goroutines, and also when your main goroutine finishes the others will also be finished, which can happen if your print never appears