Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The thing with Go, is that it is disappointing what Google is capable of in terms of language design versus what Apple and Microsoft have done in this field.

Sure there were languages with such type systems before, and we managed to deliver our work with them.

However I don't want to work in 2017 as I used to work in the mid-90's, when templates were an experimental feature in C++, or the only MLs we knew were Caml Light, Miranda and SML.

The world has moved on.



> is that it is disappointing what Google is capable of

Man, how long will this meme survive? Go only initially originated with some Google developers, it's not in any way "Google's answer to Apple's and Microsoft's strategically-important and accordingly-subsidized-and-evangelized-and-invested-in languages". Just picture a handful of (previously "accomplished" in the field, as it turns out though) guys thinking "this company has a wide mess of Python etc scripts that should really be C programs, except for the problems this would pose"..


Those developers are being paid by Google and their actions within this context relate to the public image of their employer.

If Google wouldn't agree with their actions, or did not pay to increase the team size, they would be developing the language outside Google walls.


You may disagree but Google relationship with Go looks lot more distant as compared to C#-MS, Java-Oracle, Swift-Apple. Here Dart-Google looks more appropriate. Those Dart people always keep telling us about Adword's usage of it. Google organizes Dart's conferences whereas for GopherCon doesn't even have Google as sponsor.

Go looks far more independent from Google in branding, sponsorship and references from official Google products.


That being said Go is one of the four recomended language in google : java, c++, python and go.


Especially because Go is in most ways less powerful than Java – a native compiler for Java would have been more useful than this.


What do you mean by "powerful"? How is a language powerful? Or not?


From Paul Graham, and one of the best essays on the subject ever written: http://www.paulgraham.com/avg.html

As long as our hypothetical Blub programmer is looking down the power continuum, he knows he's looking down. Languages less powerful than Blub are obviously less powerful, because they're missing some feature he's used to. But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn't realize he's looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub.

When we switch to the point of view of a programmer using any of the languages higher up the power continuum, however, we find that he in turn looks down upon Blub. How can you get anything done in Blub? It doesn't even have y.

By induction, the only programmers in a position to see all the differences in power between the various languages are those who understand the most powerful one. (This is probably what Eric Raymond meant about Lisp making you a better programmer.) You can't trust the opinions of the others, because of the Blub paradox: they're satisfied with whatever language they happen to use, because it dictates the way they think about programs.


So when you say a language is "powerful" you are talking about its level of abstraction? Because then we should probably try to call it something else so as not to confuse "power" for technical ability to deliver performance or productivity.


Definitely, the measurement of how "powerful" a language is directly corresponding to its level of abstraction.

It does not necessarily mean that any dev can code faster – or even similarily fast. But it means that much of refactoring usually is easier (as you’ll have less duplicated code), that you get more guarantees, that you have less boilerplate, etc.


Then I'm not sure if "powerful" is necessarily what I look for in a language.

I have three priorities when programming:

  1. Correct
  2. Understandable
  3. Fast
Priority 1 is non-negotiable (code should be correct, or the rest is moot). Priority 2 is negotiable in situations where priority 3 isn't, however I've had this happen perhaps a handful of times in the last 25 years.

Being able to produce code quickly is nice, but unimportant if the code isn't likely to be correct, understandable or fast. Productivity in production code is measured in how you achieve the above.

Likewise it is nice to have code that is easy to refactor and doesn't require duplication, but duplication is more permissible than the dogmatic avoidance of duplication when it is detrimental to understanding or speed. It can also lead to unnecessarily bothersome abstraction or spending too much time creating abstraction where the domain doesn't naturally lend itself to abstraction.

