Hacker Newsnew | past | comments | ask | show | jobs | submit | SkepticalWhale's commentslogin

Betting on AI could mean a pause on hiring junior developers while we wait to see how AI plays out, though.


Go has its fair share of flaws but I still think it hits a sweet spot that no other server side language provides.

It’s faster than Node or Python, with a better type system than either. It’s got a much easier learning curve than Rust. It has a good stdlib and tooling. Simple syntax with usually only one way to do things. Error handling has its problems but I still prefer it over Node, where a catch clause might receive just about anything as an “error”.

Am I missing a language that does this too or more? I’m not a Go fanatic at all, mostly written Node for backends in my career, but I’ve been exploring Go lately.


> It’s faster than Node or Python, with a better type system than either. It’s got a much easier learning curve than Rust. It has a good stdlib and tooling. Simple syntax with usually only one way to do things. Error handling has its problems but I still prefer it over Node, where a catch clause might receive just about anything as an “error”.

I feel like I could write this same paragraph about Java or C#.


Java and C# are both languages with A LOT more features and things to learn. Go someone can pick 80% of the language up in a single day.


Just because you can learn about something doesn't mean you need to. C# now offers top-level programs that are indistinguishable from python scripts at a quick glance. No namespaces, classes or main methods are required. Just the code you want to execute and one simple file.

https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals...


The benefit of the language being small and "normal" idioms mostly followed and the std library being good-enough that people rarely import another dep for something it can handle is that it's by far the easiest language in which to read my dependencies that I've ever used.

If I hit a point where I need to do that in pretty much any other language, I'll cast about for some way to avoid doing it for a while (to include finding a different dependency to replace that one) because it's almost always gonna be a time-suck and may end up yielding nothing useful at all without totally unreasonable amounts of time spent on it, so I may burn time trying and then just have to abandon the effort.

In go, I unhesitatingly hop right in and find what I need fast, just about every time.

It's the polar opposite of something like Javascript (or Typescript—it doesn't avoid this problem) where you can have three libraries and all three both read like a totally different language from the one you're writing, and also like totally different languages from one another. Ugh. This one was initially written during the "everything should be a HOF" trend and ties itself in knots to avoid ever treating the objects it's implicitly instantiating all over the place as objects... this one uses "class" liberally... this one extensively leans on the particular features of prototypal inheritance, OMG, kill me now... this one imports Lodash, sigh, here we go... et cetera.


I mean thats fine, but thats hardly applicable to the ease of throwing a new dev into a very large c# codebase and how quickly they can ramp up on the language.


Any large codebase has a large ramp up time by virtue of being large. And the large codebase can have devex automation to get past the initial ceremony setup of larger languages like Java. It feels like the wrong thing to optimize for. As a better alternative to small services that would've been made in python or node, yes for sure, then the quick setup and simplicity of go makes sense. Which is why the biggest audience of people who use go and used another language previously is python engineers and people who want to make small network services.

At the larger codebase go company I worked at, the general conclusion was: Go is a worse Java. The company should've just used Java in the end.


Java and C# have way to much baggage to compare them to Go. They nearly look like different languages depending on the version you're using.


And they will trip over the remains 20% percent for the rest of their days.


Java is a very tiny language. I don't buy that it would take significantly longer to learn.


Now throw in spring on top of it, which is the standard in large java web codebases. Its very very daunting


Well, you ain't adding together two numbers in Go either.

Give me an apples to oranges comparison. With routing, cookies, authN/authz, SQL injection, cross site scripting protection, etc.


"Simple syntax with usually only one way to do things" is pretty much the exact opposite of Java.


I mostly agree with you except the simple syntax with one way of doing things. If my memory serves me, Java supports at least 2 different paradigms for concurrency, for example, maybe more. I don’t know about C#. Correct me if wrong.


But that's only because they're older and were around before modern concurrent programming was invented.

In C#, for example, there are multiple ways, but you should generally be using the modern approach of async/Task, which is trivial to learn and used exclusively in examples for years.


