Hacker News new | ask | show | jobs
by scriptkiddy 3310 days ago
> I mean, what's the better alternative to Go for this work? Maybe Rust? It is, at least more controllable at a lower level...but, not as easy to pick up for people coming from a C/Python/Perl/Ruby systems and ops background.

You know, it's interesting. I've been programming with Python for about 6 years now. I've also picked up Javascript, SQL, bash, and PHP along the way. I'm always gaining a little bit of C knowledge here and there when writing C extensions for my Python applications. I'm a fairly experienced programmer at this point. To the point:

I tried picking up Go one day because I was hearing so much about how it could replace Python as network glue code with better performance and reliable concurrency. I can't really validate or invalidate those claims. That said, I found Go to be sort of difficult. The syntax is really simple. Compiling is really simple. Concurrency is even simple. However, need to do something in a different way than Go decides is correct? Well, you can't. It won't even compile. The difficulty in Go is in learning about what the compiler thinks is OK. I don't really like that. You don't really know if your code will work until you compile. Basically, I just think Go isn't really flexible enough for modern programming. I find that Nim can do Go's job better than Go can for my use cases anyways.

5 comments

> The difficulty in Go is in learning about what the compiler thinks is OK.

I think this is similar to what people think about the type system in Haskell or the borrow checker in Rust. With every higher level language comes new things to learn and obey.

But with Rust once you learn to work with the borrow checker you can work at any level of abstraction. With go you get what the Go implementors decided was best for you. (I omit Haskell because I don't know it)

I want to mix C++11/14 into that also. Now that the typesystem is used by the standard library to describe resource ownership in code whole categories of errors can be found at compile time. If you are new this it can seem like you are fighting the compiler, but once you learn that the compiler just won't let you make certain kinds of mistakes you get access to every level of abstraction with C++11/14 and Rust. You can code in terms of passing database bindings betweens threads in threadpools or you can twiddle individual bits in specific registers and everything in between.

I don't know Go well, but it seems really limited. You can't write certain classes of bugs, but you also can't write many design patterns.

I have experience with Rust and Go as well as a dozen or so other languages. Go usually has one or more easy ways to solve a problem, and in my experience, these easy paths are usually much easier than in other languages. There are certain problems for which this isn't true (like the one documented here), but it's generally true. These easy paths are often not elegant, and sometimes they trade a 1% risk of type error for a 60% easier solution. They may also trade a small amount of performance for a large boost to usability.

Whether or not I choose Go is almost always comes down to whether I want to solve a problem quickly and with decent performance/readability/etc or if I want to take a lot longer for a solution that is more aesthetically pleasing or with a smaller risk of error.

I'm sure lots of people will argue that their language is faster to develop in, but apart from toy programs or those requiring libraries unavailable in Go, this has never been my experience. In particular, even after two years with Rust, I still have trouble reasoning around memory management, lifetimes, how to pass around functions, how to do anything asynchronously, etc. Go isn't perfect for anything, but it strikes a good balance for the kind of work I tend to do.

YMMV.

> I don't know Go well, but it seems really limited.

That was my experience, too. Vaguely interesting in a couple of ways, but definitely a bondage and discipline language and nowhere near compelling enough to make me want to put up with that.

> You don't really know if your code will work until you compile.

This is true in every text-based programming language. s/compile/execute/ for interpreted or repl-based languages.

Even then you don't know if program is correct. There have been pieces of software running in production for 20 or 30 only to fail because of some unforeseen and planned for error condition.

My favorite was the Comair christmas failure back in 2004 or 2005. I tried googling the root cause, but I think it was an Integer overflow in the 16 bit integer they used for storing the flight number. The system was designed in the mid 80s and 65535 flights was an insane amount, but but when the software failed on Christmas it interupted more than 1,100 flights.

I am curious why people are downvoting me. It seems obvious to me to that proving software is correct is hard or impossible. It building and passing the tests help to increase confidence in correctness, but doesn't prove it.

No one disagreed with this comment and it is one of the least controversial thing I have said on HN. I think I have a downvote fairy, someone who just downvotes everything I say. If so, why bother? If I don't have one then when you downvoted me, why didn't you respond?

This too is true in every programming language.
I disagree. For instance, if I'm writing something in C and I know that it is syntactically and semantically correct, I know that it will definitely compile.

Go hijacks control flow and makes it more difficult to reason about how your code will be compiled and executed. At least that is true in my personal experience.

Sorry, I don't understand what you mean by "Go hijacks control flow". Could you elaborate cases, where Go did not behave as you expected? And where syntactic and semantic correct Go code did not compile?
So, keep in mind that my experience with Go is not at a professional level. Take this example:

https://gobyexample.com/channel-buffering

As far as my understanding is concerned, channels are a way for goroutines to pass data between one another, correct? Yet in this particular case, the channel `messages` is operating in the same manner as a generator or array. So, am I creating goroutines by passing messages to the channel or am I just using the channel as a simple buffer?

This example helps as well: https://gobyexample.com/channel-directions

Am I implicitly creating goroutines by using channels or am I simply creating a buffer?

Sorry I don't have any of my own code to share as I deleted all of my Go practice stuff.

Channels are a safe way for goroutines to communicate. Safe here means, that the channel itself performs all the necessary locking needed for any number of goroutines to read or write "at the same time" to and from the channel. Other than that it does behave like a plain pipe. You write into it and can read from it "on the other side". Creating a channel does not create a goroutine. A goroutine is only created if you use the "go" command, like "go f(42)". This would run the evaluation of f(42) in a separate goroutine, which behaves like a thread, but uses less resources. So in neither of your examples, goroutines are created. You can optionally add buffering to the channel. A write to a channel without a buffer blocks, until the value you write to the channel is read. If you have buffers, you can fill them without blocking, even if the values are not consumed immediately. Without the buffer, the first example would get stuck, as the first write to "messages" would block until there is a read on that channel - which is never performed. But due to the buffering, the two writes to "messages" are performed without blocking, and the values can be read after that. A third read on the then empty channel would also block infinitely.

The flow of data through channels can be confusing until the concept becomes familiar, but the behavior is well-defined, so the behavior is as easy or difficult to predict as of any program of the given complexity.

It really just seems like you're saying "When I think my Go code is correct, it turns out it often isn't, but when I think my ${other_programming_language_i_know_better} code is correct, it turns out it usually is.
When I read about channels and various forms of IPC/inter-thread communication in most other languages, and remember the past pain of threads and mutexes in C/C++, I am so happy to be able to send a message in Erlang to another Erlang process (Pid) as easily as this:

    Pid ! {self(), 42}
And in the process identified by Pid, to receive the message:

    receive
        {From, Data} when is_pid(From) ->
            handle_data(From, Data)
    end
And beyond that, the process identified by Pid can be running on a physically separate host system - it's transparent.

Too bad we can't use Erlang for systems programming, but you can't have everything!

>Am I implicitly creating goroutines by using channels or am I simply creating a buffer?

A channel is just a thread-safe queue. An unbuffered channel blocks until something else receives the sent value. A buffered channel allows n sends until it blocks. Using a channel will never create a new goroutine, its just a way send data. You can use a select statment to wait on sending or reciving from multiple channels or to send or get without being blocked by a full or empty channel.

In C you could put together a RW mutex, condition and a linked list or array and have the same thing pretty much.... If you want to create a goroutine you need to invoke "go X".

Out of curiosity, do you know C/C++ or Java?

If you write a syntactically and semantically correct go program it will compile. Can you give an example?
Please see my reply to __ph__.
Yes but the problem with languages like Nim is lack of support and maturity. Go is more versatile and at the same time more mature than anything out there. It is a different design and it excels in what it does (considering all tradeoffs now).

Will Nim be as versatile and solid as Go in the future? Hard to predict but i would say no. You need a solid financial backing and certain amount of adoption where people actually write software that makes them money.

> Yes but the problem with languages like Nim is lack of support and maturity.

Agreed, that's why I don't use it for anything super important yet. Nim is approaching a 1.0 release soon. Go has a similar problem in that it is maintained almost entirely by Google who has a history of dropping projects without warning.

> Go is more versatile and at the same time more mature than anything out there.

This is objectively incorrect. In fact, Go aims precisely to be non-versatile for the sake of simplicity. That is why Go does not have generics for instance.

> It is a different design and it excels in what it does (considering all tradeoffs now)

I don't think it's design is all that different. It looks like a stripped down version of C and it's definitely not the first PL focused on concurrency.

> Will Nim be as versatile and solid as Go in the future?

Nim is already leagues above Go in the versatility(I assume you mean flexibility?) department. As far Nim being as "solid" as Go, I'm not entirely sure what you mean. If you're asking about stability, I believe that Nim can reach a similar level of stability as Go, yes.

> You need a solid financial backing and certain amount of adoption where people actually write software that makes them money.

I agree with this. However, it's not always a quick process. The only reason Go is as popular as it is is because of Google's size and reputation(edited). Every programmer on Earth heard of Go within a few days of it's official release. Nim is taking a slow roll approach. Look at Python. It took almost 15 years before it started getting really popular.

All that said, I didn't come into this thread to argue about Go vs Nim. I've been accused of shilling Nim in the past. I'm sorry that I like talking about PLs I enjoy using.

It's more than fine to be enthusiastic about programming languages. However, some of your points about Go are dubious.

The reasons Go doesn't (yet) have generics are practical rather than philosophical. And well-documented.

I also don't believe Google's marketing budget contributed much if anything to supporting Go. The _reputation_ of Google and the Go authors was far more important. (Personally, when I saw people like Brad Fitzpatrick try Go and rave about it making programming fun again, I decided to try it.)

You can happily accuse me of shilling Go if you like :-)

No, I encourage you to shill in fact.

> The reasons Go doesn't (yet) have generics are practical rather than philosophical. And well-documented.

Can you give an example? I guess I fail to understand why a statically typed language would choose to forgo all of the advantages generics provide. Does it have something to do with Goroutines?

> I also don't believe Google's marketing budget contributed much if anything to supporting Go.

I didn't necessarily mean their marketing budget. I should probably edit that. I meant that anything they do is news.

> Can you give an example? I guess I fail to understand why a statically typed language would choose to forgo all of the advantages generics provide. Does it have something to do with Goroutines?

Like I said, the objections are practical, not philosophical:

They published four past design docs for generics in Go that simply didn't pass technical muster (https://github.com/golang/proposal/blob/master/design/15292-...)

Also, rsc stated he plans to understand generics better in 2017: https://research.swtch.com/go2017#generics

Also, bradfitz said recently on the GoTimeFM podcast that doing Generics and Go2 together makes sense.

> I didn't necessarily mean their marketing budget. I should probably edit that. I meant that anything they do is news.

I feel like the comments from others about Dart give the lie to this one. Go is fantastically, dramatically, massively more popular than Dart, which is also from Google.

> Like I said, the objections are practical, not philosophical

Russ Cox and Rob Pike keep repeating this mantra, but I don't buy it. No, I don't believe they object the idea of generics itself. And yes, generics pose practical complexities and a plethora of issues that have to be resolved.

But so does every other language feature. The features you choose to add reflect your philosophical values and priorities.

Go chose to bake some hitherto very niche features that could have been as libraries into the language. Channels in particular, are a language construct only because Go doesn't allow operator overloading and generics for user types. But channels get them, because channels are demonstratively important for Rob Pike[1].

There's nothing wrong with that of course, but that's a philosophical decision. Why channels can avoid the vagaries of interface{} boxing, but not sets, linked lists or queues?

The reality is that every modern statically typed language except Go has generics, and they all implemented them very well. The ML languages and Ada were already doing it in the 80s, and OCaml and Eiffel managed to combine generics and polymorphism back in the 90s.

It seems to me that when originally designing Go, Pike, Griesemer and Thompson just didn't think generics are worthwhile enough for the effort it takes to properly research them.

When Go was started, its authors mostly looked to languages which implemented generics later in their lifecycle (namely Java and C++) and their implementations suffered from problems due to other, rather obvious, design defects: https://research.swtch.com/generic

I'm happy to see that this attitude is changing, and other languages are looked at.

[1] https://swtch.com/~rsc/thread/

> The only reason Go is as popular as it is is because of Google's marketing budget. Every programmer on Earth heard of Go within a few days of it's official release.

I think Google put lot of marketing budget for Dart. But I don't see it ever comes in discussion regarding popularity or lack of it.

It is fine a lot of people do not like Go but claiming its popular just because of Google seems baseless.

Well, Go is obviously not a bad language. That said, I do think that it's adoption was primarily fueled by Google's popularity. Imagine go being released by a single person or small group of people. How would people have heard about it?
I think this isn't quite true. From my perspective, Go did get a massive boost but not from Google. The language was originally designed by Robert Griesemer, Rob Pike, and Ken Thompson.

It is fair to say that without those names attached I would have likely passed it by. Google is boring, but those three names, for me at least, I had to take a look.

If Google could make a language popular, where does Dart fit into the story? People seem to love Go, and with very little encouragement from Google. I don't see a lot of love for Dart...though everyone who's played with it seems to like it well enough.
Someone said this and it feels correct: it is not a bad language, but it is also not a good language.

> Google & adoption

I think it helped get around the initial cycle of drawing in the curious. An argument counter to claims regarding the importance of the people involved would point out Plan9 etc. that are hardly widely known, much less adopted.

In sum, I think the role of Google in one becoming a Go programmer depends entirely on when it happened. Today, of course Go has its own brand name. 8 years ago, it was Google that eased the debutante phase of the language.

No it is absolutely fine to be enthusiastic about PLs. I enjoy reading about production ready Nim or Crystal apps :-)
Glad to hear it. Crystal is another language I've been getting more and more curious about lately.
> Go is more versatile and at the same time more mature than anything out there.

This doesn't seem like a very credible statement on the face of it. Is Go more mature and more versatile than Python? Than Java? Than...Scala? Go does seem to share a lot of use cases (and limitations) with Java; and it would be hard to call it more mature.

> the problem with languages like Nim is lack of support and maturity

It was the same for Linux, Python, Ruby. Being community-driven can be a bug or a feature.

> Go is more versatile

Nim has macros, templates, overloading and compiles to C, JS, Objective-C. Runs on more architectures than Go including arduino microcontrollers.

> mature than anything out there

Go is not more mature than C, C++, Java, Python, Perl...

> You need a solid financial backing

See Linux, Python, Ruby... many projects had no big company or funding behind them.

> You know, it's interesting. I've been programming with Python for about 6 years now. I've also picked up Javascript, SQL, bash, and PHP along the way. ... However, need to do something in a different way than Go decides is correct? Well, you can't. ...

Pardon me and no offense, but it sounds like you are hitting the 'statically typed language' boundary.. all of the others you mention are fairly loose and dynamic. Go & C, not so much. It sounds like your use of C has been library code, which presumably is more 'data processing' oriented and so doesn't require much structure or control of process/runtime/etc.. which is where you will run into this stuff on the c side..

This is why I moved from c/c++ into dynamic languages to start with.. that said, as I grow more sophisticated and can 'deal' with the typing/lower 'machine' level control, the more I can understand other tools.. even C++! ..

i mention this because each layer of abstraction is there for a reason.. best to view with a fresh pair of eyes imho

>You don't really know if your code will work until you compile.

You are supposed to "compile on save".

I usually do this, but sometimes I'm writing a really long function or something and I want to save part way through so I don't lose my progress from some unlikely, yet catastrophic, failure.