(Note that points 2 and 1 tend to dictate that duplication should be avoided: it isn't about the typing saved, it is about correctness.)

Priority 3 could be elaborated as "quick response times and avoidance of unnecessary resource use". Any idiot can write code that does X. A craftsperson writes code that does X well. A valuable craftsperson can do X well and quickly. Be a craftsperson.

For rapid prototyping you can throw the rules slightly overboard, but when you write production code things count.

Abstractions and language mechanisms that can give you static guarantees are good when they help you achieve the above. They are counter-productive when they conflict with any of the above. It is easy to become counter-productive when you try to satisfy some dogma.


I mean that you will need to write more, and more duplicate code, to express the same, it’ll be less clear, and less safe.

Generics, and annotation processing with code generation integrated in the compiler, are two example features supported by Java that improve this.

Haskell obviously is a lot better even.

Additionally, it’s also a question if, in the language, any state of the program is immediately obvious from the code – or if the syntax hides things (such as Go’s multi-return errors vs. Java’s exceptions, although Java could use an "ignore" keyword to ignore any error happening in a block or statement)

A powerful static type system can express everything a dynamic type system can, and more. (That’s why I tend to err towards static typing)


Very little people who have tried errors by value or Either monads (they are basically the same concept in some sense) think that exceptions are better. Exceptions cause your code to be non-linear. Also, it makes them seem like something exceptional (pun intended), whereas you should really carefully handle each error and decide what it implies.

Also, just something I noticed after almost two years of Go. Thanks to library quality I usually end up writing much less Go than Java/Scala for similar applications.


I think Go has made a lot of people re-think their assumptions about what makes a language a good language.

I have yet to figure out precisely what it is that makes me more productive in Go (which I have relatively little experience with) than Java (which I've programmed since the first beta).


Make sure to write some blog post about it when you do! I'd be very curious to hear what it is.


At least one thing I can say right away is that they have taken care of a lot of small hygiene factors. Things like the rapid compiler, the "go" command that has a lot of nice things built in, the way they did away with formatting discussions (although I can't articulate how it differs from other languages that try to do the same....probably the tooling).

The Go community also prefers libraries over frameworks. Coming from Java, and its humongous, cancerous framworks, that's a BIG selling point. I notice that when someone posts a link to a "Go framework" I get slightly ticked off and I feel resistance even before I've clicked the link.

As for the language: I don't know yet. It just works for me. :)


Go does not have Either monads, or real errors by value. It has a multi-assignment syntax similar to tuple return, but nothing else.

For Java, with a tiny library, you can have real Either monads: https://github.com/spencerwi/Either.java

I use them in lots of code.

For Go, you end up with an assignment syntax where you have to manually check, and get no compiler safety. At all.


You do have errors by value. You return for example two values, the response and error.

What do you mean with no compiler safety exactly?


I mean that the compiler does not check if I’m handling the error. I can easily just ignore the error and work with the value, and therefore have code that breaks if the value might not be there.

Any code that compiles should not be able to ever segfault or have NullPointerExceptions or similar.


Well, I never had segfaults.

Anyways, it's true, I miss pattern matching on errors.

However, in practice, you just get used to it. I haven't had a situation in the past half year where I'd forget to handle the error / check it.


> However, in practice, you just get used to it. I haven't had a situation in the past half year where I'd forget to handle the error / check it.

But with the same argument, you could as well use PHP7.

And this still doesn’t allow you to replace all stdlib datatypes with your own implementations without using custom precompilers.


Excuse me, what do you mean by 'replace all stdlib datatypes with your own implementations'. Why would I do that?


To interface via an FFI with a game engine, which uses a custom allocator, and you need to pass datatypes between it and your own code?

(As I’ve done in Java!)

To replace existing implementations with your own, because you want a LinkedArrayList (a linked list of blocks)? Or because you want a TreeMap instead of a HashMap, or a Set with different implementation?

Because you want to implement your own Either type to better handle return values (see https://github.com/spencerwi/Either.java )?


This is an interesting point actually. Because it gets raised every time and I actually thought the same before starting with Go.

Thing is, in practice you usually don't need special generic containers. And when I actually need it, I'll just code up a non-generic implementation. When I need a complex type system I'll use Scala.


Well, I use them a lot – I’ve written lots and lots of generic code in my projects, and reuse it across many dozens of projects.

This allows me to have fully reactive collections in Java, lazy reactive collections, and more.

I can just connect to a socket transmitting updates with netty, write a transformer, apply those to a lazy reactive collection, and have the changes directly appear in the list in the UI, fully threadsafe.

Writing those things again, and again, every time, would be far more work, and increase the time I need to write code massively.

I’ve actually used go a bit, and tried reimplementing several of my projects in go, but either it wasn’t easily possible, or I had to translate dozens of generic classes into hundreds of non-generic versions, with lots of duplicated code.

And then I had found a bug, fixed it at one point, and had to copy it to hundreds of files.


I'd love to take a look at your codebase if it's hosted on github (or something comparable).


Currently not, as I only used it in smaller projects in the past.

In the future I’ll use it likely with QuasselDroid-NG, an app of mine that’s very early in development, and for which I developed it.

The use case there is that we have a list of IRC messages, constantly updating and adding messages at any point of the list, and we want to update the UI and animate.

The client can also cache, or preload, messages at any point, or throw them away.

Additionally, users can filter, search, or choose to disable some messages.

Other messages might get merged, or synthetic ones inserted.

So I have a backing store of messages that can constantly change, I have on top of that a stream of transformations taking part, and on top of that an interface presenting a single, consistent Java List, but also triggering the relevant updates on Android’s recyclerview.

Most importantly, you can just add a message to the lowest list, it will be properly filtered, transformed, animated, and displayed, and this properly threadsafe across UI thread, backend thread, and filtering threadpool, while being faster than the solutions Realms and co provide for such updated UI.


I'm not sure if I understand, are you actually using Go for your UI backing or using it as a backend for your application?


The application described above is Java. Runs on Android and desktop Java with JavaFX.

I tried to reimplement the desktop version with Go, due to native UI bindings. And failed.


Well, I don't see any problems with the logic part. Receiving, filtering, transforming, and notifying someone else about incoming messages (would probably do it in a few threads, sending messages between each other).

For the UI part: no wonder, Go, at least currently, is useless for UI's.


> (would probably do it in a few threads, sending messages between each other).

The problem is that I try to abstract these things away – in Java, I have a general framework, and just do

    var c = new ObservableCollection<Message>();
    var f = new AsyncObservableFilter<Message>();
    f.setSource(c);
    f.addFilter(new DayChangeMessageFilter());
    f.addFilter(new CollapseJoinLeaveMessageFilter());
    f.addFilter(new RemoveIgnoredMessagesFilter());
    var adapter = new ObservableAdapter<Message, MessageViewHolder>();
    adapter.setCollection(f.getResultCollection());
and then I can do

    c.add(new Message(new Date(), "cube2222", "Well, I don't see any problems with the logic part."));
And this works for any type – I can use the same code for observable collections of IRC networks, of channels, etc. And I do use them for that. And if I change the filters, it also does the minimum amount of work necessary to update the list, and not a single CPU cycle more.

I’m using it with over 11 different types in the Java version, and I’d have to maintain 11 identical, but with different types, versions in the Go version.

You can understand how much of a pain in the ass this is.

Oh, btw, this also abstracts away the entire thread handling, while still doing it in a reasonable way.

And the backing collection doesn’t have to be a normal ObservableCollection storing data in memory – I also have ones using SQLite as backend, or caches, and I have the ability to add listeners for scrolling up or down to load or unload data as well, if it’s not needed anymore.

In Go, I’d manually have to reify all these, and if I find a bug in one, I’d have to update all of the others, too.


Of course I can't say for 100% as I don't know your codebase. But I think you could easily do this with Message being an interface defining the common functionality of your messages (like, probably, render(), timestamp(), id()). Then you could just have you DayChangeFilter use the timestamp, joinleave do a type assertion, removeignored check for the id.

If the genericism for you is also abstracting away the source of the messages -> in Go you just usually abstract sources as io.Readers.

All filters can easily be an intermediate channel which only sends further proper messages. Or just write a filter(func (m Message) bool) function which abstracts that away.

Though I understand you may want to use your Reactive collections and streams, this isn't really a case for Go.

Have I understood your use-case correctly?


See, the problem is that "message" is only used in this one place.

In another place, I use there a type such as network, and the filters are entirely different ones.

In yet another place, I use even other types.

The types used there have nothing in common, nor do the filters.


> Generics, and annotation processing with code generation integrated in the compiler, are two example features supported by Java that improve this.

I think it is fair to point out that generics were not part of the first Java spec. They were added in version 5, see [1].

[1] https://en.wikipedia.org/wiki/Generics_in_Java


Of course not. Early Java was comparable to today’s Go in many ways, and Generics is part of that.




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

Search: