I'm not as familiar with Java but It's more about concurrency than threads. I have more familiarity with Python, so using that as an example...
There are Tornado and asyncio libraries for Python that give you asynchronous networking. But you have to totally rework how you write Python code within those request handlers to factor out blocking IO which makes using existing libraries for DB and such a pain.
Go is built from the ground up to handle IO like that asynchronously so all of your libraries and stuff will just work in that context.
NodeJS is similar to Go in that regard, but the JS language has baggage that gives you weird blends of callback asynchronicity mixed with async/await and it generally just doesn't feel as nature as Go.
Sometimes a simple request/response model isn't enough. Maybe you need a streamed (chunked encoding) API or WebSockets where the performance for massive numbers of connections using threaded servers is going to tank quickly compared to a language like Go that handles the IO and concurrency better from the ground up.
There are Tornado and asyncio libraries for Python that give you asynchronous networking. But you have to totally rework how you write Python code within those request handlers to factor out blocking IO which makes using existing libraries for DB and such a pain.
Go is built from the ground up to handle IO like that asynchronously so all of your libraries and stuff will just work in that context.
NodeJS is similar to Go in that regard, but the JS language has baggage that gives you weird blends of callback asynchronicity mixed with async/await and it generally just doesn't feel as nature as Go.
Sometimes a simple request/response model isn't enough. Maybe you need a streamed (chunked encoding) API or WebSockets where the performance for massive numbers of connections using threaded servers is going to tank quickly compared to a language like Go that handles the IO and concurrency better from the ground up.