In general, we want to avoiding blocking IO and make it parking. Let us say we make saving to DB nonblocking by a go block.
(defn save-user-info [user]
(go (...)))
Now if I want to use this function, I want to call it in a go block since I do not want blocking.
(defn register-user [user other-info]
(go (validate-user ...)
...
(<! (save-user-info user))))
The function save-user and register-user can be used in many places and then we need another go block.
(defn send-welcome-email [user params]
(go ...
(<! (register-user user))
...))
And again send-welcome-email can be used in other functions (say last-fn) and we then need another go block. So we have created a chain of functions using go since the "origin" one does.
Then if we call last-fn, we have to create several go blocks one-by-one.
My question is: is this the acceptable/correct way to use go? Or my question is wrong.
I am worried because it seems in order to execute one function, we need to create several go (and then channels) and GC them. it is not elegant some how. I do not understand core.async quite in deep but believe go is to make IO non-blocking. On the other side, if we think go as a state machine, then it seems we shall avoid IO in go and make things inside side-effect free.