go func() { […] m.content = "initialized\n" }() […]
…but only once a key is pressed several seconds later does it return:
initialized
For this reason, making changes to the model is best done in the normal message flow, either in Update() or via a tea.Cmd.
Not just best practice, but absolutely necessary because the code has a proper race condition. It must absolutely be avoided at all cost. Fortunately, it’s easy to do: never mutate the model outside of the event loop (ie a separate goroutine). Fortunately Go’s race detector is generally excellent at detecting this at runtime as well, so it’s always a wise idea to add -race to your testing/QA process. It surprises me Google built such an awesome and easy-to-use tool yet few seem to use it.
Great post btw. I use a homegrown similar architecture myself. I do wish Go had better dispatch architecture than a switch statement but it’s not the end of the world.
Comments
From section 5:
Not just best practice, but absolutely necessary because the code has a proper race condition. It must absolutely be avoided at all cost. Fortunately, it’s easy to do: never mutate the model outside of the event loop (ie a separate goroutine). Fortunately Go’s race detector is generally excellent at detecting this at runtime as well, so it’s always a wise idea to add -race to your testing/QA process. It surprises me Google built such an awesome and easy-to-use tool yet few seem to use it.
Great post btw. I use a homegrown similar architecture myself. I do wish Go had better dispatch architecture than a switch statement but it’s not the end of the world.
Good point. I'll update this section to more clearly refer to the use of go routines in particular outside of the event loop.