Get Your Development Team Started With Go
digitalocean.com
digitalocean.com
For us its a freaking story of awesome success. Go = ROCKS!
Now if he said they had no such luck w/ Java/D/Rust, then perhaps I could understand your ultra defensive fanboi position.
But since the post was on topic of Go and we do have quite large Go infrastructure I just wanted to comment that Go is awesome. More people should know about the awesomeness and perhaps experience the same as we did.
Greybeards like myself already experimented "Go's awesomeness" in the form of Modula and Oberon derivatives in the early 90's.
Having said this, reducing the amount of C code in the world, by using memory safer languages is surely positive.
It's kind of like if I excitedly told my friend I'd run an eight minute mile, and she replied, "oh, so what? Lots of people can do that". Technically true, but unnecessary.
It's a very old project and super important core technology - we did refactors before and I was somewhat scepitcal when lead devs on the project suggested to use Go instead for the next "refactor". I was blown away by the quality, speed and productivity.
If you're building server infrastructure that needs to be performant, consider Go.
1) Error handling, Give you ability to impose defensive practices making network or another other I/O failures or unexpected responses from external or internal calls easy to handle.
2) A lot of errors can be caught at compile time. Which means less errors in runtime.
3) It so simple that all of the build in functions and syntax can be expressed in less than 16 lines. Makes reading your code and anyone else code very very easy. Also FMT is sick.
4) Dead simple concurrency.
But all this has still not helped me push Go as the goto lang at the company I work for, why? Sometimes you work with people that just don't want any change.
Give Go a try you'll be shocked how well its designed.
[0] https://groups.google.com/d/topic/golang-nuts/RKymTuSCHS0/di...
" Functional programming languages don't have for loops, and so need to provide assistance to perform iterative tasks."
Are you sure you're modifying the correct outside variable ? Are you sure you really are modifying it:
bar[i] = f(foo[i])
and not creating a new one: bar[i] := f(foo[i])
? Are you sure you're not also modifying another variable that you didn't know was "linked" somehow ?Given the direction Go has taken, it would make very little sense to introduce functional programming bits. But you must admit that the immutability/lack of side effects of the FP gives you a lot of assurance on what to expect.
foo := 5
is shorthand for: var foo int
foo = 5
the "range" keyword over an array gives you the index and the value at that index. If you don't need the index or the value, you can put a "_" in it's place (to save on the allocation).http://play.golang.org/p/Z2ejUlN5An
You'll notice that foo[i] is still printing "0", because range always creates a copy of the object assigned into v. Unless you start using pointers, you'll never have mutation issues.
But maybe, rather than just carping, you should wait until you really understand why Go is trying to solve the problems that it is actually trying to solve. Because I don't think you do understand that yet.
Go is trying to solve the kinds of problems you run into when you have a multi-million-line code base that you have to maintain over two or three decades. At that scale, you get new problems - not just more of the same old programming-in-the-small problems.
I'll give you this much, though: Loops are easier to screw up than the grandparent seems to recognize.
Likewise, composability improves readability and isolates code into small parts that can be assembled. This is beneficial to large applications as well.
You seem to indicate that concurrency is the only problem worth investing in with large applications but they are not mutational exclusive. Erlang does a good job of both, for example.
For example, one of the big problems is circular dependencies. Go solves this by explicitly prohibiting it - your dependencies must form a directed acyclic graph. You therefore have to work out a solution the moment you would want to introduce a circular dependency. You can't introduce even the first one. That means that you can never build up the kind of nightmarish hairball that large projects often turn into.
Is it painful to have to prevent circular dependencies all along the line? Certainly. But it prevents more pain later.
Now: Do I know that functional programming, map/filter/reduce, and avoiding mutation cause problems at scale? No, I don't. On the other hand, I doubt many projects have been built using FP at this scale, so one can't assert that FP will scale this far.
HN's reaction to Go reminds me of Stroustrup quote about C++:
..."There are only two kinds of languages: the ones people complain about and the ones nobody uses"
So much complaining about how Go lacks this and that features of shiny new (and sometimes unfinished) language X. In the meantime, as time goes by it seems that more and more real companies use Go code in real production and are quite happy with it, despite all the shortcomings frequently listed here.
And to your last sentence, use in production is not a good measure of language quality (except in a tautological sense), because many non-technical factors strongly affect popularity.
And to your last sentence, use in production is not a good measure of language quality
It is actually a great indicator of the gap between abstract language tourism, and practical day to day development.
I will say again that Haskell is held as the perfect language and set of choices on here constantly (particularly when used to denigrate Go). Yet it is used for perilously few actual solutions (despite being around for decades).
Sometimes the things that seem incredibly important and of great value just aren't such a great value in the real world. Similarly, things that seem minor end up being very important.
As for use in production, I agree that it can be a fair barometer for "utility", but I strongly disagree that it's a good measure of "quality" (as in, technical design choices). We live in a path-dependent world rife with network effects, so quality per se just doesn't matter all that much, and non-technical factors like "being backed by a major corporation" can matter a lot. I'm sure there's more Visual Basic in the wild than Go, but I'd hardly use that to argue that it's a superior language, or that Go proponents are "abstract language tourists".
i hope you're just not aware whom you're talking about http://en.wikipedia.org/wiki/Go_%28programming_language%29:
"Go, ..., is a programming language initially developed at Google[6] in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson."
Suggesting application of Blub paradox to the people who invented Unix ...
no offense, man, yet this your statement is an example of the blub paradox.
"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 ..."
it is like you looking up at Thompson and not realizing that you're looking up. You probably consider Thompson equivalent to you and everyone. (Again, no offense intended, though i can see how it can sound kind of offensive).
On the other hand, unless you spend a lot of time using a feature in earnest, it's hard to know that the feature is actually not necessary because it's an enormous workaround for something else.
Who mean the same people that disregarded memory safe system programming languages and decided to create their own "unsafe by default" one?
The same people that created a text based operating system, while at Xerox PARC GUI based workstations were being developed in memory safe system programming languages?
it sounds a bit oxymoronic, at least on practice. I'm yet to see a normally functioning system written using "safe system programming language".
>The same people that created a text based operating system, while at Xerox PARC GUI based workstations were being developed in memory safe system programming languages?
i hope you don't mean Unix here because Unix has nothing to do with either "text based" or "GUI based" - it is completely orthogonal to that.
Just some examples of operating systems that worked for several years in certain circles.
Xerox Star systems coded in Mesa.
Lilith coded in Modula-2.
Spin coded in Modula-3.
Oberon coded in Oberon.
AOS coded in Active Oberon.
Ethos coded in Oberon.
Original version of OS/400 coded in Modula-2.
Mac Lisa and initial versions of Mac OS coded in Object Pascal.
VME in Algol 68
The real time systems driving lots of trains, planes, helicopters and medical devices running Ada code deployed directly to firmware.
> i hope you don't mean Unix here because Unix has nothing to do with either "text based" or "GUI based" - it is completely orthogonal to that.
I sure do.
UNIX System V does not offer any GUI interface.
POSIX does not offer GUI support.
I'm pretty sure Ken Thompson &co were fully aware of generics and sum types (to use your own example). It trades the implicit complication of implementing and using those (and other) features for strong concurrency. For a lot of people, that's a good tradeoff to make.
Clearly that was a very deliberate choice on the part of the Go creators, not the result of oversight or ignorance. I suspect they simply didn't want to reflect the state of the art 30 years ago, 20 years ago, or today. I don't find that at all surprising, because people who want to get things done often like very simple tools which stay out of the way. To each their own though, and I'm sure the go creators would be very happy to see other languages used instead of go by those who prefer more features, more complexity, state of the art from 30 years ago, etc. I do find myself puzzled by the hostility it generates though - it is just a language, one of many, and about which some very ordinary claims are being made (easy to learn etc).
Sure, that's really useful - you guarantee that you can never access the unset half of the value. But it adds a lot of complexity, too. You need a way to declare values of this type - this means more keywords and/or more special syntax. You need a way to then access both halves of the values, so now you have to add pattern matching... that's actually a lot of complexity to add to a language that only has 25 keywords.
All that, instead of just doing what Go already does, which is to return two values and just have a convention of checking the error before the value... which works really well 99% of the time, and doesn't require all the rest of that complexity.
Does the functional style of maps and composition cause problems at scale? I don't have any data. However, I would not begin by assuming that Go's designers were either stupid or ignorant of functional programming idioms.
I cannot see a single way in which that is objectively "better".
I cannot return a loop.
It has been pointed out multiple times that the page you refer to, only focus on C++ and Java, while forgeting about all the other languages.
Edit: Removed stupid comment.
The languages and compilers I'm familiar with (Scala, Haskell, MLton) all pay a cost, usually in compile time.
[1] http://research.microsoft.com/en-us/um/people/akenn/generics...
In F#, you can use hat types via inlining to get even more power. Like creating a map function that works directly on List, Array, and Set - but without using any common interface. Pretty neat, but it emits the function's IL into every callsite so it can get out of hand.
I recall there being a mailing list thread on Go where the designers addressed this. I've no idea how Go is implemented so perhaps the multiple-copies problem is actually significant.
Also addressed by Ada generics for example. There are many others.
Strong typed languages with generics go back to CLU (1974), so there are lots of research material, as well as, real languages if one steps outside Java/C++ implementation mindset.
I find some philosophy of C and Go similar, BTW. Minimalism is an art.
If all business decisions were based on pure computer science we might very well have much better software, but im inclined to believe we wouldn't have so many different and great products out in the world.
(It isn't of course)
:.:.:
Go lacks a lot of basic functionality a lot of other languages take for granted. I.E.:
In Rust you can type
fn id<T> ( item:T) -> T
{
return item;
}
And you assign the type to the function. This is possible in Go by double casting the type. Which is really messy, and what java did in 2004 for generic functions (and was ultimately useless).:.:.:
Lets say you want to iterate over a array in say java.
for(byte a: bytes[]
{
x += a;
}
This also doesn't exist in Go. Yet does in python, java, and several others thanks to iterators.:.:.:
Lets say I'm adding vectors and dark magic has told me to use '-' for the dot product. In most languages (Rust, C, C++, Haskell) this is completely possible, as - is just a function. __subtract__() in rust.
You can't in Go.
:.:.:
Now lets talk about pointers. When you want to signify data doesn't exist in Go you pass a null pointer (nil, 0x0). This is wrong on almost every single level. Your not only creating a back door, but your by passing your entire type system.
The only thing that stops this from being common practice is that Go has such good message handling, but it still exists! Why?!
:.:.:
Immutable variables, data structures, etc. are a thing of beauty. In Rust and Haskell all values are immutable by default, but most languages (C, C++, Java) let you delcare variables, data structures, etc. as immutable.... Go doesn't.
:.:.:
Go has no support for turning off compiler safety features. Much like Rust offers the
unsafe{ ... }
tag for isolating code that may do strange things, go doesn't.:.:.:
TL;DR
Go doesn't do anything new.
Actually it takes a step back.
for _, a := bytes {
x += a
}
No there's no generics. I rarely need generics. Usually I need a specific, and waste time making a genetic.No there's no operator overloading, and thank god. + is numeric add, I never have to wonder if + might be some crazy O(n^2) function. Yes, that makes go bad for Matt and science code. That's ok, go is not for every application.
Go has unsafe and reflection, it is just discouraged strongly.
Yes, nil exists. Big deal. You know how often I've seen nil pine exceptions in a year of writing go full time? Once. Because go has multiple returns and you never look at the pointer before checking the error.
No there's no immutable data structures.... And I've never missed them. You can approximate them with interfaces with only getter methods, but it's rarely worth the effort.
Often times in large code bases you'll have short mathematical expressions used in multiple places.
fn error<T:num>(real:<T>, test:<T>)-> <T>
{
return ((real-test)/real)*100;
}
Now instead of typing the same thing over and over and over again I call a function (literally what they're designed for), and it works for floats, doubles, AND ints.>no operator overloading, and thank god. + is numeric add, I never have to wonder if + might be some crazy O(n^2) function.
Overloading is normally done a per-data type basis to avoid exactly what you state. But yes, it is a big mathematical/scientific point. It can really simplify your life working with some data structures.
>Yes, nil exists. Big deal.
No that's the problem. Its existence is a bug. And has no use existing, as you said yourself its rare, you never see it, you hardly use it... So why even include it?!
>[...] immutable
Immutability is more of a programmer hack, not a language hack. Rust and Haskell make me ask myself 'will I actually change this value' when declaring a new variable. And addes an extra mental step and self check of your own code when programming.
He said he rarely sees code fail because of nil dereferences, not that he rarely sees it. "if err != nil {" is probably the most commonly written line of Go code by a large margin. Nil fits well with the language's zero defaultness of values. It may not be theoretically sound, but in practice it fits within Go very well and rarely causes the problems it tends to in other languages with null.
http://www.infoq.com/presentations/Null-References-The-Billi...
To say Go doesn't do anything new is wrong however. The language specification doesn't include new material, sure, but the language tools are incredibly engineered. Go get just works (but don't use it for long term dependency management, that's not what it's designed for.) The documentation is stellar, and it's really easy to make good documentation. The compile times are lightning fast. Go fmt is by far my favorite feature; All Go code looks the same, and it even saves time trying to format code to look nice.
As for your specific complains:
:.:.:
No, Go doesn't have generics, but for most cases that's ok. The saying goes when you have a hammer, everything looks like a nail. However Go does give you a screwdriver (interfaces), and it turns out a lot of things work well as screws. Generics aren't easy, they complicate the language (which goes against one of their language goals), and increase compile time or run time (which go against other goals.) They haven't said generics will never be in the language, just that they haven't found a solution they like and that it won't be in the language any time soon.
:.:.:
You can iterate in Go. Otherwise for loops are a tried and true method.
:.:.:
This complicates some code, but makes the language a lot simpler. Yes it's a trade off, and the language author's choices may differ from your preferences.
:.:.:
Yuck, nil pointers, I agree. However sometimes an ugly feature makes the whole language look a lot better. Nil usage aligns very well with the design of the rest of the language. Gross? Yes. The wrong design decision for Go? Definitely not.
:.:.:
Immutable values complicate the type system and require that those features occupy some brain power. They may be nice in other languages, they have no place in Go.
:.:.:
Go has unsafe operations.
> For example, SoundCloud maintains one monolithic $GOPATH
> in a single git repository that they can then
> selectively update.
No, we tell developers to use a single $GOPATH on their machine, and check out/edit code directly in the canonical location, e.g. $GOPATH/src/github.com/soundcloud/foosvcDon't use multiple spots on your hard drive for code in source control. Use source control for what it's made for.
> This is what source control is for. You switch to the
> branch and hack on it.
We're also running a microservice (SOA) architecture; each repo represents one service, with one (hopefully) tightly-constrained purpose. It's very rare that we're doing more than 1 or 2 feature branches in a repo at one time.we started off with the idea that all three of us had to be talked into every feature in the language, so there was no extraneous garbage put into the language for any reason.
I would also argue C++ started in similar fashion but it went exact opposite route. The balance between minimalism and feature creep can only be achieved if you are designing language as a side effect of building your own large scale project combined with a sense of urgency.
Go is currently a lucky language. There is a huge vacuum that Java has left after Oracle acquisition plus its prolonged stagnation. People who need compiled languages for their relatively new code base, Go would end up becoming their choice regardless of its shortcomings. People will enjoy its minimalism until code base grows to be monster and features starts becoming sorely missed. This is nothing unusual in world of programming languages. We have seen COBOL become a gold standard at one point and PHP is still pretty hot.
What? Uh no. That's exactly what it was designed for. Big projects at Google. It has been stated by the creators of Go multiple times.
The simplicity of Go helps in many ways that are not immediately obvious. You always know how memory is laid out in a struct, so you know how much memory you're copying with every instruction. You always know when you're generating garbage, so you can take steps to avoid it when it matters. In general, everything your code tells the computer to do in Go is very obvious, so you can actually reason about what your code does on the small scale and not just on the big scale. And yet, it does this without the added unsafety of C, and without all the enormous complexity of C++. And it does that in a way that you just can't achieve with Java's "everything is an object".
That's why people are flocking to Go. Because it has Java's ease of writing with C's ease of tweaking, and yet fixes a lot of the inherent problems in both languages.
As per Wikipedia -
Ken Thompson states that, initially, Go was purely an experimental project. Referring to himself along with the other original authors of Go, he states:[11] When the three of us [Thompson, Rob Pike, and Robert Griesemer] got started, it was pure research.
http://talks.golang.org/2012/splash.article
"The language was designed by and for people who write—and read and debug and maintain—large software systems."
I'm sure it started as research. Many things do.
I would have loved a more detailed explanation of why they chose Go for a particular problem space rather than C/C++/etc. What problems is Go particularly good for, and for which problems is it a poor choice?
Binary downloads http://sourceforge.net/projects/liteide/files
#!/bin/sh
export PORT=8080 go run go/spanishdb.go go/Html.go
Any good blogs on using Go in a production ready server? Should I run behind Apache?
http://stackoverflow.com/questions/14537045/how-i-should-run...