There is no one paradigm for concurrency, no method is strictly better than the other. Channels are not the only primitive used in go either, so it's a bit moot point.

What's important is how good primitives you have access to. Java has platform and virtual threads now (the latter simplifying a lot of cases where reactive stuff was prevalent before) with proper concurrent data structures.


What are Javas 2 different paradigms?


Maybe this is a bit pedantic, but it bothers me when people refer to "Node" as a programming language. It's not a language, it's a JavaScript runtime. Which to that you might say "well when people say Node they just mean JavaScript". But that's also probably not accurate, because a good chunk of modern Node-executed projects are written in TypeScript, not JavaScript. So saying "Node" doesn't actually say which programming language you mean. (Also, there are so many non-Node ways to execute JavaScript/TypeScript nowadays)

Anyway, assuming you're talking about TypeScript, I'm surprised to hear that you prefer Go's type system to TypeScript's. There are definitely cases where you can get carried away with TypeScript types, but due to that expressiveness I find it much more productive than Go's type system (and I'd make the same argument for Rust vs. Go).


My intent was just to emphasize that I’m comparing Go against writing JavaScript for the Node runtime and not in the browser, that is all, but you are correct.

Regarding Typescript, I actually am a big fan of it, and I almost never write vanilla JS anymore. I feel my team uses it well and work out the kinks with code review. My primary complaint, though, is that I cannot trust any other team to do the same, and TS supports escape hatches to bypass or lie about typing.

I work on a project with a codebase shared by several other teams. Just this week I have been frustrated numerous times by explicit type assertions of variables to something they are not (`foo as Bar`). In those cases it’s worse than vanilla JS because it misleads.


Yeah, but no one is using v8 directly, even though technically you could if you wanted. Node.js is as much JavaScript as LuaJIT is Lua, or GCC compiles C.


Fair, but I think the JavaScript ecosystem is unique in that the language is very separate from the thing that executes/compiles it. When you write Go, 99.9% of the time you're writing for the Go compiler.

When you write JavaScript (or TypeScript that gets transpiled), it's not as easy to assume the target is Node (V8). It could be Bun (JavaScriptCore), Deno, a browser, etc.


it is pedantic, everyone knows what "node" means in this context


Apparently not, because I first assumed that he was talking about TypeScript considering that JavaScript doesn't have much of type system to compare to.


The real cream is that there barely any maintenance. The code I wrote 15years ago still works

That’s the selling point for me. If I’m coming to a legacy code as that no one working wrote, I pray it is go because then it just keeps working through upgrading the compiler and generally the libraries used.


Yeah the big problem is that most languages have their fair share of rough edges. Go is performant and portable* with a good runtime and a good ecosystem. But it also has nil pointers, zero values, no destructors, and no macros. (And before anyone says macros are bad, codegen is worse, and Go has to use a lot of codegen to get around the lack of macros).

There are languages with fewer warts, but they're usually more complicated (e.g. Rust), because most of Go's problems are caused by its creators' fixation with simplicity at all costs.


I thought it was obvious that codegen was better than macros—at least, textual macros. You can't tell me Ken Thompson omitted macros from the Golang design because he didn't have experience using languages with macro systems!

Even AST-based macro systems have tricky problems like nontermination and variable capture. It can be tough to debug why your compiler is stuck in an infinite macro expansion loop. Macro systems that solve these problems, like the R⁵RS syntax-rules system, have other drawbacks like very complex implementations and limited expressive power.

And often there's no easy way to look at the code after it's been through the macro processor, which makes bugs in the generated code introduced by buggy macros hard to track down.

By contrast, if your code generator hangs in an infinite loop, you can debug it the same way you normally debug your programs; it doesn't suffer from tricky bugs due to variable capture; and it's easy to look at its output.


I would say more or less equivalent to textual macros. Unfortunately, as far as I can tell, the idiomatic way to write Go codegen (having skimmed some codegen repos and written some codegen tooling myself) is with the text/template package. Even battle-tested tools like protoc-gen-go are effectively built with printf statements rather than any sort of AST builder.

