Hacker News new | past | comments | ask | show | jobs | submit login

I like Go quite a lot. Mainly I am a Lisp programmer, so I am not looking for the next most high level programming language. I am looking for a language which gets things done, where Lisp doesn't quite fit. For jobs, which traditionally would have been done in C. Programs that run fast and have a reasonable complexity. It brings back the virtues of the Wirth computer language family back into modern times, as with strict type checking and the module system. On top of that it adds memory safetey due to the presence of GC.

Go it easy to learn, as its a moderately sized language, but it has just enough abstractions, that your programs are not held back by the lack of those, without opening the traps too "powerful" languages bring with themselves, namely complexety.

On top of all, the whole infrastructure is very well thought out and a pleasure to use. A very fast compiler which produces static executables, a good module system without header files, a rich standard library, many things. There are quite a few quirks, especially for the beginner, but the more I gain insight, the more I agree with the choices made - with some I don't, but the agree to disagree ratio is surprisingly high. And most of them don't get into the way of writing good programs, which is what counts.




> It brings back the virtues of the Wirth computer language family back into modern times, as with strict type checking and the module system. On top of that it adds memory safetey due to the presence of GC.

Wirth's work also includes languages with GC. :)


And more modern features than Go, even if designed in the 90s...


Out of genuine interest: could you elaborate on those? I have mainly worked with Pascal/Modula-2, and only shortly glanced at Oberon, so I am a bit shaky on his "later works".


I don't have much time to explain them in detail now, but can quickly provide some links:

Check Active Oberon:

http://www.ocp.inf.ethz.ch/wiki/Documentation/Language

Component Pascal is a Oberon-2 derivative but Wirth hasn't collaborated much there:

http://www.oberon.ch/blackbox.html

They made the very last version available for free. It was a kind of Delphi like, with the Oberon ideas of full stack OS.

www.pas.rochester.edu/~skulski/Presentations/BB_Class.pdf


This post is yet another reinforcement of my assertion that the people who like Go only like it because they have no idea what has happened in programming languages for the last few decades. Case in point:

> It brings back the virtues of the Wirth computer language family back into modern times, as with strict type checking and the module system.

Strict type checking? Have you used any other languages besides C? Go's type system is a joke.

Like literally, it's a joke. If you get a bunch of people who know about types languages in a room discussing types, "What about Go?" is guaranteed to get a laugh.


Sorry, your posting is unnecessarily abrasive. I am well aware about more advanced type systems. I have never claimed that Go has the most advanced type system. But indeed, compared to C/C++ which still are the most commonly used languages in industry, it has a strict type system. It could possibly have a more advanced one, but strict it is. And it gets work done.


> Sorry, your posting is unnecessarily abrasive.

Go is a much bigger problem in our industry than the tone of my post.

> I have never claimed that Go has the most advanced type system.

You claimed it had "strict type checking", when it has the least strict type system of any statically-typed language in common usage except C.

> But indeed, compared to C/C++ which still are the most commonly used languages in industry, it has a strict type system.

With template types, you can definitely get more strict type-checking out of C++ than out of Go.

So basically, Go has a more modern type system than C. And that's arguably not true. None of which disproves what I said: I said, "people who like Go only like it because they have no idea what has happened in programming languages for the last few decades."

> And it gets work done.

You can make that claim about any language. The question is, does it get work done as efficiently as other languages? And the answer is pretty clearly no.


Maybe if by "people who know about types languages" you mean "Haskell snobs"


But also ML, Scala, C++, C#, Java, TypeScript, Hack, Dart, Swift, Objective C (as of late), Visual Basic... and COBOL snobs.


I was referring more to the "joke" part of this. Just because a type system offers slightly more safety doesn't make it better. I'm primarily a Java developer, and I would prefer Go's type system over Java's the vast majority of the time. It does a much better job at staying out of the way.


That may be true, but the joke part comes when you actually want to develop new abstractions that are type-safe.

For example you cant write a thread-safe map container in Go without sacrificing type safety (i.e. one that would not crash the program when there are concurrent writes to the map).

The standard library doesn't offer one either.

This means you end up copy pasting the lock related code for every map you want to make thread safe. You have to remember to declare and initialise its lock, to use that lock every time you access it, and to remember to unlock it.

Now for some things, this cost isn't too bad. For others, it makes the language a joke.

As a result, Go is a toy, or at least, a non-general-purpose language. If the problem you're solving fits its limited set of built-in abstractions, its great. Otherwise, its a disaster.

In my experience, well written programs evolve over time to gain new carefully chosen abstractions that cleanly implement shared underlying concepts of the problem domain. These abstractions often require the use of generics.

When this happens in a Go project, however, you're out of luck. Even worse, developing primarily in Go means distorting your thinking to fit its limits.

This is more or less true in any language, and its not a binary thing. Languages are all over the place on the ladder of abstraction (with lisps being close to the top, Go near the bottom).

p.s. Java also suffers because it added generics too late: by the time they were added there was already a clear picture painted of "idiomatic Java". To make matters worse lambdas were also added way too late, and the verbosity of type declarations is still staggeringly high. However, modern Java is a much better language than Go.


I can definitely see the tradeoffs of choosing between Java's bad namespacing conventions and lack of type inference, but keep in mind you're comparing to a 20 year old language. Other languages (i.e. C#, Nim) have learned from Java's mistakes. Go hasn't; they've just gone back to making most of C's mistakes (in type systems).

I've no particular love for Java's type system, but I can't criticize it as much because it was a lot more reasonable when it was released (1996). In 2016 there's no excuse for having a type system as broken as Go's.


Or literally any statically-typed language I know of after C. I suppose it's possible there's some language I'm unaware of that has managed to somehow provide less type-checking than Go, but it's certainly not a commonly-used one.


It's not really a matter of less or more in my opinion. Java has more type checking, but it doesn't give you much more safety than Go, and it's a lot more cumbersome. In general I find Go's type system to be better than Java's because of this.


I think that Java can definitely provide significantly more protection than Go, but I do agree that Java's horrible namespacing conventions and lack of type inference makes it cumbersome.

So what, you're on par with a 20 year old language? C# for example learned from Java's mistakes; why couldn't Go?


I think I just don't come across situations where I find myself needing generics in the software that I typically write. I can imagine it would suck in those situations. There is a workaround for it, though. Basically you write a template and do code generation off of that to sort of approximate generics. I've never done it myself, though.


> I think I just don't come across situations where I find myself needing generics in the software that I typically write.

You don't need generics, sure. You can write working code in assembly, too. But abstractions catch more of your mistakes for you.

> There is a workaround for it, though. Basically you write a template and do code generation off of that to sort of approximate generics. I've never done it myself, though.

So, basically slightly more powerful macros, like in C, with most of the pitfalls and dangers associated with them.

There are better approaches to these problems.


Why is the type system a joke (genuine question)?


It provides zero abstraction, which is especially painful when handling errors. In Go you basically _have_ to handle the error right when you receive it, there is no way of usefully combining or composing it. Also error handling itself is very verbose and can't be abstracted over.

In other languages you can compose errors just as regular values, which allows you to handle the errors at the place where you have all the information to deal with it.

Not only that, the types represent the structure of the computation you ran.

For example, your type is Future[Option[List[Person]]] and just by looking at the return types of the things you called, you can tell exactly _where_ an issue occurred and how to handle it:

Your value is a Success(None)? -> The method inside your asynchronous computation that returned Option[List] failed!

Just to note, Future[Option[List[Person]]] is not some made-up example, it could be a real-world query against the database–for instance "do we know the friends of user X"?

  - Future – we run it async
  - Option – we might not know it
  - List   – his friends
This let's us very neatly tell apart things like

  - Failure – "the database response from the database timed out" 
  - Success(None) – "we have no idea about user X' friends"
  - Success(Some(Nil)) – "X has no friends"
  - Success(Some(List(...))) – "here are X' friends"
(And the compiler will make sure that you handle all possibilities)

In Go the closest pattern would likely be to extract the string from the error value and compare it to error strings you recognize. An alternative would be to define a special single-purpose data type specially for each type including all combinators, as Go would not be able to express any commonality between Future[Option[List[Person]]] and Future[Option[List[Pet]]]. You would need to define 4 new data types and all operations anew.


Mainly because it has no generics.


Nor sum types.


Interfaces can be used to messily construct open sum types. Not enough to save go's error handling story, though.


Interface values have a "type", despite being nil, that can make equality fail.


I am really curious about the kind of tasks that are easily done in Go but for which Lisp doesn't quite fit.


Sometimes I like to have a fully statically typechecked program. You can do that in Lisp, its easier in Go. Also, it directly produces statically linked executables. You can do a lot of this in SBCL, it also produces executables, has type checking etc. But for some of this, you have to wrestle a bit with the Lisp system. The Common Lisp numeric tower is great - until you want to write low level programs where you just want to have machine word sized integers which may wrap around. I once even submitted an abstract to a Lisp conference addressing some of these issues, but as it was not accepted, this side-project was postponed (but I plan to revive it some day).

And of course, there is always the question of the environment. The Go universe has tons of libraries, actively developed.


If you're looking for a FULLY statically typechecked program, you can easily do better than Go. Heck, even using Typescript or Javascript with Flow would give stronger typing than Go with its ubiquitous "interface{}".

Static executables by default is something that Go is famously good at, but I'm pretty sure Haskell can do this as well without so much pain and with a type system many times stronger than Go's.


I guess I don't write the same kind of tools as you, I never need word sized integers. Generally, I define the types according to the problem domain and don't require a specific bit layout. A different case arises when you exchange data through a given protocol, but then you don't do computation with it, just encode/decode.


Word sized integers are fast to compute. So as long as your problem can be expressed with them, it is the fastest way to perform math. When using Common Lisp, I have flexible sized integer numbers, which is nice to have, but the performance penalty can be sometimes too high.


[flagged]


Please don't do this. You obviously disagree that Go is a language which provides full static typechecking. Please instead just state that disagreement, rather than feign confusion. It leads to much better discussions.


[flagged]


HN advocates the principle of charity - assuming the best possible intentions of the people you're talking to. In this case, that would mean assuming this person means something different when they use the phrase "fully statically typechecked", stating what you mean when you say it, and possibly linking to some source material to help further explain. It's quite possible they have the same understanding you do, they just are using the terms differently.


Okay, why don't you assume in everything I'm talking about fluffy rainbow butterflies or something nice like that? Principle of charity, right? That way we can both go our separate ways happily.

If someone doesn't mean "fully statically typechecked" then they shouldn't say "fully statically typechecked". It's not an ambiguous phrase.


That is not what it means: http://philosophy.lander.edu/oriental/charity.html

People have different backgrounds and and experiences. It's reasonable for a person to think "fully statically typechecked" to mean "a program which is statically typechecked, and it does so to the entire program". That would apply to languages such as C, C++ and Go, which are statically typed, but give ways to subvert the type system. You probably mean something closer to "a program which has fully sound static typing", more along the lines of the MLs or Haskell, which have a richer type system which you cannot subvert.

We're here for interesting discussion. Derision is not a part of interesting discussion. You're relatively new here, so I figure it's worth explaining this explicitly.


> That is not what it means: http://philosophy.lander.edu/oriental/charity.html

I'm aware of what it means--I'm saying that the principle of charity doesn't apply. The principle of charity doesn't mean you get to actually change what the person is saying, it means you assume the best when there's ambiguity.

> People have different backgrounds and and experiences. It's reasonable for a person to think "fully statically typechecked" to mean "a program which is statically typechecked, and it does so to the entire program". That would apply to languages such as C, C++ and Go, which are statically typed, but give ways to subvert the type system.

But in the cases of C and Go, it's not just that--you can't use generics or templates, so you're stuck writing generic-like code with void* or object, respectively. That's not subverting the type system intentionally, it's just not type checked and there's no alternative. So these languages are not fully type checked, even if you don't subvert the type system. So even by your charitable definition, it's not fully statically type checked.

The word "fully" has a meaning that's not ambiguous. There's not an interpretation of "fully statically typechecked" that includes Go, even being charitable. Every nontrivial Go codebase has sections that are not statically typechecked and can't be modified to be statically typechecked.

> We're here for interesting discussion. Derision is not a part of interesting discussion.

I'm here for interesting discussion, and I don't think that an interesting discussion starts from obvious falsehoods like "Go is a fully statically-typed language". Derision discourages making such statements and increases the average interesting-ness of discussion because people are afraid to say dumb things. People should think before they make claims.

> You're relatively new here, so I figure it's worth explaining this explicitly.

I'm not new here, I just delete my accounts every so often.


Derision is not civil, and explicitly discouraged.


True, but given the entire point here is to have interesting conversations, I think that's a higher priority than civility.


They are considered the same thing here. There is a reason it comes first in the guidelines on comments.


Heh: my initial thought was that Go is nothing like Lisp - Lisp has the most powerful metaprogramming around thanks to its macro system, while Go doesn't even have C-level macros, or any of the type-system features some languages use as an alternative approach to metaprogramming. As a result Lisp is notoriously unopinionated, while Go is very opinionated. Lisp is functional, Go is aggressively imperative. And so on. But I guess the languages share some things: no complex type system, fast compiles, emphasis on simplicity in general, no need for an IDE, old fashioned feel (no, really, that's not a diss necessarily)... and at least Go has reflection.


> Lisp is functional

Not really, multi-paradigm.

> and at least Go has reflection.

Go is introspective.

Lisp has both introspection (e.g. find-class allows to look at existing classes) and intercession (e.g. ensure-class creates/modifies a class at runtime).


> Not really, multi-paradigm.

Yeah, that's probably a better way to describe it; it certainly ain't Haskell. But Go really doesn't want you even to use things like map and filter.




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

Search: