On Mon, 10 Nov 2014 05:28:12 -0800 (PST)
Mikhail Vitsen <
mikhai...@gmail.com> wrote:
> > > >>
http://play.golang.org/p/h0zoMJVybU
> > > >>
> > > >> If i remove "go" in 9th line (go server.ListenAndServe()) -
> > > >> everything works fine, but main thread blocks.
> > > >> If i doesn't remove "go" - i can't receive response from
> > > >> server at all.
> > > >>
> > > >> What is the problem?
> > > >>
> > > > When main() exits, your program will exit. If you start some
> > > > work in another goroutine, you have to arrange that main is
> > > > blocked until that work is complete.
> >
> > > Of course, i know it. main() has infinite loop. After starting
> > > goroutine for http server, main() starts anouther goroutine for
> > > tcp socket and then processes messages from both goroutines.
> >
> > The main() in the sample code you've posted does not has an
> > infinite loop: it agganges for HTTP serving to start and then
> > quits.
> >
> > Wrong playground link?
> >
> As soon as it is impossible to run server code in playground - this
> link is only an example (i thought it is good way to show go code on
> playground) and represents only the idea of a problem.
> i've fixed it
http://play.golang.org/p/boBae29AB9
OK, a couple of things.
First, you can't sensibly use a busy loop in a production code
(actually, in any code). It should basically lock an OS thread on
which the goroutine executing it happened to be scheduled.
What you should use instead is one of agreed upon methods of
synchronization between goroutines: channels or wait groups.
Your main() most probably should just wait on some synchronization
resource while all the other work is to be done on other goroutines.
As to how exactly approach the problem depends on how gracefully you
want to tear down the services provided by your process (that HTTP
server and TCP server etc). The simplest way is to just set up a
handler for TERM (and INT) signals which would simply call os.Exit(0).
That would bring the whole thing down brutally killing all the
goroutines without any chance for then for cleaning up. A more
involved approach would be to broadcast a "shutdown signal" to all the
"servicing" goroutines expecting them to tear their own subordinate
goroutines down than send an acknowledgement signal back; after
collecting all the ACK signals, the controlling goroutine might safely
exit. You might hand-roll this mechanism or use something already made
like [1]. In either case, you won't probably be able to use
http.ListenAndServe() directly in such "graceful" way because there's
no way for it to be controlled from the outside. Instead, you'd need
to first create a listener and then write a custom code that would
`select` both on a listener and a synchronization channel delivering
those "shutdown signals" discussed, and after accepting another
connection spawn a goroutine serving the request (i.e. do what
http.ListenAndServe() does, and more).
1.
http://blog.labix.org/2011/10/09/death-of-goroutines-under-control