AST macros are complicated, yeah, and I agree that any half-decent macro system needs a convenient way to dump generated code and so forth. I'm not saying any macro system is better than codegen. But a decent macro system will give you hygenic tools to modify an AST, whereas codegen really forces you to hack something together. I'll grant that there's some worse-is-better charm to codegen, but I don't think that saves it from being ultimately worse.


A code generator is just a compiler; general arguments against code generation work equally well as arguments against using a compiler.

Writing a compiler is not "worse is better" and does not force you to hack something [fragile] together. Therefore, your argument is wrong.


Empirically, I think you'll find that Go code generators are bad compilers. Go codegen isn't written with AST transformations and quasi-quote libraries. A macro system would be an opportunity for the Go compiler to take responsibility for the the tooling around metaprogramming; in the absence of that, we have a fragmented ecosystem where everyone is always reinventing a minimal, hacked-together version of the wheel so that they can get on with building the thing they actually need.

Frankly, an official Go codegen library would solve pretty much all my complaints, but the only difference between that and a macro system is compiler integration.


Well, I do agree that bad compilers are bad, but I don't agree that a good compiler is basically a bunch of macros, or that emitting the code from the compiler backend with print statements correlates with a compiler being bad.


I have a deep hatred of Go for all the things it doesn't have, including a usable type system (if I cannot write SomeClass<T where T extends HorsePlay> or similiar, the type system is not usable for me).

For NodeJS development, you would typically write it in Typescript - which has a very good type system.

Personally I have also written serverside C# code, which is a very nice experience these days. C# is a big language these days though.


FYI, newer versions of Go do support the following

  type HorsePlay interface {
   Neigh()
  }
  
  type SomeClass[T HorsePlay] struct {
   players []T
  }
  
  func (sc SomeClass[T]) NeighAll() {
   for _, p := range sc.players {
    p.Neigh()
   }
  }
  
  type Horse struct{}
  
  func (h Horse) Neigh() {
   fmt.Println("neigh!")
  }
  
  func main() {
   sc := SomeClass[Horse]{players: []Horse{{}, {}, {}}}
   sc.NeighAll()
  }


It definitely hits a sweet spot. There is basically no other faster, widely used programming language in production used predominantly for web services than Go. You can argue Rust, but I just don't see it in job listings. And virtually no one is writing web services in C or C++ directly.


Maybe Nim. But it's not really caught on and the ecosystem is therefore relatively immature.


>with a better type system than either

Given Python's substantial improvements recently, I would put it far ahead of the structural typing done in Go, personally.


Yes, Python is massively ahead there. The largest wart is that types can be out of sync with actual implementation, with things blowing up at runtime -- but so can Go with `any` and reflection.

Python, for a number of years at this point, has had structural (!) pattern matching with unpacking, type-checking baked in, with exhaustiveness checking (depending on the type checker you use). And all that works at "type-check time".

It can also facilitate type-state programming through class methods.

Libraries like Pydantic are fantastic in their combination of ergonomics and type safety.

The prime missing piece is sum types, which need language-level support to work well.

Go is simplistic in comparison.


As long as none of the code you wrote ten years ago is worth anything, and you don't expect to want to use the code you're writing today ten years from now. Python is useful for prototyping.


This. Both Typescript and Python type systems are way far ahead, with structural typing, exhaustive checks and much more.


Python with a library like Pydantic isn't bad—I wouldn't rate base Python as being near Go's level, at all, though you can get it up to something non-painful with libraries.

Go (and lots of other languages...) wreck it on dependency management and deployment, though. :-/ As the saying goes, "it was easier to invent Docker than fix Python's tooling".


Yeah I think, given its gradual typing approach, that any discussion about the quality and utility of Python's type system assumes that one is using one of the best in class type checkers right now.

I didn't really use it much until the last few years. It was limited and annoyiongly verbose. Now it's great, you don't even have to do things like explicitly notate covariant/contravariant types, and a lot of what used to be clumsy annotation with imports from typing is now just specified with normal Python.

And best of all, more and more libraries are viewing type support as a huge priority, so there's usually no more having to download type mocks and annotation packages and worry about keeping them in sync. There are some libraries that do annoying things like adding " | None" after all their return types to allow themselves to be sloppy, but at least they are sort of calling out to you that they could be sloppy instead of letting it surprise you.

It's now good and easy enough that it saves me time to use type annotations even for small scripts, as the time it saves from quickly catching typos or messing up a return type.

Like you said, Pydantic is often the magic that makes it really useful. It is just easy enough and adds enough value that it's worth not lugging around data in dicts or tuples.

My main gripe with Go's typing has always been that I think the structural typing of its interfaces is convenient but really it's convenient in the same way that duck typing is. In the same way that a hunter with a duck call is the same as a duck with duck typing, a F16 and a VCR are both things that have an ejection feature.


Strong agree here. I learned Go after having worked in large typed Python code bases, and Go feels like a HUGE step backwards typing-wise.


Python type system is very good. It’s enforcing it consistently that’s bad. Thankfully most new libraries are typed.


I’ve only used Go for a little toy project but I’m surprised to hear the opinion that it has a better type system than Node, a runtime for which the defacto type system is typescript!

Agree on node/TS error handling. It’s super whack


I find Go's type system to be extremely lackluster.


Ok can you elaborate?


Maybe even painful for one dev once you need dependencies (virtualenv...)


Thankfully, uv makes this a lot better, but it'll still be a while before that percolates to the entire ecosystem, if ever.

There are real concerns about tying the language's future to a VC-backed project, but at the same time, it's just such an improvement on the state of things that I find it hard not to use.


I do really like the idea of going for more walks throughout my work day, and just checking in on Claude with my phone.


I'd like to see more software that amplifies local social interactions.

There are apps like Meetup, but a lot of people just find it too awkward. Introverts especially do not want to meet just for the sake of meeting people, so they fallback on social media.

Maybe this situation is fundamentally not helped by software. All of my best friendships organically formed in real-world settings like school, work, neighborhood, etc.


I ran a co-working space social club that resolved this issue for many introverts in 2015-2017.

This is at core a 3rd places issue, haven't had the capital to restart it post covid.


That sounds interesting. How did that work, did you rent a place for coworking and then opened it up for the social aspect?


My tech (I was founding engineer and CTO) company took over a co-working space and expanded it, we ran that portion of it at break even.

We intentionally set out to create a social club/co-working space. A lot goes into it. I'm a non-theist who comes from a multi generational group of theist church planters (like 100s of churches, just over and over), it's a multi factorial process with distinct transitions in space-time and community size, where each transition has to be handled so you don't alienate your communities founding members (who will be very different from later members) and still are able to grow.

People don't do it because they can't see the value while they are in the early mess of it. You have to like people to pull it off, you have to NOT be a high control person who can operate at high control at certain developmental stages. You have to have a moral compass everyone understands and you are consistent with, tech people like 0 trust. You have to create a maximum trust environment which means NOT extracting value from the community but understanding that the value is intrinsic in the community.

You have to design a space to facilitate work and play. It's not hard but you have to get everything right, community can't have mono culture and it must be enjoyable/uncomfortable, and you must design things so people can choose their level of engagement and grow into the community. It's easier once it has enough intertia that they understand they are building a thing with real benefits.

Even things like the flow of foot traffic within the space, chokepoints narrowing, these kinds of thing all effect how people interact.


I've been wanting to setup something like a 3rd place that tries only to break even. I'm unfortunately not a very social person.

Because these 3rd spaces are open to anyone and probably bringing people in from internet commmunties. What do you do when someone comes along and they're not breaking any rules but its clear that no one likes them? I've seen it drive entire groups away but because the person has done nothing wrong I cant/dont want to just say "fuck off kid no likes your weird ass"


