So I tried Go the other day



  • Now I can be told that I'm stripped of my Go programming virginity. And it sort of hurts.

    Granted, I've got the job done. Granted, it's not as ass-ugly as it could get. However, all the while I was writing that code (not much: parse some command line parameters, connect to a database, suck some data in, write some files), I was asking myself: why do those hipsters do this sort of things to themselves all the time?

    The OO model is some kind of an idea that might come to you on a bad magic mushroom trip. Okay, I get it, four legs good, two legs bad, composing good, inheritance bad. But why the hell just eliminate inheritance altogether? Does it eat your kids at night, or what? There is that handful of cases when inheritance is exactly the solution, and using composability instead makes it unnecessarily complicated.

    Okay, I get it: global variables are bad. Why, however, make them impossible to have at all? My program has maybe 5 functions total, including main. Why in the world should I make a separate package just to be able to have the five global variables I'm otherwise forced to pass around? (I ended up passing them around, as having a single source file for a program that small won.)

    Error handling got me flashbacks from the C days. Rob Pike might have a kind of a personal grudge towards proper exceptions, but making them nonexistent and forcing everyone into explicitly handling errors in every damn place they might occur is as stupid as it gets (I know there's panic and recover, but it's of no help if nothing in the standard library ever uses it).

    I just might use Go for the next small tool I need to carry around as a single binary that can run on anything as long as the OS is roughly the same, but I frankly don't understand why hipsters keep drooling over it.


  • BINNED

    Paging @ben_lubar...


  • BINNED

    And yet, languages that do make these "bad" things simple get just as much criticism 🤷♂


  • Banned

    @wft said in So I tried Go the other day:

    Granted, I've got the job done.

    There aren't many programming languages you can't get the job done in eventually.



  • @Gąska Unfortunately, the human lifespan is limited somewhat. :)


  • Banned

    @wft exactly. Don't waste your time with Go.



  • I've looked at alternatives to C# in the past because I feel like a lot of stuff is a bit boilerplately.

    I looked at Go. It is just strange and I think I dismissed it after I had a mare getting the latest version running on Ubuntu LTS (I think it was 16.04).


  • Notification Spam Recipient


  • area_can

    @wft if err != nil



  • @wft said in So I tried Go the other day:

    Okay, I get it: global variables are bad. Why, however, make them impossible to have at all? My program has maybe 5 functions total, including main. Why in the world should I make a separate package just to be able to have the five global variables I'm otherwise forced to pass around? (I ended up passing them around, as having a single source file for a program that small won.)

    ???

    Who's been lying to you about how variables work? You're able to use global (package-level) variables in Go. main is the name of a package.



  • @bb36e said in So I tried Go the other day:

    @wft if err != nil

    OPEN INPROGRESS


  • Discourse touched me in a no-no place

    @ben_lubar Looking at all that reinventing of exceptions and try…finally is painful.


  • BINNED

    @kazitor said in So I tried Go the other day:

    And yet, languages that do make these "bad" things simple get just as much criticism

    There are two types of programming languages:

    1. Those that people complain about.
    2. Those that no one uses.

  • Considered Harmful

    @wft If you used Rust, you'd end up eliminating all of those gripes while still being able to achieve the same goal. Inheritable traits, code with a minimum of boilerplate, still encouraging composition over inheritance, the availability of global variables (assuming you're right about them being impossible in Go; I've got my doubts), single source file, explicit errors with an operator to completely ignore them, and what you said about compilation still holds true.


  • Considered Harmful

    @antiquarian said in So I tried Go the other day:

    @kazitor said in So I tried Go the other day:

    And yet, languages that do make these "bad" things simple get just as much criticism

    There are two types of programming languages:

    1. Those that people complain about.
    2. Those that no one uses.

    If you start with the blakey mindset that every single bit of software in the known universe sucks donkey balls, the entire software world could be seen as one enormous version of the Streisand effect.



  • @wft said in So I tried Go the other day:

    Okay, I get it: global variables are bad. Why, however, make them impossible to have at all? My program has maybe 5 functions total, including main. Why in the world should I make a separate package just to be able to have the five global variables I'm otherwise forced to pass around?

    I hate the "global variables are bad" meme. Global variables store global state. Global state is a thing that most programs, by necessity, have. Yes, state should always be as contained as it can be, but that doesn't mean you can't have program-wide state. And any way of "hiding" it makes things worse.


  • Banned

    @pie_flavor said in So I tried Go the other day:

    code with a minimum of boilerplate

    xD

    the availability of global variables

    Only with external libraries.


  • Banned

    @anonymous234 said in So I tried Go the other day:

    @wft said in So I tried Go the other day:

    Okay, I get it: global variables are bad. Why, however, make them impossible to have at all? My program has maybe 5 functions total, including main. Why in the world should I make a separate package just to be able to have the five global variables I'm otherwise forced to pass around?

    I hate the "global variables are bad" meme. Global variables store global state. Global state is a thing that most programs, by necessity, have. Yes, state should always be as contained as it can be, but that doesn't mean you can't have program-wide state. And any way of "hiding" it makes things worse.

    Disagree. Global variables mean hidden links between otherwise independent parts of code, sometimes completely unrelated parts. It makes it extremely hard to analyze exact data flow, and is one of the leading causes of software bugs. You cannot completely avoid global state - at the very least, you need the own process handle, and other only-ever-one-per-process data like standard input/output - but you absolutely can (mostly) contain it in one module, and through IoC and proper abstractions make the rest of code that it's actually shared global state - and it doesn't look bad at all! And when it turns out the singleton isn't actually single (it happens more often than you think), making relevant changes is MUCH less painful. Also, multithreading.


  • And then the murders began.

    @Gąska said in So I tried Go the other day:

    ... but you absolutely can (mostly) contain it in one module, and through IoT and proper abstractions make the rest of code that it's actually shared global state - and it doesn't look bad at all!

    Ah, so that's why I had to hook up a Raspberry Pi to my web server. 😉


  • Banned

    @Unperverted-Vixen fuck, wrong TLA.


  • Considered Harmful

    @pie_flavor And there's even left_pad!



  • @pie_flavor said in So I tried Go the other day:

    If you used Rust, you'd end up eliminating all of those gripes while still being able to achieve the same goal. Inheritable traits, code with a minimum of boilerplate, still encouraging composition over inheritance

    I think so now too. cargo seems a lot more mature at managing dependencies and builds. A question, though: can I compile on Fedora (which has glibc) and execute on Alpine (which has musl), or is there some compilation/linking mumbo jumbo to be done? Go binaries happily chug away, as long as the underlying kernel and CPU architecture are of the same type.

    @pie_flavor said in So I tried Go the other day:

    (assuming you're right about them being impossible in Go; I've got my doubts)

    I was wrong there. Apparently you can have global variables, but you must qualify them with a package name, so main.foo_var. Which for some reason is not necessary with functions within the same package, so hmm anyway.

    I like multiparadigm languages which might promote some paradigm or another over the rest, but make the rest easily accessible anyway. Go seems to actively punish you for not adhering to the Rob Pike's pet paradigms.


  • Considered Harmful

    @wft said in So I tried Go the other day:

    the Rob Pike

    that's The Rob Pike.



  • @antiquarian People complain about languages and the whole stacks, because at some point they require you to shave a yak or three before getting a straightforward task done. That is, the task is straightforward to you, and might be completely alien to the authors of said technology stack. This is what drives the progress forward.

    The authors might just embrace the idea that they might not be aware of all possible use cases, and take time to educate themselves and work with "complainers" to enable those use cases; or they might point out that while they don't have a monetary incentive and moral obligation to enable X for you, there's such and such way to make it easier; or they might claim that since they don't know about X or they don't do X, X doesn't exist or is not worth talking about — complete with a tantrum on top about how stupid you are to even think about X.

    I'm glad the people who actually advocate Go's way of handling errors are not in the business of making cars, or the drivers would need to inject fuel into the engine's cylinders manually with six provided levers; a failure to do it precisely enough would make the engine go out of order silently and then stop or explode on a motorway.



  • @Gribnit said in So I tried Go the other day:

    @wft said in So I tried Go the other day:

    the Rob Pike

    that's The Rob Pike.

    Then it should read "Go seems to actively punish you for not adhering to the The Rob Pike's pet paradigms."



  • @dkf said in So I tried Go the other day:

    @ben_lubar Looking at all that reinventing of exceptions and try…finally is painful.

    finally already exists in the form of defer someFunction().


  • Considered Harmful

    @wft said in So I tried Go the other day:

    @pie_flavor said in So I tried Go the other day:

    If you used Rust, you'd end up eliminating all of those gripes while still being able to achieve the same goal. Inheritable traits, code with a minimum of boilerplate, still encouraging composition over inheritance

    I think so now too. cargo seems a lot more mature at managing dependencies and builds. A question, though: can I compile on Fedora (which has glibc) and execute on Alpine (which has musl), or is there some compilation/linking mumbo jumbo to be done? Go binaries happily chug away, as long as the underlying kernel and CPU architecture are of the same type.

    I'm not very familiar with Linux or whether (and how) musl would be incompatible with glibc. I know that libc is dynamically linked in a Rust program, so that might(?) mean it'll all work. But, in the event that it doesn't, compilation and linking is absolutely not mumbo jumbo in Rust. You are likely building against x86_64-unknown-linux-gnu; you'd just switch the target to x86_64-unknown-linux-musl.


  • area_can



  • @anonymous234 said in So I tried Go the other day:

    I hate the "global variables are bad" meme. Global variables store global state. Global state is a thing that most programs, by necessity, have. Yes, state should always be as contained as it can be, but that doesn't mean you can't have program-wide state. And any way of "hiding" it makes things worse.

    I like injecting state whenever possible, but that gets harder and harder the further away from singleton services you get.

    I mean, has anyone tried injecting DateTime state, instead of relying on the implicit global? I did that here and there (mostly through duck-typing), and it's not easy. When I do manage it, it makes testing so much easier, though.



  • @wft said in So I tried Go the other day:

    Error handling got me flashbacks from the C days. Rob Pike might have a kind of a personal grudge towards proper exceptions, but making them nonexistent and forcing everyone into explicitly handling errors in every damn place they might occur is as stupid as it gets (I know there's panic and recover, but it's of no help if nothing in the standard library ever uses it).

    Until about 6 months ago I was maintaining a node.js codebase that relied exclusively on callbacks with the function (err, result) signature. So I was doing pretty much what Pike and his bunch would want go developers to do.

    In the new code-base, I use Promises. And I am NEVER going back. What took hours of careful orchestration and error juggling is effortless with promises.

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack. Their concerns have no place in memory managed languages.



  • @cartman82 said in So I tried Go the other day:

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack.

    I thought the main complaint against C++-style exceptions was their non-locality.


  • Discourse touched me in a no-no place

    @ben_lubar said in So I tried Go the other day:

    @dkf said in So I tried Go the other day:

    @ben_lubar Looking at all that reinventing of exceptions and try…finally is painful.

    finally already exists in the form of defer someFunction().

    I didn't grasp what the nature of the conditions under which a deferred callback is run really is. Is it scoped to anything less than a function? Can it be cancelled?

    Use case: I'm trying to think how a database transaction would be handled; mechanisms to scope those to a particular section of code with success-exits committing the transaction and erroring-exits automatically triggering rolling back are superb for ensuring that data access semantics are correct, and are hugely simpler than doing it by hand. In truly sensible languages, I can do this by just giving a block to something (that depends on the language) that says “I'm scoping a transaction to this block”, and you can simulate it with various techniques in other languages (I've got utility code for Java that makes this fairly easy even without a framework like Spring; there's still little syntactic overhead). The more code it takes at each use, the more likely programmers will get this wrong.


  • Discourse touched me in a no-no place

    @MZH said in So I tried Go the other day:

    @cartman82 said in So I tried Go the other day:

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack.

    I thought the main complaint against C++-style exceptions was their non-locality.

    Mostly because of the challenges of getting the memory management right. With garbage collection, those objections are mainly moot.


  • 🚽 Regular

    @cartman82 said in So I tried Go the other day:

    In the new code-base, I use Promises. And I am NEVER going back.

    Promise?

    What took hours of careful orchestration and error juggling is effortless with promises.

    I wish you good luck with stack traces and never forgetting .catchs and returns.


  • BINNED

    @dkf said in So I tried Go the other day:

    @MZH said in So I tried Go the other day:

    @cartman82 said in So I tried Go the other day:

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack.

    I thought the main complaint against C++-style exceptions was their non-locality.

    Mostly because of the challenges of getting the memory management right. With garbage collection, those objections are mainly moot.

    ❓

    And C++ has had RAII from the beginning...


  • Banned

    @cartman82 said in So I tried Go the other day:

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack. Their concerns have no place in memory managed languages.

    The problem isn't non-local error handling. The problem is not being able to tell which functions throw exceptions and which don't.


  • kills Dumbledore

    @Gąska said in So I tried Go the other day:

    @cartman82 said in So I tried Go the other day:

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack. Their concerns have no place in memory managed languages.

    The problem isn't non-local error handling. The problem is not being able to tell which functions throw exceptions and which don't.

    So Java is the perfect language?


  • Banned

    @Jaloopa it certainly has better exceptions model than C#.

    Hey, look. A language can do one thing right and still completely suck. Just look at C++!


  • Notification Spam Recipient

    @Gąska said in So I tried Go the other day:

    @Jaloopa it certainly has better exceptions model than C#.

    No.


  • Discourse touched me in a no-no place

    @topspin said in So I tried Go the other day:

    And C++ has had RAII from the beginning...

    The mechanisms to support it, yes (or probably; how “beginning” is beginning after all?), but the understanding of it as a pattern wasn't so widespread to start with. Yet that's not the same as what you need with exception objects themselves as those typically cross many scope boundaries, making handling them a touch trickier. When there's a guaranteed GC about, those concerns are much more moot: the object appears, conveys the exception information from its creation point to where it is consumed, and then goes away gracefully when the runtime determines it is safe and advisable to remove it.


  • Discourse touched me in a no-no place

    @MrL @Gąska I find it amusing how the adherents of the two languages will use the same evidence as proof of opposing philosophical positions. 😆


  • Banned

    @dkf the never ending war between "I want my code to run correctly" and "I'm a lazy fuck".


  • Notification Spam Recipient

    @Gąska said in So I tried Go the other day:

    @dkf the never ending war between "I want my code to run correctly" and "I'm a lazy fuck".

    I attained armistice. My code runs correctly. There's just not much of it.


  • Discourse touched me in a no-no place

    @MrL said in So I tried Go the other day:

    My code runs correctly.

    So far as you can tell anyway… 🏆



  • @MZH said in So I tried Go the other day:

    I thought the main complaint against C++-style exceptions was their non-locality.

    What I meant was, people who had to deal with exceptions in C/C++ go to design their new memory-managed language and are now ideologically opposed to exceptions, even though a lot of their issues go away when you don't have to worry about releasing memory.

    Mostly because of the challenges of getting the memory management right. With garbage collection, those objections are mainly moot.

    ^ exactly.



  • @dkf said in So I tried Go the other day:

    Use case: I'm trying to think how a database transaction would be handled; mechanisms to scope those to a particular section of code with success-exits committing the transaction and erroring-exits automatically triggering rolling back are superb for ensuring that data access semantics are correct, and are hugely simpler than doing it by hand. In truly sensible languages, I can do this by just giving a block to something (that depends on the language) that says “I'm scoping a transaction to this block”, and you can simulate it with various techniques in other languages (I've got utility code for Java that makes this fairly easy even without a framework like Spring; there's still little syntactic overhead). The more code it takes at each use, the more likely programmers will get this wrong.

    I am doing this with a Promise in javascript and it works great.



  • @Zecc said in So I tried Go the other day:

    What took hours of careful orchestration and error juggling is effortless with promises.

    I wish you good luck with stack traces and never forgetting .catchs and returns.

    One general catch on the request level. All errors roll back to that. If I want custom error, I can add intermediate catches and throws, but those are nice-to-haves, not show stoppers.

    Background processes (not tied to requests) must be caught manually, but if I fail to do so, the application crashes and I fix it.

    Stack traces can be a bit iffy, but I have utilities that extend them at crucial junctions (eg. going to the database, web, hard drive, etc.), so it's generally not a huge issue.



  • @topspin said in So I tried Go the other day:

    And C++ has had RAII from the beginning...

    That's basically adding a lot of bureaucracy to get what memory managed language does out of the box. I can understand why a lot of C gurus are boycotting the pattern.



  • @Gąska said in So I tried Go the other day:

    Whoever thought non-local error handling is problematic has smoked too much C/C++ crack. Their concerns have no place in memory managed languages.

    The problem isn't non-local error handling. The problem is not being able to tell which functions throw exceptions and which don't.

    I never found that to be a problem. If I care about a certain type of error, I figure out what to expect and catch it. Otherwise, I let it bubble to the general error handler at the app or request level.

    Figuring out what errors to expect can be an issue, forcing me to dig through the library source code or docs. But it's exactly the same type of problem with callback/return style error; you still need to figure out which error codes are possible and what to handle and what to pass through.

    In fact, Java-style exceptions are the only construct that tries to address that issue. And those are a bit too verbose for most real world use cases and are shunned even by exception advocates, so...



  • @cartman82 won't deny that RAII was a bit broken before C++11, which caused a lot of issues. But the "bureaucracy" added nowadays is "write auto foo = std::make_unique<Foo>(); instead of Foo* foo = new Foo();".

    In exchange, you never have to write a "using" or "finally" clause to remember not to leak every other kind of resource. Never quite understood why people that like automatic management of memory like manual management of everything else.


Log in to reply