People who likes Go's simplicity, have you ever looked into the even simpler syntax of lisps? For example, Clojure have minimal amount of syntax, that once you know, you know the entire language. The rest is just libraries that you use, the actual program/data structures or language modifications (macros) that each codebase usually employs a bit different depending on needs. But lisp languages are really, really simple, even more simple than Golang (or any C like language) can be.
As a long-time Clojure user, I find the claims that many Clojurists put forth that Clojure “has a minimal amount of syntax” to be quite misleading, especially toward beginners.
I think Clojure has a lot of syntax. The syntax is just embedded in a number of conventions, macro mini-languages, and the reader syntax itself. Because Clojure’s syntax can be extended in user space (via macros and related tooling), the syntax also grows more rapidly than other communities.
As a professional programmer who came from Python, Java, C, and JavaScript, I found a lot about Clojure compelling, but “minimal syntax” was not one of the compelling points. To the contrary, I think there is a lot more to learn in Clojure than other languages about how to properly structure your code.
As I wrote in my blog post comparing Python and Clojure:
> ... the Python programmer will observe that in the Clojure program, many aspects of the program are implied, rather than annotated by special syntax. Many Clojure proponents will say that Clojure has a “simple syntax”, but I think this is misleading. They don’t mean simple as in “easy to read without prior context”. They mean simple as in “unceremonious”. Perhaps they mean simple as a contrast to “baroque” (how you might describe Java or C++’s syntax). Clojure does have a syntax, but it is implicit from the layout of the code in the list data structures.
This is nominally a library as it can be implemented via the language primitives. But in practice this occupies the same space as Haskell's do-notation, and the learner cannot ignore it. The lack of special syntax becomes an implementation detail.
People who like "Go's simplicity" are talking about a completely different kind of simplicity than Lisp's or Forth's or Smalltalk's.
The latter are simple in that they're built around a few core concepts which are available to the developer, almost any tool the language designer had is available to the end user. They're simple in the sense that old school legos or meccanos are simple.
Go is simple in the sense of simplistic, it provides a much larger number of restrictive features and most definitely doesn't give end-developers access to the language designer's tooling. It's the simplicity of playmobil or duplo: the developer is provided with much more concrete (and effective in a way) but much less flexible "primitives".
And this is no secret, there's a pretty famous quote from Rob Pike explaining the design and purpose of Go:
> our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.
Making codebases look uniform and preventing building abstractions (by the language being actively hostile to abstractions which are not built-in) is in line with that.
"Our programmers are Googlers" comment is a retcon! It was from 2014; what was the pitch before that?
In 2010 Pike presented Go as "suitable for writing systems software" [1] such as: web servers, web browsers, compilers, programming tools, IDEs, and OSes ("maybe").
Today Google makes a web browser, and lots of compilers, and programming tools, and an IDE (Android Studio), and at least two OSes (ChromeOS, Android), and Go is not relevant in any of them (excepting Go tooling).
In 2012, Pike was still pitching Go as a C++ replacement, but was dismayed that it was appealing to Python/Ruby programmers. Why don't C++ programmers use Go? He hypothesized [2]:
> C++ programmers don't come to Go because they have fought hard to gain exquisite control of their programming domain, and don't want to surrender any of it. To them, software isn't just about getting the job done, it's about doing it a certain way.
The saltiness was aimed at Google's own C++ engineers, but I honestly don't think that Go was or even is up to reimplementing v8 or Blink.
But today Go really is enormously successful and compelling. It failed at displacing C++ but found its niche. Kudos. But retcon - it is a mainly server-side language because that's where it succeeded, not what it was designed for.
Today Rust is busy displacing C++, so it can be done. Go just wasn't the one to do it.
What is with all of the condescension that other developers have towards Go developers? Go has a set of highly desirable features that are very practical for building large team projects.
Imo it's unnecessarily hostile to compare go to playmobile and diplo, and it really encourages people to overlook the genuinely excellent features that go supports.
Yes, I've been programming in Lisp and Racket for the past twenty years and recently switched to Go. The main reason was the availability of a large number of packages and the general tooling for Go. So far, I'm quite happy with my choice. Productivity is slightly less than with Racket, but outweighed by the small size of the executables, easier deployment, and more 3rd party libraries. Of course, I'm missing a lot of features that pretty much any Lisp offers, but the simplicity and static typing does overall have many advantages.
Since you mention Clojure: That's useless for me, because it runs on the JVM. One reason to use Go is exactly that it produces static, self-contained executables that don't require any heavy infrastructure.
If you care about a rich standard library, and static self-contained executables, I would strongly suggest Crystal. I have used both Go and Crystal, and the latter is much more productive as well as simpler. It’s standard library is richer. See, for example, the things you can do with strings with the provided functions. I used to love Go. But after some time the verbosity got tiring. I moved to Crystal, and there is nothing I miss from Go. Two big caveats: 1. I dont work in a big team. 2. My main use case is a web-backend.
For small executables, check out Chicken Scheme. For static typing, see Typed Racket (though Chicken Scheme is also moving in the direction of gradual typing, if I recall correctly).
Lisp is simpler on a completely different dimension. Lisp code can be arbitrarily complicated to read due to arbitrarily complicated macros. This is frequently blamed for Lisp's continuing failure to take off, that every major program written in it is eventually actually written in a custom dialect of Lisp. This directly opposes, for better or worse, the sorry of simplicity Go has. (I think there's a place for both, so I'm not judging one as "better" here.)
Avoiding Lisp because macros could be abused is like avoiding C because functions could be abused. What if I create a function called "log_error" that actually tries to reformat your hard drive? There is nothing in C that requires me to give functions names that aren't nonsensical.
Macros, like nearly anything else, are an abstraction that requires a little bit of restraint and common sense when you're using them. The answer to the "functions can have misleading names and therefore can be used to create intractable tangles of incomprehensible code" is "well then don't fucking do that", which is the same answer to the majority of problems people think macros cause.
The simplicity of Go isn't in a syntactic minimalism. It's in the self-conscious restraining of abstractive power (eg. the article's example of the only generic data structures being slices and maps).
I assume that people are trying to attach it to the term “simple” because that word has a much more positive connotation, but the meaning isn’t the same.
An important difference is that Go not only has a concise set of constructs, it also tends to deliberately avoid abstraction.
So any given piece of code is very explicit and self-contained. Apart from function calls, you can tell exactly what it does without looking up anything else, like a macro definition for example. It similarly doesn't have a lot of different ways to do the same thing tends to be opinionated about idioms (gofmt, for example).
Something like a Lisp DSL would be antithetical to the Go model of what simplicity means.
> Apart from function calls, you can tell exactly what it does without looking up anything else, like a macro definition for example.
It sounds like you’re splitting hairs here. In my experience, macros aren’t any more mysterious than functions. The only difference, after all, is when they’re evaluated.
The difference is that they generate code. So now you have compile some code in your head as well as running your hypothetical execution. Nothing wrong with that but they tend to be harder to understand than functions.
This is something that people overlook quite often. It is very important to have a well-documented, up-to-date, and capable standard library packaged with your language. It just creates a smoother experience altogether.
Besides that, it also sets the standard for the 'right' way of designing your interfaces and whatnot. In Go, the third-party libraries are often compatible with the standard library methods and interfaces, which is just fantastic in both mobility between libraries, and having consistency with different projects.
> Compare that to JS or even Python, where I have to either use libraries for even the most basic stuff or have a huge amount of syntax and keywords.
in python, you don't have to. same for javascript, before the whole jquery era, and the nodejs era that followed, we didn't even know what javascript libraries were.
I‘be looked into clojure briefly. What made it unattractive to me was the lack of performance and complexity of the build tooling. Simplicity in go goes beyond the language itself. It is also very simple to build, depend on libraries and deploy.
Go has had an absolutely appalling dependency management complexity for a long time. Go modules looks like it is going to fix that but it's long time coming.
I am both using Go and Lisp and like both very much. As mentioned by others, the simplicity of Go isn't in the syntax, it is the conceptual simplicity. To large extend it does share this with Lisp. Especially if you look at scheme, most abstractions are built on top of functions, something you can equally do in Go, as you have first class functions and closures.
Simple syntax is why I prefer Erlang to Elixir. The syntax is so simple you can learn it in one day easily -- a big plus when you have to work in multiple languages at the same time for one project.
i agree with you. go is not the simple language its creators wanted. and i feel like it's only going to get more complex from here on.
for example, i couldn't get a library to work the other day because of one of the dependencies needed a specific version of another library but "go get" (1.13.4) was getting utterly confused.
i never looked into the modules thing and i found that there is a 4 parts series of articles on the official blog explaining modules are and why we need it. i just gave up at that point and decided to manually copy the version i wanted to the $GOHOME/src folder and it got me going...
Take a look at this (short) page which describes ALL the syntax of Clojure (except macros) if you're interested: https://clojure.org/guides/learn/syntax