A 3rd place isn't a friend group.

It isn't a single conversation or room. It isn't a single relationship cluster.

And someone is paying the insurance bill. Ultimately that person gets final say. A successful 3rd place can have tension, but not fools (in the economic sense, a person whose decision making and choices actively destroy the groups financial opportunities and stability. Theoretically a very clumsy person might be banned.)

There's a lot to unpack, I mean social dynamics, group polity, these really start with understanding what you really want to see brought into the world and why.

These things take fluidity, nuance and effort to get off the ground. Sometimes they just get lucky too. It's hard to tell ahead of time, proximity is important, population density is important, parties are important.

Getting initial traction is the hardest part, most groups die before they get a chance to have problems, that's why tying the groups space to a stable economic engine like an anchor company or a mission agency is so critical for repeatable success. Same with a small friend group as initial anchor, they just can't all be clique people.

The one thing that's very important is to always frame the space as a place for creating and experimenting, celebrate the amateur and the pursuit of mastery, getting started with a group of taste makers instead of doers will 100% kill your group.

Getting started with hypernetworkers who don't do things will kill your group. They'll show up and they are important later on.

All of these people have a place eventually but they can't form the dynamic core. The whole goal is to eventually have a place for every type of person so they can contribute to the whole and find the space where they can be celebrated, but a group has to be larger before certain types of people can bring their core skills to bear.


Hypothetical that I’d be happy to deal with when the time comes. We always imagine the worst case I get that. But once something like this takes off I imagine the whole point is to have created a community. And a community has lots of people that can do things together. I don’t know, I just don’t think this is something worrying about.


I woul love to hear more about this. I am in need of a 3rd place, but unfortunately the only meetups around are sports or churches here. What did the members in your group do after you shut down? Were you open to members offering donations to keep your 3rd place going?


That's very interesting. Do you have time to elaborate a bit?


This isn't a technology problem. Technology can help accessibility, but fundamentally this is an on-the-ground, social coordination problem.

Functioning, welcoming, and well-ran communities are the only thing that solves this. Unfortunately, technology often makes this worse, because it creates such a convenient alternative and also creates a paradox of choice. I.e. people think "when there's 1000 meetups to check out, and this one isn't perfect, I'll just move onto the next one" when actually it's the act of commitment that makes a community good.


I call it technology for touching grass e.g. look at The Offline Club [0]

[0] https://www.theoffline-club.com/


Indeed, you're describing the lack of a 3rd place. These days, maybe even the lack of a 2nd place as you graduate school and work is now fully remote. Without that societal push towards being in a public spot, many people will simply withdraw to themselves.

A third place would fix this, especially for men who need "things". You go to a bar for "thing" and if you meet some others to yell at sports with, bonus. We have less "things" for gen Z, and those things happen rather infrequently in my experience. I'm not sure if a monthly Meetup is quite enough to form strong bonds.


Great analogy.

Although I still wonder how long we're in this phase and how ubiquitous it will be, because didn't power tools coincide with improved automation in factories eliminating manufacturing jobs?


Whenever I have to develop on Windows, I clone my repos and run neovim / docker inside of WSL, for the improved performance (versus copying / mounting files from windows host) and linux. The dev experience is actually pretty good once you get there.

I'm not sure this is the same, though. This feels more like docker for desktop running on a lightweight vm like Colima. Am I wrong?


This is my same workflow even for C#


I agree with item #1, but it can be mitigated somewhat with dev tools like errcheck: https://github.com/kisielk/errcheck?tab=readme-ov-file


Minimizing state simplifies the codebase but it’s a trade off.

There are times the user experience is just objectively better with more state, and you have to weigh the costs.

If I am filling out a very long form (or even multi-page form) I don’t really want all that state lost if I accidentally refresh the page.


Yes, every time I start using some GUI software, I eventually find myself returning to markdown.

I spend all day editing in VSCode -- it's nice to use the same tool (and vim keys)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: