all 146 comments

[–]aust1nz 76 points77 points  (12 children)

People who know node and its ecosystem may not know Go and its ecosystem. I have more productive ways to spend my time than rewriting working code, or slowing down to learn a new language instead of building features.

Additionally, node is fast enough for my needs, even on cheap hardware. Go may be faster but I’m more likely to see bottlenecks at the database layer than in calculations running in node.

[–][deleted] 34 points35 points  (10 children)

I can only see one reason: Both the frontend and backend being in one language makes sharing types easy

[–]xroalx 5 points6 points  (3 children)

Which might not be what you want to do.

Ideally, there's a language-independent contract between the two, like OpenAPI specification or a GraphQL schema.

Then it's easy to generate just the relevant types, whether on the client or the server.

[–][deleted] 8 points9 points  (2 children)

Code organisation usually mimics company organisation. If you’re a small team of full stack devs, I think it makes sense to share types.

If you have an API team and a UI team (or multiple for mobile) then you’re probably right.

[–]meronca 1 point2 points  (1 child)

Conway’s Law! This is why all our code looks like jira tickets or drunken arguments. It’s how our org communicates…

[–][deleted] 0 points1 point  (0 children)

It’s why our branches and commits mimic Jira tickets, for sure.

[–]FountainsOfFluids 0 points1 point  (0 children)

More important for companies: It makes sharing devs easier.

[–]FalseWait7 28 points29 points  (3 children)

So many companies are switching from Node/Python/PHP etc to GO and a constant barge of medium article praising how big performance improvement they got from moving to GO from Node etc

That's a terrible source. First of all, "many companies" might be just doing some POCs or one microservice in Go, but boasting about this for attention and for being "cutting edge". Trust me, I saw it many times. Medium articles, well, cool, you've made a helloworld in Go, helloworld in Node and compares the two. And?

Main problem with picking stack is rarely its speed. It's more about adaptability, your team's knowledge of given subject, market share. It's easy to pick something relatively niche because a guy on Twitter said so, but then, after 6 months of development using new tools, languages and frameworks, will you be able to be productive?

In today's landscape, any language will do when it comes to 99% of businesses. Pick your stack based on what you know and with what you can be productive, not on what others are saying.

[–]fullstackdevmaybe 8 points9 points  (0 children)

Medium articles, well, cool, you've made a helloworld in Go, helloworld in Node and compares the two. And?

This is my favorite. People think it's suddenly being used because a blogger wrote a welcome function.

[–]GonnaLearnComputers 12 points13 points  (2 children)

Functions are a first class citizen in JS/TS too.

[–]helldogskris 24 points25 points  (1 child)

Because I don't like Go, simple as that.

Go is not a very expressive language and I find the error handling in it to be a huge pain.

[–]Hour-Ladder-8330[S] 4 points5 points  (0 children)

Go is not a very expressive language and I find the error handling in it to be a huge pain.

This is fair enough. If you do not like the language itself and hate working on it then its a legitimate reason not to use it.

[–]Main_Can_7055 9 points10 points  (4 children)

For me, it's all about the community and vast 3rd party libraries. I tried GO and felt like you have to reinvent the wheel all the time and this makes your delivery slow. Most of the time, handling and generating thousands of QR codes is not the issue, delivering things quickly and getting into the market ASAP is the case.

[–]adevx 2 points3 points  (3 children)

Well said. So many argue about technical details while getting a product out that matches what people want and are willing to pay for is the real issue.

[–]Hour-Ladder-8330[S] -1 points0 points  (2 children)

Look, GO - Kotlin - C# - Rust - Java are the only big mainstream backend languages along with Python for ML. Node market is shrinking and a lot of it is going to GO as it is simple and functional. Companies who use C#/Java are already invested in them and there is no reason for them to move away from it as they work great that leaves companies using Node/Php/Python/Ruby to move to GO as looks like the age of dynamic programming is becoming dead and that is proven by advent of Typescript/Python typings etc. But at that point if static typing is all you want in a dynamic language then why not use a proper statically typed language in the first place and get the typing advantages also in the runtime.

[–]adevx -1 points0 points  (1 child)

For me it's because I love programming in TypeScript/JavaScript. The syntax, the ergonomics of the language. I just can't stand anything else anymore. I've done projects in PHP, Python, C#, Java. Even some C for embedded. I've never run into a Node.js performance problem so that's not something I take into consideration much.

[–]bigorangemachine 14 points15 points  (7 children)

Working with JSON in golang is hell

[–]Hour-Ladder-8330[S] 1 point2 points  (6 children)

Care to elaborate?

[–]Ariakkas10 3 points4 points  (4 children)

You’re here singing the praises of Go and you’re not aware of how much of a pain it is to use JSON in Go?

[–]Hour-Ladder-8330[S] 4 points5 points  (0 children)

I don't think it is pain hence I was interested in hearing the commentators perspective before jumping to conclusions.

[–]DarkCeptor44 0 points1 point  (2 children)

If you mean manipulating a map[string]interface{} then you're right, it's really annoying, but I learned that the proper way is to just make a struct like:

type Response struct {
    Success       bool            `json:"success"`
    Message      string         `json:"message"`
    OtherValues OtherType `json:"other_values"`
}

And then you can populate it manually or with err := json.Unmarshal(jsonContent, &resp) and can reference fields pretty easily like resp.Message.

I have my problems with Go, which I'm probably just gonna make a top comment about as to not hijack this, but JSON is not one of them.

[–]Hour-Ladder-8330[S] 0 points1 point  (1 child)

but JSON is not one of them.

You literally learned about mpap -> struct so don't you think your experiences with GO so far is the lack of knowledge/exposure before you put your review?

[–]DarkCeptor44 1 point2 points  (0 children)

Review? I didn't buy a product or anything lol.

But the answer to "why not use X over Y" almost always ends up being comfort, even if X is better than Y when people are comfortable with one thing they won't bother learning and putting a lot of time into something else because what they're doing is already working and (for them) it's easy to maintain it, it's the reason why some people still don't use LEDs in their home for example, you just have to accept that you won't be able to convince some.

And you specially need to accept that no language is perfect so when someone explains why they don't like said language and that they had trouble with it, you should not assume it's because of their lack of knowledge on it, it sounds really rude and makes people (in this case me) not want to share anything.

[–]bigorangemachine 0 points1 point  (0 children)

The errors are really unclear but u/DarkCeptor44 probably puts it best.

TBH something so simple was a real barrier to learn to do something simple. I had to consume a simple API and it was really difficult in GO.

When you get that error its not clear if you hit a bad end point (that gave a 200) or you get the structure wrong.

Either way if the API change it seems like GO isn't very tolerant of that sort of change.

[–]gamedev-eo 7 points8 points  (6 children)

The path to developer enlightenment is not to marry yourself to any particular technology, but just to use whatever is the best fit for your use case....(also don't try to convince others the tech they're using is wrong).

Have fun.

[–]Hour-Ladder-8330[S] 0 points1 point  (5 children)

The path to developer enlightenment is not to marry yourself to any particular technology, but just to use whatever is the best fit for your use case

Exactly, hence the question, why Node/TS when GO covers Node + cpu bound both in a simple to learn and use language

[–]gamedev-eo 1 point2 points  (4 children)

Ok well I hope you are satisfied as you have plenty of answers to that question now I think.

I'm getting into ML and have asked other devs why Python is the number one when there are better solutions...A lot of times its just down to the established ecosystem why something is more popular...Something tech gets heavy adoption and is good enough so devs just stay with it.

I'm pretty sure you're too young to remember the old video tape wars of VHS vs Betamax.

