The way I solved OpenGL in a multi-threaded, concurrent environment was to have a "master" goroutine that formally owned the context, and was perpetually locked in a loop over a chan func(). While you can do any calculations or whathaveyou outside the thread/goroutine, to execute instructions on the context itself, you send a func() over a channel to the main context, and the context thread will execute it. A simple/naive implementation is just
runtime.LockOSThread()
whateverImUsing.MakeContextCurrent()
for f := range instructionChan {
f()
}
Though often you need a bit more control than that (my rendering system uses a select statement that is set to render the scene at set intervals between executing functions, for instance), but the gist remains the same.
You do have to be aware that instructions may not be executed immediately, of course, but it works pretty well and the delay in execution is usually fairly negligible (at the very least it's not too much worse than any OTHER non-professional implementation of an asynchronous rendering system).
You may want to handle I/O separately, but with most setups it's not strictly possible (the event callbacks for the input are going to be executed in the context no matter what), but you can keep them conceptually separate if you introduce a one-way dependency. For instance, I have an input handler that tags along with my renderer as a separate subsystem, and reading the code it feels like they're mostly independent of each other, but in reality 90% of the "input handler's" job is feeding new callback registration requests to the renderer's function channel as is necessary. Most of the actual work is executed in the renderer's thread/goroutine even though the code is in the input handler. (And the rendering system is agnostic to the input handler's existence).
I don't know how much of this is immediately applicable to ncurses, or gtk+, or whatever else, but from the gist I got from the thread they seem similar in concept.
I'm sure it may be theoretically possible to do I/O concurrently, but it would probably have to be built ground-up with it in mind, not just a wrapper around an existing library. Rob wrote an article on a concurrent window system here:
http://swtch.com/~rsc/thread/cws.pdf