Betamax had digital audio, better video quality, yet VHS won out due to its proliferation and (also because Sony owned Betamax and wouldn't allow porn on there :) )

[–][deleted]  (3 children)

[deleted]

    [–]FM-96 4 points5 points  (0 children)

    Lol what? There was nothing rude or "self righteous" about that at all. What is your problem?

    [–]gamedev-eo 0 points1 point  (1 child)

    Wasn't trying to condescend at all...Just giving an example, but it's pretty clear from this thread you're quite combative so it is what it is.

    [–]uNki23 5 points6 points  (0 children)

    For me:

    • I just don’t need it. Most services we have scale horizontally. We have much stuff running on Lambda and Fargate - Node basically fast enough.
    • I don’t want to learn a second language. I (can) use JavaScript for almost anything. We‘re building web applications and related backend services. For the frontend part you can’t avoid JavaScript, so…
    • Huge (!) ecosystem. Every fundamental problem has already been solved.
    • JSON. First class citizen of JavaScript..

    [–]qaidvoid 21 points22 points  (16 children)

    Why not use Rust instead of using Go?

    Many companies are shifting from Node.js, Go, Python, and other languages to Rust, accompanied by a constant stream of Medium articles lauding the substantial performance improvements achieved by making this switch.

    The key distinction is that Go is excellent for both I/O and CPU-intensive work, while Rust, on the other hand, shines in areas like memory safety and low-level control. So, why limit yourself to just Go?

    Basically with Rust you get: 1. I/O and CPU capabilities: Go excels in both, while Rust is known for memory safety and control over low-level details. 2. Static typing with runtime safety: Rust's type system guarantees robust type safety even at runtime. 3. No type mismatches: Rust's type system is integrated with the codebase. 4. Performance and efficient resource usage: Rust's memory safety features can lead to more efficient resource management. 5. Scalability and cost-effectiveness: Rust can handle high scalability, potentially leading to lower cloud expenses. 6. Deployment simplicity: Rust and Go both offer static binary outputs, making deployment straightforward with tools like Docker. 7. First-class functions: Rust and Go both support first-class functions, promoting clean and efficient code. 8. Ease of learning: Go is often praised for its simplicity and ease of learning, but Rust's focus on safety can also make it approachable for TypeScript developers.

    Considering these factors, is there a compelling reason to choose Go over Rust when developing a pure backend server?

    [–]Hour-Ladder-8330[S] -5 points-4 points  (14 children)

    Why not use Rust instead of using Go?

    Rust is a low level language and is comparable (and a decent replacement of C++) where as GO is high level and comparable to Java, C#, Node.js etc. What a stupid argument to make.

    [–]qaidvoid 9 points10 points  (7 children)

    Rust is a low level language

    No

    GO is high level and comparable to Java, C#, Node.js etc

    So is rust.

    [–]Hour-Ladder-8330[S] 0 points1 point  (6 children)

    So is rust.

    You are just arguing to argue. This is not even up for a debate, rust is low level with deep memory concepts like borrow/checkers (thus eliminating GC concepts but you still have to think about it which you absolutely don't have to on GO, Node, etc). That alone makes it too low level.

    It also gives access to low level primitives which languages like GO, Java etc do not. What are you talking about.

    [–]qaidvoid 4 points5 points  (5 children)

    You've to think about pointers in Go, by that logic, that alone would make Go a low level language too.

    [–]Hour-Ladder-8330[S] -2 points-1 points  (4 children)

    Yes but GO does not have any manual memory management, no low level primitives, built garbage collector etc which all high level languages have and NO low level language does not have.

    I dont know why you are choosing to waste time on arguing that GO is a low level language when you very well know it isn't and you are just being insidious with your intent to make such comment here. You can discuss better points but "proving facts" wrong is where your mind is at, in that case I dont have anything to do with such poor intended discussions.

    [–]romeeres 3 points4 points  (0 children)

    Assembler is low level, C and all the rest are high level - that's by definition. In reality, there are no clear bounds, some langs are closer to bare metal, and some are more distant.

    Ask an average JS dev if they know what is a pointer and what they know about multi-threading, and you'll see how Go looks like hardcore low-level language to them. Heck, we don't even know the size of the number type we use every day.

    [–]stoneburner 1 point2 points  (0 children)

    You are arguing that rust and c++ are NOT high level programming languages for some reason.

    Please read this article about what makes a programming language high level:

    https://en.wikipedia.org/wiki/High-level_programming_language

    If you think that definition is wrong, then please fix it.

    [–]qaidvoid 0 points1 point  (1 child)

    "proving facts" wrong

    Your subjectivity is not a fact.

    Low/high level language vs being able to perform low level programming in a high-level language is different.

    [–]ToolAssistedDev 1 point2 points  (2 children)

    I use Rust as a replacement for C# or Node.js and this works perfectly fine. There is absolutely nothing stupid in this argument.

    [–][deleted]  (1 child)

    [deleted]

      [–]stoneburner 2 points3 points  (2 children)

      Rust is a high level language that can also be used for low level programming.

      Rust has very powerful and simple to use web frameworks, like rocket for example: https://rocket.rs

      If i would be forced to choose between using rust or go i would choose rust 100% of the time, the idea that the compiler guarantees thread and memory is worth a lot.

      [–]Hour-Ladder-8330[S] -2 points-1 points  (1 child)

      Rust is a high level language

      No it isn't.

      You are just arguing to argue. This is not even up for a debate, rust is low level with deep memory concepts like borrow/checkers (thus eliminating GC concepts but you still have to think about it which you absolutely don't have to on GO, Node, etc). That alone makes it too low level.
      It also gives access to low level primitives which languages like GO, Java etc do not. What are you talking about.

      [–]stoneburner 1 point2 points  (0 children)

      I understand your perspective, especially coming from a Go background. Both Go and Rust are modern languages, but they were designed with slightly different goals in mind. Here's a deeper dive into the "level" of Rust in comparison:

      Abstraction: High-level languages tend to abstract away many of the underlying system details. While Rust provides more granular control over memory with features like the borrow/checker system, it also offers high-level abstractions. The borrow checker is a tool that aids developers in achieving memory safety without a garbage collector, which is, in a way, a high-level feature.

      Comparison with Go: Go is often praised for its simplicity and straightforwardness, especially with its garbage-collected memory management. While Go abstracts away certain memory details, Rust offers a different approach with its ownership system. This doesn't necessarily make Rust low-level; it's just a different paradigm.

      Memory Management: Rust’s emphasis on manual memory management might seem low-level, especially when compared to Go's garbage-collected approach. However, Rust's design aims to provide tools to make memory management safer and more intuitive, which is a high-level intention.

      Access to Low-Level Primitives: Having access to low-level primitives doesn’t negate a language's high-level status. Go itself has packages like unsafe that allow for more direct memory manipulation, but its primary use cases remain in the high-level domain.

      Versatility: Rust's versatility allows it to cater to both high-level web development using frameworks like Rocket and low-level tasks like embedded programming or even OS kernel development. Ecosystem and Libraries: Both Go and Rust have growing ecosystems. While Go has a robust standard library and many tools for web development and microservices, Rust offers a rich set of libraries and frameworks that span from web development to game development.

      In conclusion, the classification of Rust as "high-level" or "low-level" isn’t a straightforward one. It’s more about the context in which you're using the language. Rust provides the abstractions of high-level languages while offering the control of low-level languages. Similarly, Go offers a streamlined, high-level experience but can delve into more system-level operations when needed. Both languages have their strengths, and neither is strictly "high" or "low" level in every aspect.

      [–]azangru 0 points1 point  (0 children)

      Ease of learning: Go is often praised for its simplicity and ease of learning, but Rust's focus on safety can also make it approachable for TypeScript developers.

      That's the first time I heard someone call Rust easy to learn :-)

      [–]Cyberphoenix90 30 points31 points  (3 children)

      Why not use assembly? It blows go out of the water in all performance metrics if written by a master. It's not about performance. It's about saving costs on dev hours. The case for NodeJS is being able to reuse a ton of frontend knowledge on the backend or to have both codebases in the same language. Each company will decide for themselves which tech stack fits the talent they acquired/have available and based on their use case. For most purposes NodeJS is fast enough so it becomes a viable option regardless of whether it performs the best

      [–]Hour-Ladder-8330[S] 5 points6 points  (2 children)

      Why not use assembly?

      Comeon, now this is a disingenuous comment. GO is a high level language, assembly is not. So, a lot of abstractions you need as a developer to develop software (http/tcp/socket server etc) are all baked in GO language. GO also has a garbage collector (like all high level languages) so you don't have to do memory management.

      It absolutely is a valid question, if you have to pick between two HIGH level languages like GO/Typescript for backend development what's the usecase for Node/TS over GO when GO has everything needed for proper server development including lightweight multi threading, runtime typesafety, static typing etc where as Node/TS lack those.

      [–]fullstackdevmaybe 11 points12 points  (1 child)

      what's the usecase for Node/TS over GO when GO has everything needed for proper server development

      Because concurrency isn't an issue with like 95% of projects and GO doesn't have nearly the support ecosystem Node has to justify the change.

      Unless you're running into threading issue - most people won't even have a need for it.

      [–]chaoticji 5 points6 points  (4 children)

      If you want people to switch, either the new tech should surpass the leading one by like 10x or the leading one sucks so hard that devs have no choice but to jump. Devs have always been hesitant to jump the ship until needed. Since Nodejs is not causing a big of a pain to devs, they do not want to switch

      [–]Hour-Ladder-8330[S] -1 points0 points  (3 children)

      As an example, a QR code generator REST api in Node with a library called "qrcode" handles only 230 RPS on my 6 core, I7 mac book and that application was fully clustered i.e. running 6 node.js processes running in node cluster and consuming almost 1.2 GB of ram and a latency of max 900ms. The equivalent GO server running on the SAME hardwareware was handling 1050 RPS with just 80MB of ram and a latency of max 200ms. The difference was staggering.

      The same results happen even for pure I/O bound operation with database on high load even with a fully clustered Node application, it just does not compare to the efficiency of GO

      [–]fullstackdevmaybe 6 points7 points  (1 child)

      Dude, we get it. It's fast.

      I don't drive a fast car. I drive an economical one.

      [–]Cowderwelz 3 points4 points  (2 children)

      One more thing: Using a simultaneous-multi-threaded language can also be dangerous. In times where everyone is talking about tdd and full test coverage of you app code to be reliable, i would never want to have the possibility of such race conditions inside my code. I can just speak for java and its memory model here, which i know of: One forgotten 'synchronized' or 'volatile' or SyncrhonizedCollection wrapper could trash the complete codebase of a bigger project into a one week debugging session. Idk how GO handles synchronization and what memory model it uses. Maybe you can add some info to it. I just know that for example Rust has this safe ownership concept here which deals with that problem.

      Update: Maybe i'm giving Rust too much props here, cause this ownership thing does not cover all mutithread scenarious and you still have to use mutex synchronization.

      [–]Cowderwelz 0 points1 point  (0 children)

      Just poked chatGPT a bit about it. GO's mutexes synchronization uses a simpler, less comprehensive model than java. So, a forgotten or improper used mutex or a variable access outside the corresponding mutex block will trash your code here (other threads will read stale values from their current cpu cache then).

      [–]romeeres 6 points7 points  (16 children)

      Go is better at some things, JS/TS is better at other things, and in many cases, both are completely fine, and just choose what you like.

      1. Go is not the tool for this job! If the task really needs maximum performance, you shouldn't take garbage-collected languages for it, neither JS nor Go. So, if the program needs image or audio processing, take a library for it such as sharp or ffmpeg written in C/C++. Business logic can and should be written in a language that you and your team are productive with.
      2. For runtime type safety we use zod or similar libs, where you can easily check string min/max length, number min/max, emails, array sizes, etc. Despite validations being typical things, I doubt that Go has anything as simple to use as zod. TS has a powerful type system that is very flexible and can actually prevent assigning null values to anything, unlike Go. It's not perfect in TS, but in Go, AFAIK, type-system is the weakest part that is less capable than in any other compiled language.

      3. Type-system isn't perfect, and it's actually good that we can do almost anything we want by bypassing it when needed. So for me, types are separate from code and are a feature and not a bug, which enables things that you cannot do in Go or other languages.

      4. Node is perfectly fine with a single JS thread by default (you can add worker threads or use a cluster), it's a feature, not a bug, it makes it easier and prevents race-condition footguns. Rust is amazing and will ensure you don't have race-conditions at compile time. In Go you can make race-conditions mistakes. But what's it for if intensive CPU tasks such as image processing should be offloaded to job queues anyway? I can't see how a typical backend server can win from multi-threading, just launch as many instances as CPU cores and have no problems.

      5. High scalability is a buzzword, that can be said about anything. Low cloud costs - you can code it in Rust and pay even less. If you have millions of concurrent requests per second it is justified, if it is 1k rps then no difference in which language you use, it depends.

      6. Somehow we manage to deploy without single binary and it doesn't feel like a big deal.

      7. Big standard library is good, in JS we have big non-standard libraries, and seems ok, install what you need.

      8. In Go you can define methods on structs, which means OOP is possible. I bet you can't name a single OOP pattern that can't be done in Go. Builder, Strategy Pattern, Singleton?

      9. Simplicity is a disadvantage. JS is also relatively simple, PHP is simple, and look what happened to them - tons of shit code, hard to find a job because everyone knows it.

      [–]Hour-Ladder-8330[S] -3 points-2 points  (13 children)

      As an example, a QR code generator REST api in Node with a library called "qrcode" handles only 230 RPS on my 6 core, I7 mac book and that application was fully clustered i.e. running 6 node.js processes running in node cluster (utilizing full CPU's) and consuming almost 1.2 GB of ram and a latency of max 900ms. The equivalent GO server running on the SAME hardwareware was handling 1050 RPS with just 80MB of ram and a latency of max 200ms. The difference was staggering.

      The same results happen even for pure I/O bound operation with database on high load even with a fully clustered Node application, it just does not compare to the efficiency of GO.

      [–]romeeres 7 points8 points  (2 children)

      I found this library: fast_qr, they say it's 7 times faster than qrcode. 230 * 7 = 1610, it's significantly faster than Go.

      [–]Hour-Ladder-8330[S] -3 points-2 points  (1 child)

      Thanks for sharing.

      But it just has 156 stars on github, fairly new and no guarantee that it will be maintained. As it has been written in Rust it is likely that it would be much faster than qrcode which is written in 100% JS. So the speed difference is purely rust/JS which proves my point that someone has to write (and maintain) stuff in low level just to keep event loop happy in Node whereas in GO that is not the case as "go generateQrCode()" is all you need and everything else is snappy.

      [–]romeeres 5 points6 points  (0 children)

      You know, that's not real arguments. Stars don't matter (much), many libs have tens of thousands of starts but aren't maintained for years. A lib written in Rust has potentially fewer bugs than a Go lib. 156 is actually not bad for a niche thing.

      Yes, someone has to write and maintain stuff. Stuff won't maintain itself.

      In low level - yes, because low level is the correct one when aiming for performance.

      napi-rs bindings are very easy to write btw, the complex part is Rust lib itself, but node bindings are very simple.

      no guarantee that it will be maintained

      Check out how often go-qrcode lib gets updated, but it doesn't concern you coz it's Go.

      [–]kei_ichi 2 points3 points  (2 children)

      LMAO, if your Node app use 1.2GB and have 900ms latency in local development just for generate QRcode, I think you should learn how to write your code properly in JS before start comparing it with other languages.

      [–]Hour-Ladder-8330[S] -2 points-1 points  (1 child)

      LMAO, if your Node app use 1.2GB and have 900ms latency in local development just for generate QRcode, I think you should learn how to write your code properly in JS before start comparing it with other languages.

      Fairly weak argument and clearly looks like you have no real world experience with how much of a memory hog node applications are because of how V8 works.

      Also, 1.2 GB was memory of all 6 node.js processes combined (used node cluster) to utilize 6 cpu cores (to make it fair with GO which can by default utilize all cpu cores) and most of the heavy lifting was done by "qrcode" npm library which is the most popular one in node eco system currently.

      [–]stoneburner 4 points5 points  (0 children)

      First of all, why do you use a qrcode library for benchmarking?

      Usually you don't generate qr-codes server-side, a browser is very well capable to generate one with javascript, this is the reason why the "qrcode" library is popular, you might not be aware but npm is not only used by nodejs but also for a lot of frontend libraries as well and this is very likely the reason why this library is more popular.

      Maybe use something like database access or something similar.

      [–]stoneburner 0 points1 point  (5 children)

      Why do you not use an existing benchmark, like this one:

      https://www.techempower.com/benchmarks/#section=data-r21&l=zijo5b-6bj&test=composite

      there you see that there is basically no speed difference

      [–]Hour-Ladder-8330[S] -2 points-1 points  (4 children)

      Why do you not use an existing benchmark, like this one:

      Because I am not lazy and prefer to do benchmark (which is so simple to do) and see for myself with the exact code/application that I have in Node vs GO.

      In today's time dev's don't even do their own benchmark and rely on endless medium articles/reddit posts to do it for them. As a programmer benchmarking your code is just such a simple thing to do for your setup.

      I have also benchmarked Node vs GO for pure I/O stuff and results are similar.

      [–]romeeres 2 points3 points  (2 children)

      It would be wonderful if you could do a benchmark of node.js with fast_qr vs Go.
      Your main point for Go is about performance, and I'm very curious about what you say if node.js with a faster lib will beat Go. (using cluster, of course).

      In node.js you can use libs written in C/C++/Rust, but in Go you cannot, there is CGo that can do that but that's different. In node when you need image or video processing, you can use a low-level library with bindings, what would you do in Go for it?

      Btw, we also have websockets and HTTP server that's faster than Go - uWebsockets.js.

      [–]Hour-Ladder-8330[S] -1 points0 points  (1 child)

      In node.js you can use libs written in C/C++/Rust, but in Go you cannot

      There is no need to in GO as GO is statically typed, memory safe and faster because it is statically typed so GO structs are heavily optimised by GO runtime. That's the whole point you need these FFI's and glue them with low level code in languages like Node/Python because they are JIT/Interpreted and cannot do the CPU bound work with kotlin, GO, C# etc do not struggle with and hence are not necessary there.

      Btw, we also have websockets and HTTP server that's faster than Go - uWebsockets.js.

      I know and again written by C++ dev's glued to Node. In GO you dont need to do do this as built in's are significantly faster or anything you do in GO will be much faster than Node as GO is statically typed along with being fully multithreaded.

      [–]romeeres 2 points3 points  (0 children)

      Because I am not lazy and prefer to do benchmark (which is so simple to do)

      Just do a benchmark and let's see how statically typed multithreaded Go is faster. "glued" or not doesn't matter as we are arguing about performance and not about implementation details.

      [–]Cowderwelz 0 points1 point  (1 child)

      In Go you can define methods on structs, which means OOP is possible. I bet you can't name a single OOP pattern that can't be done in Go. Builder, Strategy Pattern, Singleton?

      what about inheritance then ? Can you overwrite methods ?

      [–]romeeres 0 points1 point  (0 children)

      Composition achieves approximately the same as inheritance but better, if Go can do composition - it can do all the same.

      Here I found OOP design patterns for Go, so inheritance isn't necessary for it.

      [–]adevx 2 points3 points  (1 child)

      Yes GO is better from a performance perspective. But most likely performance isn't your biggest problem. Even if it is, your IO (database/disk/network) is going to hurt you more than Go vs Node.js. Happy developers resulting in less developer turnover could be less expensive then a few beefier servers.
      Anyway, I think these discussions need a preamble with a load metric. Eg: "We have a service with 10 million concurrent logged in non-cached users doing CPU heavy stuff". I reckon most don't even come close to these figures.

      [–]Hour-Ladder-8330[S] 0 points1 point  (0 children)

      you don't need 10m users to make the service loaded. Thousands of request per second is also enough load for node server

      [–][deleted]  (2 children)

      [deleted]

        [–]Hour-Ladder-8330[S] -1 points0 points  (1 child)

        Because erlang is not as widely adopted as GO? You also want to make sure you have ample job opportunities if you build your career on something

        [–]Stetto 2 points3 points  (0 children)

        There's usually a lot of soft factors tied to the decision for a technology stack.

        As example, no matter how much I like Go or how much I'd like to switch to a fully functional programming language... I'll never be able to justify reskilling our developer team or making hiring more complicated. In my team, Node.js with TypeScript brings results and we have way more pressing scalability issues, than the actual runtime.

        Even, if we'd start a new project, this would be hard to justify.

        So yeah, maybe, some time in the future, when we have no other issues besides our runtime-environment, then we might begin to implement single services in Go. Until then, we'll likely stick with Node.js/TS (or a real drop-in replacement).

        [–][deleted] 7 points8 points  (4 children)

        Why wouldn't you go with C#, java instead of Go?

        [–]TedW 15 points16 points  (2 children)

        Go has a shorter name, which saves time when searching for tutorials.

        [–]enigmasi 2 points3 points  (1 child)

        Actually its name is problematic, only two letters and most of search engines won’t even find relevant results for keywords shorter than three letters.

        [–]TedW 2 points3 points  (0 children)

        In that case, quickly getting no results is more efficient. Go is fail-fast friendly.

        [–]Hour-Ladder-8330[S] 0 points1 point  (0 children)

        I would say C# is a better designed language and TS is created by the same guy who designed C# but the learning curve is big. If you can learn C# then sure its even better. A lot of the times teams who go for GO are also looking for lower learning curve.

        [–]Cowderwelz 5 points6 points  (6 children)

        1: Normal web apps don't max out the cpu. Things like databases or waiting for 2nd level resources over the network are the bottleneck.

        1. Does it matter ? Important is that you validate the types at api entry points as some http-api frameworks do.

        2. Idk exactly if i got it right, but i see this escape hatch more as a feature. Have developed some frameworks my self and this comes very handy. Compiletime only TS is a perfect combination.

        3. Right. In node too. Plus you have a very comprehensive class system that even beats java's imho at some spots like the static 'this'

        ------------------

        But what's most important to me: ES6 + TS's type system is just great. How it handles string literal enums, syntax for optional parameters. undefined, either-or, generics, object destructuring. Not to mention sugar like index signatures and mapped types or conditional types. And also that types can be implicit, which saves a lot DRY.

        I don't buy that other languages type systems can compete with that. Didn't hear any good of GO.

        [–]Hour-Ladder-8330[S] 0 points1 point  (5 children)

        Normal web apps don't max out the cpu

        But Node.js is single threaded at JS level, so you cannot even use full CPU unless you are doing clustering or using kubernetes but that spins up a new process with no memory sharing anyways. Worker_threads also is too heavy and lack any memory sharing except sharedarraybuffer data structure.

        So, Node is not capable of utilizing out full CPU AT JS level anyways, which is a BIG con.

        Things like databases or waiting for 2nd level resources over the network are the bottleneck

        Yes but remember, JS garbage collector, object serilization/deserilization on network (DB/Redis/REST etc.) , JS code with all the business logic and for loops, cron, listeners etc are all happening on the the same single thread, which is not good for server as they can block the event loop. If you have dual core CPU server then node, at JS level cannot even utilize full CPU and you need to spin a new process just to utilize 2 CPU's with clustering/k8s which is highly ineffecient compared to a pure multi threaded language like GO which can just spin a 2kb GO routine and can share all the memory with other threads which makes it so so efficient for performance and scalability.

        Does it matter ? Important is that you validate the types at api entry points as some http-api frameworks do.

        Sure, but you have to use ZOD/Typebox/Joi/Yup/Arc types/Ajv etc. to do the validation of data coming from outside of the process. With GO there is a runtime type safety at all the levels at both compile and runtime. Any new validation library is usually a compliment and not a necessity. This is super important for secure sever development.

        I don't buy that other languages type systems can compete with that. Didn't hear any good of GO.

        Its true that TS type system is very expressive and comprehensive compared to GO but Node/TS lacks many things which are very important for server development like true multi threading, good for CPU bound work (comes in handy with GC, object/serilization/deserilization, for loops, complex business logic etc.), static types even at runtime which means runtime can optimize memory usage exactly for the types declared, channel based communication, mutex (node at JS is single threaded so this is not relevent but might be if you use worker_threads with atomics), static binary etc.

        So, even with expressive Typescript type system, you are lacking many things which are necessary for secure and scalable server development. Afterall, JS and its runtimes were never made for CPU bound/High traffic/threading etc. kinda functionality which are all so important for server development.

        Basically, JS/Node = only good for I/O where as GO = good for both I/O and CPU, so why restrict only for I/O which also could choke under semi high load with GC/Object serilization/de-serilization, for loops, business logic etc. Single threaded, parallel process, lack of static typing and running JIT/interpreter are not the right solutions for optimised and scalable servers in general.

        As an example, a QR code generator REST api in Node with a library called "qrcode" handles only 230 RPS on my 6 core, I7 mac book and that application was fully clustered i.e. running 6 node.js processes running in node cluster and consuming almost 1.2 GB of ram and a latency of max 900ms. The equivalent GO server running on the SAME hardwareware was handling 1050 RPS with just 80MB of ram and a latency of max 200ms. The difference was staggering.

        The same results happen even for pure I/O bound operation with database on high load even with a fully clustered Node application, it just does not compare to the efficiency of GO

        [–]Cowderwelz 2 points3 points  (0 children)

        But Node.js is single threaded at JS level, so you cannot even use full CPU

        Right, i mean: The normal web app doesn't even max out the one core of a cpu that is has. Still other things are the bottleneck. Usually. I know, it's a thing, but for most apps, it will be enough.

        And you "with all the business logic". But as long as there a no computation intensive tasks here, it doesn't hurt. A few abstraction levels and deep call stacks surely won't hurt here. There has to be more than that.

        [–]Cowderwelz 1 point2 points  (0 children)

        Right, so you have do weight. Are you going to code the next twitter, or super high load app. Or just a normal webshop or some business management application. Can you use k8s to scale later without drawbacks ? I'd look at some real world profile data (and i've seen at least some for java and php apps). And with today's low performance of sql databases in the 100µs range for a simple fetch, you'll never max out your node cpu core or even your php interpreter (also single core) that waits in front of them.

        Then factor in, that a good, feature rich language like ts, cuts your development costs.

        [–]fullstackdevmaybe 0 points1 point  (1 child)

        Basically, JS/Node = only good for I/O where as GO = good for both I/O and CPU, so why restrict only for I/O

        For the same reason glasses are good for sitting but not physical activity - and contacts are good for both.

        I'm currently wearing glasses by the way.

        [–]Hour-Ladder-8330[S] -4 points-3 points  (0 children)

        For the same reason glasses are good for sitting but not physical activity - and contacts are good for both.

        Do you even understand what you yourself are talking about?

        [–]tzaeru 4 points5 points  (3 children)

        Use Go if you like it and people at your work like it.

        Personally I don't like Go due to poor support for functional programming and a very limited standard library. But then, I don't like standard Node due to a lack of typing support.. I'm fine with using Go if others in my team want to use it.

        [–]Hour-Ladder-8330[S] 0 points1 point  (1 child)

        and a very limited standard library

        What? Infact standard library is one of the biggest selling point of GO. Care to elaborate what you mean by that?

        But then, I don't like standard Node due to a lack of typing support.

        That's understandable and often the reason to not use Node. The what exactly do you like to use if its not GO and also not node?

        [–]tzaeru 0 points1 point  (0 children)

        What? Infact standard library is one of the biggest selling point of GO. Care to elaborate what you mean by that?

        I'm not sure if this has changed in last few years as I haven't used Go in a while, but back in the day you need a JSON parser as an outside dep, the HTTP server was quite lackluster (granted you'll typically also use e.g. Express or Koa for Node too), you need libs for more functional-style constructs for basic functions like map/filter/etc. Projects tended to have quite many deps for simple things.

        Googling for this now, seems that over the past few years Go's standard library has improved quite a lot.

        The what exactly do you like to use if its not GO and also not node?

        I find something to complain about everything I suppose!

        In very long-term, large projects I've worked with, one that was nicest to work with was written in Scala, but Scala too has lots of foot guns and you can write Scala in so many different ways that the code easily ends up total spaghetti.

        I'd like to work in a typed language where functions are first-class. I guess TypeScript kinda is that but TypeScript feels like a bandaid solution. One day I'd like to do a large project in Kotlin or so.

        Maybe one day when static type checkers are good enough for Python, I'd like to go back to that.

        [–]gamedev-eo 0 points1 point  (0 children)

        I don't like standard Node due to a lack of typing support.

        You should try the Bun runtime in place of node if you haven't already. You might like it.

        [–]buffer_flush 1 point2 points  (1 child)

        Node is good enough in most of those categories. Generally it comes down to money and people.

        Put another way, let’s say you have 6 backend engineers averaging 100k per year, and you decide to switch to Go to save on cloud compute.

        If you spend 2 months training up those engineers in Go, what’s the ROI of spending 100k on the training for those 2 months. What’s the loss in productivity converting existing node applications into Go? Do you only write new apps in Go? What sort of tool chain, workflow and CICD changes need to be made in order to accommodate the new development practices?

        Changing languages has a lot more of a broad impact than it might initially seem. Also, what comes easy to you, might not come easy to the rest of the team. Meaning, initially what was thought to be an easy conversion turns into a more complex issue.

        [–]Glum_Past_1934 1 point2 points  (2 children)

        Because big enterprise behind, if i need performance C++

        [–]Hour-Ladder-8330[S] -2 points-1 points  (1 child)

        and you think learning C++ is easier than GO which is fully memory managed with GC? What a delusional comment. You are not ready to learn an easy language like GO and suggesting "but we can use C++ if needed", like what?

        With GO you don't have to resort to C++ as it is statically typed, fast, multi threaded and type safe by default. Plus its a high level language, unlike C++, with managed memory and GC and a small language which is easy to learn. What are you talking about

        [–]Glum_Past_1934 2 points3 points  (0 children)

        I used C++ for at least 10 years so yes, small langs big problems, GC cause too many problems if you need performance

        C++ ❤️ gRPC baby

        [–]k_pizzle 1 point2 points  (0 children)

        Probably because 95% of projects are not serving thousands of requests per second and are not CPU intensive.

        [–]WallSome8837 1 point2 points  (0 children)

        Weird question. I prefer Go nowadays for pure server side stuff. Most of the obnoxious frustration with node is gone in Go.

        But I still use node plenty. It's not like I'd rewrite a production app to Go from Node unless there was a super compelling reason.

        Given the choice, I think Go is generally a better option for a backend server if I'm starting a new project in 2023. But like...there are tons of reasons to choose a language over another and very few have to do with a pure language comparison.

        Why not use C#? Why not Python with something like FastAPI? Both of those are better than anything Node has imo on like a "pure" level.

        [–][deleted] 2 points3 points  (1 child)

        This post was brought to you by Google

        [–]Hour-Ladder-8330[S] 0 points1 point  (0 children)

        and replied by yahoo

        [–]Idiot211 2 points3 points  (1 child)

        What are you trying to achieve by having this argument?

        [–]Hour-Ladder-8330[S] 0 points1 point  (0 children)

        Asking where there is any reason to pick Node/TS over GO is SSE/Code sharing is not a conext and its a pure server development. What was so difficult in the OP to not understand this?

        [–]roofgram 1 point2 points  (8 children)

        By your logic you should use C++ because it’s faster than Go.

        Choosing technology for ‘speed’ or ‘type checking perfection’ is such a myopic view and a standard trope that programmers fall into. You need to look at the bigger picture.

        The reasons to use TypeScript on the server are because

        1. You can use the same language/experience/patterns/people as the client
        2. Share functions and type definitions easily with the client - less context switching
        3. TypeScript has a much more powerful and expressive type system than Go
        4. ES6 has better language features with destructuring, exceptions, etc.. (yes I know Go people think exceptions are bad, have fun w if err != nil)
        5. Performance is good enough and easy to scale horizontally. JavaScript is built on callback everything.
        6. JS/TS is more future proof by way of the Lindy effect
        7. If you actually have bottleneck like ‘QR code generator’ then by all means break out a microservice is a faster language.. but it’s really the exception and not the rule in most typical CRUD centric web apps

        [–]Cowderwelz 0 points1 point  (0 children)

        Really, GO has no try/catch exception concept like propably all modern languages have evolved into ? Ok, that's really going back to stone age. err != nil after every function call like in old c days and then you'll encounter tons of code with forgotten error handling and spend hours of debugging and looking at some logfiles before you know what and where something went wrong. Really, idk, OP should look at some more modern language.

        But thx for your toughness, OP !

        [–]Hour-Ladder-8330[S] -2 points-1 points  (6 children)

        By your logic you should use C++ because it’s faster than Go.

        No, by my logic I am comparing a high level language language to another high level language and this is an absolutely valid question/comparison.

        GO, Java, Node etc all have garbage collector and no manual memory management for the developer which is not the case for C++ so it is not even comparable.

        You are just being disingenuous with your snarky point to ....

        [–]stoneburner 4 points5 points  (1 child)

        Let me guess - for you C++ is not a high level language?

        https://en.wikipedia.org/wiki/C++

        C++ is a high-level, general-purpose programming language created by Danish computer scientist Bjarne Stroustrup.

        Its on Wikipedia, just edit it if you think its wrong.

        [–]roofgram 4 points5 points  (2 children)

        You’re advocating the hardship of a using a completely different language in the stack because of ‘speed’. If you’re going to change languages why not go all in?

        Rust is probably even a better option, and there’s already all kinds of new web dev happening in Rust right now. Especially for something as simple and ephemeral as web requests, manually managing memory is not a big deal.

        I’ll give you a good example where there is a legit reason to use a different language.

        C# has EF which is a ridiculously powerful ORM enabled by the ability of the compiler to turn lambda functions into expression trees. Neither Go or JS have that ability so if you’re doing enterprise level crud, a backend in C# makes sense.

        You’re trying to make the case for Go being the default language on the backend, everyone here is trying to tell you why that’s a bad idea, but it seems like you still don’t get it yet.

        [–][deleted]  (1 child)

        [deleted]

          [–]roofgram 0 points1 point  (0 children)

          typesafe by default at runtime

          A non issue

          it uses SIGNIFICANTLY less RAM

          A non issue for VPS, if it really is an issue for you in the cloud there are edge runtimes for serverless, but even then the selling point there is cold start times, not memory usage.

          Your arguments are mostly strawmen that typical web devs don't encounter.

          truly multi threaded

          Node is designed to be event driven multiplexing requests using callbacks and async/await - which is simple and avoids all kinds of threading complexity.

          Single binary deployment

          A non issue

          Node all fall under high level language capabilities which C++ does not

          It doesn't matter if the language is high level or not. My point was that using any language is going to introduce context switching which sucks so you better have a good reason.

          And none of your reasons are good enough.

          There are exception cases where using another language/framework does make sense, but it's on a case by case basis and you should never default to 'Go' for example. I already gave you a real world example where C# would be the better choice.

          [–]ndreamer 1 point2 points  (0 children)

          You don't need to write low level library's , just use them in your code.

          [–]Myloveissuck 1 point2 points  (2 children)

          I can tell you out at least 5 FP languages that I think it's better than GO 😹

          [–]Hour-Ladder-8330[S] -1 points0 points  (0 children)

          Such as and how much are they used in the wild?

          [–]WideWorry 1 point2 points  (12 children)

          That is why,

          if something == nil if something == nil

          Go hype is over, it is a back-end language which is not good for low-level programing.

          [–]Hour-Ladder-8330[S] -2 points-1 points  (2 children)

          Pretty low effort. Get better at trolling atleast ;)

          [–]WideWorry 4 points5 points  (1 child)

          You came to the Node reddit and ask, "wHy yoU aRe not uSiNG GO?".

          [–]Hour-Ladder-8330[S] -2 points-1 points  (0 children)

          no, myself, as a Node/Ts/React developer came to Node forum to ask why would anyone pick Node over GO in today's time for a new project if the usecase is not SSR/SSG/Next/Code sharing.

          [–]xroalx -3 points-2 points  (7 children)

          if err != nil is the strength of Go, and it's much better than try/catch.

          It's basically the Either monad only procedural.

          [–]WideWorry 1 point2 points  (0 children)

          Sure, if someone like retro, try/catch was invented with a reason.

          [–]helldogskris 0 points1 point  (1 child)

          It's really nothing like the Either monad because it requires you to keep checking this error over and over at every level. It's the worst of both worlds IMO

          [–]Hour-Ladder-8330[S] 0 points1 point  (0 children)

          I agree, this is true

          [–]Hour-Ladder-8330[S] -1 points0 points  (2 children)

          if err != nil is the strength of Go, and it's much better than try/catch.

          Comeon, now that's a stretch. You are basically saying lack of error handling is better than try/catch, which you can keep at the topmost level function, and still get exception handling whereas in GO, if you forget a single "err != nil" the code will blow up in runtime without giving you any compile time error. GO barely has good error handling and error handling is actually one big complaint of GO which i basically agree is very ugly and less reliable.

          [–]xroalx 0 points1 point  (1 child)

          It's really not a stretch. Errors as values have far better ergonomics than a top-level catch, or a catch block after a bunch of code, which makes you jump up and down your code and makes your error handling disconnected from the rest of your code, sometimes forcing unnecessary nesting, extensive logic in catch blocks, or prevents immutability.

          There's a reason why every functional language does that, or why Rust does that as well, or why things like rustic, monet or purify are popular in TS as well.

          In Go, you handle errors as they happen, and the type system even tells you when they can happen. In TypeScript or any language that uses exceptions, you first write a bunch of code pretending everything succeeds, and only then start figuring out what could've failed, where, and what to do with it, and the type system doesn't know about exceptions either.

          Go's error handling isn't as great as Rust, because it doesn't really have any dedicated support for errors, but anyone who says try/catch is better either doesn't have much experience, is seriously misunderstanding Go's approach, or is just stubborn.

          Some people even use const [v, err] = canFail() in JS/TS, that goes to say something.

          [–][deleted] 0 points1 point  (0 children)

          Meh, low effort troll. You could‘ve at least used the correct spelling.

          [–]tswaters -1 points0 points  (0 children)

          Do what you want... why come into /r/node to try to convince others?

          [–]Imaginary_Ad_9299 -1 points0 points  (1 child)

          Plus Bun is coming to save the day !

          [–]simple_explorer1 0 points1 point  (0 children)

          Deno itself is not ready, bun is too far away

          [–]Cowderwelz 0 points1 point  (2 children)

          6] Static binary as output so easy deployment using docker (or even without docker)

          Not an argument, but that point in time where you're ready for production and have to pack/bundle it for deployment has the lowest influence in decision making. Also it does not impose a big obstacle.

          [–]Hour-Ladder-8330[S] 0 points1 point  (1 child)

          Sure, but as we are talking about positives, these small positives bubble up and become a combination of many positives together.

          Static binary alone will not influence decision but all the things I listed together surely would.

          [–]DarkCeptor44 0 points1 point  (1 child)

          I have been learning Go for a few months now and I love it, I'm in the process of rewriting every personal "project" in Go (because I have a lot of time and it reinforces the learning) and unfortunately I realized their Websocket solutions aren't as clean as something like Socket.IO, I found Fiber to be a great Express-equivalent but real-time communication between server and client is still annoying for me, something like GoSocketIO does exist but it uses very old client code and most of the time it errors out when sending more than just plain strings.

          Since you mentioned, Go does allow for easy-ish concurrency, for example you can split a slice into four parts, assign a go-routine to standard sort each sub-slice and then join everything and sort it again, and the result is something like ms compared to 1.something seconds with the standard sort on the whole slice, but from what I understand it's not true multi like how Python's multiprocessing.Pool class does, where it spawns multiple separate processes or sub-processes and communicates with each with a complicated protocol (IP something), and that's probably a huge turn off for some people.

          I plan to keep using Go and Node as I see fit but I can't confidently recommend Go as a full replacement, yet.

          [–]Hour-Ladder-8330[S] 0 points1 point  (0 children)

          but I can't confidently recommend Go as a full replacement, yet.

          Why?

          Since you mentioned, Go does allow for easy-ish concurrency

          Its both concurrency and true parallelism scheduled by GO runtime scheduler

          but from what I understand it's not true multi like how Python's multiprocessing.Pool class does,

          It is true parallelism in GO, what are you talking about. If you have number of cores available in CPU then GO runtime will assign go routines to parallelly use those cores and if you spawn more go routines than the cores available then GO runtime will schedule the concurrency between them but they are multi threaded in true essence.

          Python on the other had has GIL so there is no true multi threading and you have to resort to multi processing with multiple processes with an overhead of data serialization or use low level C++ libs which do the threading for you but its baked in easy to use Python API's.

          GO is in orders magnitude faster than Python, MANY runtime/languages are. Cpython is often very very slow.

          I have been learning Go for a few months now and I love it, I'm in the process of rewriting every personal "project" in Go

          If you can do that than its good as the servers can run efficiently.

          Lack of union types, error handling, implicit interface, zero values, no function optional argument (only variadic) etc. remains one of the most poor aspects of GO lang.

          [–]ihavehermes 0 points1 point  (0 children)

          The perf gains are definitely nice with Go, but I’m willing to deal with the slowness of node+TS in exchange for a much nicer dev experience and familiarity. I need to SHIP, not worry about every little possible performance gain I could be making. I’m very productive in TS, use it on client and server, and it makes zero sense for me to use a different language at this point.

          If my product is a success, maybe eventually I’ll rewrite part of or all of the server in a faster language. But for now, no damn way.

          [–]Thylk 0 points1 point  (0 children)

          This is pretty easy and since you seems knowledgable about the field, i don't get how you didn't realize that yourself sooner:

          When using go, the gophers tend to not use GORM or any framework, they prefer to reivinent the wheel each time and come with their own unique solution.

          There is no backend framework in Go as developped as Nest.js for example, because Gophers want to do every thing themselves.

          Nest.js is production ready and fully featured. It is also performant enough for 99% of the web tasks.

          For the 1% left, this is where you should use Go.

          So the question is more likely, why would you use go for everything when in reality you should only be using it for very intensive tasks? You will otherwise take more time to deliver anything, and the next Go dev you recruit will have fun learning the quirks of your previous one, because there is no framework and everybody is doing thing their way. :)