Program your next server in Go
talks.golang.org
talks.golang.org
That was the good. The bad? Garbage collection, dependency management, and lack of first-tier support in various libraries. Garbage collection makes the otherwise lightweight and speedy language a memory hog under heavy loads. Not too bad, but I have to kick the memory up on my servers. Dependency management is a nightmare; honestly the worst part about it. The lack of first-tier support in various libraries is a close second. AWS's API libraries had relentless, undocumented breaking changes when we were using them, all on the master branch of their one repo (breaking Golang's guidelines for dependencies). Google itself doesn't actually have any real API libraries for their cloud services. They autogenerate all API libraries for golang, which means they're not idiomatic, are convoluted to use, and the documentation is a jungle.
We continue to use Go because of its strengths, but it just really surprises me how little Google seems to care about the language and ecosystem.
Garbage collection has become very fast in recent versions of the language. It's quite painless now, and we did struggle with it in the past. I'd take the current GC over dealing with other strategies unless you are a very specific, >60fps kind of situation. We literally don't think about the GC anymore.
Random stats from one of our busier nodes, over the past 20 min: 40GB currently in use, 391GB allocated (and freed) in the last 20min average of 2.6ms GC pauses every 70.6s 95th percentile on GC time is 7.26ms
For dependency management, there's a lot of tools that make things more automated and I think probably offer people what they are expecting/used to from other environments. This has been a sticky point for sure. I've settled on a bare bones solution that seems to work well: just using git submodules in the vendor directory within the project repo. Does everything I need (pin to version of a fork, build immediately after a clone and a submodule update --init). As of Go1.5, the vendor directory is supported by the compiler, and it will look there first to resolve dependencies. While this does work with recursive dependencies, you will want to flatten the dependency graph as much as possible if types are being used across multiple deps because types are distinguished by their full import paths. This encourages breaking things into modules so I'm ok with it.
First-tier support is a problem I have no doubt, but not one we've suffered from personally.
I'd say that debugging comes up a lot too, and Go doesn't have an official, reliable option for debugging. The Delve project is getting close to that though it looks like. I personally debug with the stdlib pprof package (provides an http server that prints stack traces for all goroutines currently active, allows cpu/memory/blocking profiles to be requested), print statements, general testing/experimentation and newrelic.
Edit: other comments below have mentioned some of the tools available to manage your vendor/ tree. Using git submodules manually can be crude, especially when adding dependencies that themselves have other dependencies.
We're (I'm one of the contributors) working on them.
Check them out here: https://github.com/GoogleCloudPlatform/gcloud-golang
Datastore docs: http://godoc.org/google.golang.org/cloud/datastore
Nice business model.
Go is certainly a language that is used at Google, but AFAIK a lot of "Googlers" don't really like it and don't use it. It certainly not the "official language at Google", given the weight of C++ and Java there. But that's the consequence of being opinionated. Using Go means having Rob Pike over your shoulder telling you how to write code. And he made sure you can't escape that fact since there is no place for "ninja coding" with Go.
Go to me feels like they implemented the Google Java and C++ style guides as a language.
Python as well.
>> how little Google seems to care about the language and ecosystem
Let's compare with Microsoft. The top four out of five users at StackOverFlow have top tags in C#, I guess Google have a long way to Go.
Why do you think that WinRT is basically the return of .NET the Ext-VOS project origins, but with .NET metadata instead of COM type libraries?
.NET Native is what Ext-VOS was going to be, if it wasn't for the decision to create the CLR instead.
Where on earth did you hear that? It's simply not true.
(googler)
The archetypal form of cowbody coding is the copy-and-paste: faster than any code reuse technique, but a booby trap for the future.
"Ninja coding", on the other side, refers to coding for cleverness' sake, at the cost of legibility and ease of use. No self-respecting ninja would simply copy-and-paste.
And a completely opposite philosophy from Go when it comes to error handling. Erlang/Elixir embraces failure (and immediately logs and restarts the process); Go seems to ignore it (unless you explicitly check, which to me seems... insane. For reasons why failing fast is better than failing silently, read https://blog.codinghorror.com/whats-worse-than-crashing/ .)
Elixir/Erlang at least have pattern-matching which makes checks like that (from functions that return a non-OK value on errors) basically inlined:
`{:ok, val} = call_some_func(with_args)`
If it doesn't match on the :ok (i.e., an error occurred), you get a match error which gets logged, and the process typically gets killed and restarted by a supervisor process in a millisecond.
Is it that bad now in 1.6 with vendor support? And a tool like `govendor` makes it easy to stick things inside of vendor.
> it just really surprises me how little Google seems to care about the language and ecosystem
To be blunt, google's priority is google, not the open source community or other companies using golang. Dependency management wasn't a priority because of mono repo. Having said that, they are pretty good about improving things for everyone, but it will never be like a company such as Typesafe whose product is the language and tooling itself.
What I would really like to be able to do though is be able to write unmanaged blocks when I need them and know better than the compiler rather than having to "run my own heap" on top of a buffer like I typically have to do in managed languages that don't have that opt out.
Do note that it triggers a GC when you call this, so it's not for all situations, but can be useful.
Are you sure? Google offers 2 Google Cloud APIs for Go:
- Google API Client Library for Go, which is auto-generated like you wrote;
- Google Cloud Platform Client Library for Go, which is intended to be idiomatically-designed.
Are idiomatic API libraries really a good thing? If an API is used heavily throughout your application, doesn't that mean it's time to wrap that part of the API in some idiomatic wrapper code that is meaningful in your domain?
Functions are idiomatic in all languages. Personally, I'd rather APIs mostly stick to simple functions, and let the application developer build idioms around them if they like. And if the API call involves a web request, I am happy to just make the HTTP call myself. Half the time you need to understand the interchange format to debug your code anyway. My experience is that wrappers rarely protect you from that.
I guess if your application is 90% calls to an API, and you use a huge range of different functions in that API then you'd want a good, complete library. But how common is that?
Also, have you actually seen the auto-generated APIs he's referring to?
Here are the Godocs for the BigQuery API: https://godoc.org/google.golang.org/api/bigquery/v2
Here's some example code demonstrating the API's bad habits -- such as deeply nested struct pointers, and Do() methods everywhere: https://github.com/google/google-api-go-client/blob/master/e...
It's still labeled "experimental" though, which makes me a bit wary to use it just yet.
If you're OK with changing your code sometime in the future, then I'd recommend giving it a try for this or your next project. Changes will likely be minimal.
Idiomatic APIs can be a real PITA, especially when you call them from a different language. KISS should reign supreme. (With bad 80's special effects in a made for TV movie filmed at a carnival.) If you leave it up to the client developer to build the idiomatic facade/interface, then the API is simpler, the code is more properly idiomatic in the end, and everyone is happier.
Source: I've written many servers in both C and Java and given the choice will never use a GC language again for a server. Holding out some hope for Rust..
However I would still favor java instead of go
Could the problem have been the "global interpreter lock"? The GIL makes it impossible for multiple threads to simultaneously perform certain basic operations, effectively making the system single-threaded.
- The Go compiler certainly isn't as sophisticated as the better C compilers. It looks that the code produces by Go 1.7 is quite improves vs. 1.6 with the SSA compiler and I would expect further gains in future releases.
- The Go compiler does not offer optimization levels and overall is optimized for compilation speed to, so these tradeoffs could be limiting.
- While the Go GC is very good and improving, so that the pauses are very low, it does use CPU, also while running in parallel to the program. How much exactly very much depends on the allocation behavior of the program, but should be accounted for.
- 1x benchmark - C / static C++
- 2x slower - pure virtual C++ / objective-c
- 3x slower - statically typed GC languages (java,go)
- +6x slower - dynamically typed GC languages (js, python, etc)
After a well optimized implementation, speed comes down to manual vs GC memory management, static vs virtual function dispatch, dynamic vs static typing and heap vs stack allocation.
Compile speed is usually slowed down by any sort of type inference or templating/generics, which is probably one reason why go resists implementing generics or subclassing
Your rules of thumb are probably mostly related to CPU bound tasks. If database i/o is the bottleneck, then the differences across language probably don't matter much.
And, runtime performance isn't always the most important thing. In many cases, "time to market" or "cost of development" might be a higher order priority. In those cases, a higher level language might be more attractive.
It's also a bit tedious to write in practice. It's dogmatic, and that's obviously a benefit in some ways but comes with the cost that quite a lot of time in my experience is wasted fiddling around with program structure to beat it into the way Go wants it to work. Dependency management is better with Glide but still not perfect. The type system is quite annoying, and although it's a cliche the lack of generics is quite annoying. Lots of silly casting to and from interface{} or copy-and-pasting code gets old quickly.
Still, it's a great tool for its niches and I really think everyone should pick it up and use it - the idea of simplicity it promotes is actually kind of interesting, in contrast to the "showy" features one might expect of a modern language.
I would upgrade your phrasing to: "frustratingly dogmatic in an ok way".
For example instead of the obscure function
a.reverse()
you can use the clear for loop for i := len(a)/2-1; i >= 0; i-- {
opp := len(a)-1-i
a[i], a[opp] = a[opp], a[i]
}
:( Averager averageCollect = roster.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.map(Person::getAge)
.collect(Averager::new, Averager::accept, Averager::combine);
System.out.println("Average age of male members: " + averageCollect.average());
From here: https://docs.oracle.com/javase/tutorial/collections/streams/...A lot of the time it is clearer as an explicit loop, especially for other people to read. But it is annoying a lot of the time. I still think they should add generics.
I have very littile knowledge of Java, but it's clear as day that we filter only entities with male gender, get their age values and return average.
I mean... really.
This isn't a big deal when what I'm looking at is "students.filter(...MALE)" because that's obviously the "male students". But it quickly gets more confusing. What is "students.filter(... == year - 3)"? Is that "freshman students" or "sophomore students" or something else entirely?
Of course there's nothing stopping functional programmers from naming their intermediate results, and nothing stopping imperative programmers from choosing useless 1-letter variable names. But the two different programming styles seem to encourage different things.
Go is statically typed, and this either requires generics or a new built-in for just reversing an array/slice. And I can't see how a trivial operation as array reversion is worth it, and there's just no end to adding such trivial operations. If you need a slice with reverse, just add a typedef and define reverse on it --it's just a trivial loop.
What is it that you want to say? That array reversal too much for mortals and better be left to array experts?
Array sorting is both important and nontrivial subject, and its place in the library is justified (similar to the situation with C).
BTW, I don't understand why your for-loop runs backwards (which makes the code look awkward to me) or why you have to define opp in the loop body. Just define len(a)-1 as a variable in the initialization and be done with it.
My example above is the semi-official one from https://github.com/golang/go/wiki/SliceTricks. The `oop` expression contains a reference to i, and so it needs to be in the loop body. I'm not sure why they opted to do it in reverse though. (Maybe they don't want to compute `len(a)/2` every time, and don't want to use a temp variable? Not sure if it would get optimized away.)
In my head there are three reasons (apart from my own laziness) that I like having reverse() in a language's standard library:
- Code is read more often than it's written. A for loop like this takes time to read, if you don't already know what it does.
- Tricky loops hide bugs. If we forgot the `-1` term in the initializer, I'd probably miss it in a code review, and the bug would only show up for even-length lists.
- Expert attention turns out to be useful here! In languages that check array bounds by default, you can gain a little speed by avoiding bounds checks in reverse(). Rust does this (https://doc.rust-lang.org/src/core/up/src/libcore/slice.rs.h...), but I wouldn't want an `unsafe` block like that in code I had to copy-paste around.
Using 3rd party code for "basic" stuff only makes sense to me when it's a tricky algorithm to get right (such as quicksort) and the author of the 3rd part code is a renowned/reputable top developer. I definitely don't trust the b+-tree implementation of some random dude on github(which what javascript people do mostly).
No idea who wrote that piece of code, but you can simply define it without the -i part, and write a[last-i] = a[last-i], a[i] in the loop (and better not call it "oop" ---whatever that means). That way, it's very readable and understandable to me:
for i, last := 0, len(a)-1; i < len(a)/2; i++ {
a[i], a[last-i] = a[last-i], a[i]
}
I still don't see anything in what you wrote that justifies adding a new built-in function for a trivial operation such as reverse, or generics to the language as a whole.If profiling shows that bounds checking in reverse() is a bottleneck in your program (although it's very difficult for me to imagine that this will happen a real-world program), then you probably don't want to use that unsafe code went through "expert attention".
While being a mortal without any specific degree on array handling myself, in the unlikely event that I find reverse() to be a bottleneck in my program, I'd rather write an assembly function which makes use of SSE2/AVX2 to get real speed-up (note that LLVM can't autovectorize that Rust code for you, that code needs a rewrite it you want vectorization).
It has become the default Go-To (pun intended) language for me for almost anything that needs to be small and portable.
However, I don't see myself writing a full server with it, I would still prefer a dynamic language like Ruby/Python for that and use Go for micro-services CLIs and the rest.
For example:
Our main application is Rails, it communicates with SOLR as the search index, in between the application and SOLR there's a proxy server that backups the documents onto S3 and also does Round-Robin between slaves.
One other thing is that we use Go to communicate with all external APIs of 3rd parties, the application code is rails and it communicates transparently with a Go server that fetches the data from 3rd parties and responds to the main application.
It doesn't make Go a bad language,it has a some good percs, it's just frustrating that its authors conflated simplicity with rigidity. Also I hate when languages have hidden APIs, i.e. things the language can do that the programmer can't. Go is full of these (for instance append which is a parametric function since it knows the proper return type no matter what type of slice you pass it, but you can't write your own? ).
It's good think that it requires very little investment to get started, but it becomes highly frustrating when one stumbles on its limitations.
To me, the power of Go's simplicity is almost always underestimated by the language's detractors. I can look at code my team wrote two years ago and with a few <leader>gd's in Vim I know what's going on. Obviously Python fails this test, but even a high-level static typed language like C# can suffer greatly from all the magic one can invoke (Linq being a great example).
What it comes down to is that Go doesn't give you many ways to be clever. Younger me who loved template metaprogramming in C++ would scoff at this statement, but if you go back and have to reverse engineer your own cleverness enough times you really, really start to dislike the practice.
(C++ uniquely bites you at both ends :)
Finding out, with absolute certainty, which code calls which code under which circumstances is a life-saver.
Any modern IDE for JVM languages accomplishes that.
It's not enough for your code to be readable. It needs to be statically traceable.
I completely agree with your overall point, but typically reflection will inhibit truly 'absolute' certainty.
All of my lambda functions are a thin Node wrapper on top of Go applications.
The go application is simply a command line accepting JSON via stdin (from the Node wrapper). It is a Joy to test, you can run it locally/independently etc...
[Edit]: Typos fix
https://github.com/KensoDev/sns-lambda-notifier-golang
It's simple enough to understand with absolutely no documentation. But here's the gist.
You develop in Go, you can run tests or run it independent from the lambda and then, when you want to deploy you run `release.sh`.
This is perfect for web callbacks, SNS notifications etc...
It's amazing how good they perform with minimal memory usage.
In this blog post the previous solution is presented using Nginx, now it's Golang similar to Templar (mentioned in the post).
> GDB does not understand Go programs well. The stack management, threading, and runtime contain aspects that differ enough from the execution model GDB expects that they can confuse the debugger, even when the program is compiled with gccgo. As a consequence, although GDB can be useful in some situations, it is not a reliable debugger for Go programs, particularly heavily concurrent ones. Moreover, it is not a priority for the Go project to address these issues, which are difficult. In short, the instructions below should be taken only as a guide to how to use GDB when it works, not as a guarantee of success.
I've only used it for simple cases, so I don't know if it helps with your criticisms, but it was designed for Go. I mention this because it seems like many gophers aren't aware of Delve.
The reality is that I don't miss it any more, for two reasons.
1. I have been forced to write solid comprehensive testing. Its a pain, but the pay off has made it worth while.
2. Because you never find all the bugs anyway, instrumentation and logging has become part of everything I do. A framework like go kit can do this out of the box for you or function as a guide for you.
There's also a go frontend to GDB that's okay, but going native is going to be a better choice in the long run I think.
What just happened?
In just a few simple transformations we used Go's concurrency primitives
to convert a
- slow
- sequential
- failure-sensitive
program into one that is
- fast
- concurrent
- replicated
- robust.
No locks. No condition variables. No futures. No callbacks.
It's the ability to make these kind of transformations effortlessly at any level, whenever I need to, that make me appreciate choosing Go when solving many tasks.I'm sure the author means there's no explicit locking done by the programmer, but readers should be aware that channels are actually implemented internally using locks (which are 4x slower than using a sync.Mutex yourself).
Is that for both buffered and non-buffered channels?
[1] http://www.jtolds.com/writing/2016/03/go-channels-are-bad-an...
Also perl is apparently as fun for humans python which I also find suspect after maintaining perl 5.x code.
Turns out this subjective made up graph is subjective and made up I guess.
When people talk about a language being 'fun', they need to distinguish between writing something new for the first time vs maintaining something or figuring out someone else's code.
Sometimes I mumble under my breath that Ruby is Perl for the 21st century - gleefully creative hackers leaving behind overly clever code for far less happy developers to deal with.
A culture of optimising the elegance of the API over the simplicity and maintenance of the implementation.
Source: Maintained a 300 kLOC Perl application for 3 years, now working with legacy and new Rails applications.
I'd also add D (above C++, level with Java) and Rust (above C++, close to Go).
FWIW, here's the Go project lead congratulating Rust on their recent birthday: https://twitter.com/_rsc/status/732379957129826305
I think what they were trying to show is whether languages are high or low level (i.e. how far are they from machine code). In C for example every statement (maybe except switch) you can guess what assembly code it would translate to. Not so much with languages on top.
Solution: design the language for large code bases
This seems crazy but whatever works. I would assume that would only buy you some wiggle room inside whatever order of magnitude of committers you have. It seems like eventually you would need to split up the code base if you are having contention issues.
The person truly had a java supremacy attitude that was very difficult to deal with. Golang is a kind of shift in thinking that you have to first unlearn your existing ways of thinking and then you will have a place for it. Some people are not willing to take that leap of faith unfortunately.
Unlearning is not always acceptable, especially when you have to unlearn sound and proven practices, which Go often requires to do.
I think it really depends where you're coming from: people coming from dynamically typed languages like Python and Ruby are quite happy with Go since it's a small ramp up on the type ladder, but anyone who's used to static types and generics will usually see Go as a step back and refuse to take that step (for good reasons in my opinion).
To draw an analogy, imagine a Go developer is being asked to switch to Python and in order to convince them, you tell them they just need to unlearn a few things. To them, you are asking them to give up types and other practices that makes their code more robust, so it's not an acceptable argument.
Such as? I'm not really sure what "sound and proven practices" a Java developer would have to "unlearn" to adopt Go. Most of the differences between Go and Java amount to removing features that 20 years of Java experience have proved to be unsound or unnecessary (inheritance and exceptions, for example). From a feature perspective, Go is mostly a subset of Java. The features Go adds are mostly related to concurrency, and I've not heard anyone say Java does concurrency better than Go.
Yes, it is simple, and you can learn it fast, you also can also communicate with it, but you will often have to fight with the language to express what you want. That person generally won't be satisfied.
Go's shortcomings wouldn't be so bad if in exchange, the language would ensure that your code is less prone to errors, but that doesn't seem to be true. In fact Go programs from my experience appear to be slightly below average in terms of stability and robustness compared to other statically typed languages.
The only shift I've found is moving on when the Golang way isn't as good as other tools you are used to. Because the ecosystem & language really are not on par with other environments I've worked in.
Right tool for the job is a better flexible mindset. If you are a master painter, you could paint something amazing with anything you have got. Same thing applies to programmers.
I think any language one it reaches a critical mass attracts people who are not problem solvers but memorizers. There is a correlation between people who rely on copy pasting existing code and SO answers and people heavily invested in their language.
Point being most people who have trouble adopting other languages tend to be memorizers vs problem solvers and become insecure when working in a poorly defined environment. Pulling them into something new after others have solved the hard problems and created best practices tends to be easier and more productive for everybody.
All it talks about is clarity (important but not the only important thing) and I just don't see how any of the left-out things are inherently unclear. I think you can write clear and unclear code alike with all of those left-out features.
> Go differs from Java in several ways
> Programs compile to machine code. There's no VM.
This tries to imply that having a VM is a bad thing.
> Simple, concise syntax
The syntax is simple, but not overly concise. For example the lack of generics leads to a lot of repetition.
> Statically linked binaries
You can have them with Java, too.
> Built-in strings (UTF-8)
Should this suggest that Java doesn't have trings?
> Built-in generic maps and arrays/slices
Yeah! Some of the most awesome things about Go is the limited set of data structures and the limitation of generics for exactly this few structures.
> Built-in concurrency
It is questionable whether this is good or not. There are a lot of good concurrency libs for the JVM.
> Sometimes this means writing out a loop instead of invoking an obscure function.
This is completely strange! The lack of abstraction is sold as a good thing. Actually a lack of abstraction leads to redundant and error prone code.
What net value add a VM (appart something more to handle) ?
> Should this suggest that Java doesn't have trings?
as long as you stick with basic multilingual plane you can consider that java strings are ok
> It is questionable whether this is good or not. There are a lot of good concurrency libs for the JVM.
Concurrency in the JVM is hard to have right
Maybe with the upcoming AOT compiler in Java 10, more people will become aware of it.
Sadly it appears to be a commercial feature.
Is there a widely available FOSS implementation of this?
* Static typing is good.
* As I expected, the standard library and other packages available had the http & routing stuff I needed, which is all good.
* I like that errors are specified in function signatures, unlike exceptions in languages like ruby/python.
* I don't like errors being easily ignored, and return values being assigned default or arbitrary values. I once may have also accidentally used the wrong equality operator against nil.
* Defer is nice, but would be better if it was based on current {} scope.
* Append on arrays? has very bizarre semantics sometimes mutating or returning a different reference.
* Initially I ran into trouble reasoning how to use some sql package and ran into "invalid memory" deference issues or some such when passing a reference. Thus, I'm skeptical about "memory safety."
This was only a simple program though and turned out to be worthwhile for me in the end.
- many mistakes are silently ignored. If you mistype object field name, divide a number by zero, add number to a string, access missing array element, no error is raised
- no proper OOP and classes
- no type hints for variables, function arguments or return values (well, there is TypeScript but it is another language)
- package manager (npm) loves to create deep hierarchies of folders
When you want to hire good developers pick Erlang, Elixir, Rust, Haskell, ML, LISP. Because chances they went out of their way to learn the language as it is not taught in US universities in depth. They are probably curious, good learners and could probably learn or adapt to other new things thrown at them.
I am at shop were we use Erlang and syntax has not phased new people that much. If typing . instead of ; is a big deal, then what are they doing to do when a netsplit hits or they have to understand other concurrency issues.
I don't know, I find Erlang's syntax rather nice, if anything it tells my brain "this is not C anymore, don't think like C". Works for me, any way.
There is Elixir of course if syntax is an issue. Elixir has other useful features as well but still runs on the same battle proven platform.
Edit: fixing typo. Pay -> play
The only languages that don't attract prima donnas are the "not hip" ones like Java, C++, C#, Perl, etc.
That's the kind of person you want to hire anyway, unless you are super crunched for time in getting someone up to speed.
It is indeed hard to hire mediocre developers for Erlang: they stay away from FP.
(shrug).
> Just call into a C lib from Erlang.
That's easier said than done. Certainly possible, but it's not quite as easy as just linking and calling.
But, it does seem that there are not regular blog posts about how to drop into C to make even the worst scripting language performant. Seems like maybe it's a dying art???
Erlang is a bit different though: if you're really concerned about being 'robust' with it, you don't want to link in some random C code in the main node. Not only could it crash, it might simply block for an unacceptable length of time, messing up the system's internal scheduler and making it unresponsive to events.
So with Erlang, to do things properly, you need to get the architecture right as well, which makes it that much tricker.
Erlang is bad at that.
http://20bits.com/article/erlang-a-generic-server-tutorial
That's just ridiculous. Erlang looks like php and python had an unholy child.
But seriously, the syntax is not that big a deal once you've understood it (and being permeable to the history behind it helps).
I wonder what unit is being counted here. I don't think it's possible to actually review and rethink 50% of what has been created before. That's just not sustainable.
That's an enormous amount of manpower.
If you add code and revise 50% of it every month, the code base is bound to grow and the share of time spent on maintaining the old code grows as well until development of new code grinds to a halt.
Unless of course there is massive growth in hiring. But that isn't sustainable.
[Edit] Well, I forgot one possibility: Deleting code.
(Can't vouch for accuracy.)
I would not adventure to say state-of-the-art schedulers would not have been possible without Go, but for sure Go fits the requirements pretty well.
AFAIK Mesos is mostly written in C++. Aurora - a Mesos framework & scheduler from the same folks is written in Java & Python.
My target machines range from i7s with massive amounts of RAM to Raspberry Pi with slightly-less-massive amounts of RAM.
In a situation where Go is acceptable (i.e. GC is acceptable) you should probably be looking at OCaml (probably what I'd recommend; http://roscidus.com/blog/blog/2013/06/09/choosing-a-python-r... may be worth a look) or Haskell rather than Rust though. If you're talking about a long-running server process then I'd add Scala/Ceylon/F# to the list.
Rust: Best suited for writing OS, network stack, embedded systems, and webservers like Nginx.
Go: Best suited for writing micro-services, CRUD apps, API servers etc
pick your poison
If you want to go build a CRUD app, use RoR/Django/Whatever(tm) and be happy with it
Don't use rust if you're asking that question.
If you could implement your solution in go or rust, then go is probably a more appropriate choice; it's a good high level solution for high level problems.Rust is not a good solution for high level problems; it's a good solution for low level problems where go would be a terrible choice; and it's a good solution for high level problems where other choices are even worse (eg. C++).
They're both good languages, and you'll learn way more from picking up rust than you will from picking up go, so if you're just screwing around and want to learn a language this year, absolutely, pick rust or clojure. Go isn't on the list for 'interesting programming languages'.
...but if you have an actual problem you're trying to solve, I would be hard pressed to enumerate the reasons why you would pick rust if the problem was solvable using go. Maybe because your C dependencies would be easier to call from rust than go? That's all I can think of.
Who is saying that ? Not the Rust team, nor the Rust users … Rust is a general purpose programming language, and it's pretty high-level (in terms of features, think about functional programming for instance). The only reason I wouldn't advise everyone to write their stuff in Rust atm, is the youth of the ecosystem (which is growing rapidly, but is still a bit too early-stage): their is no intrinsic limitation in the language that make Rust «not a good solution».
The piston developers are doing what right now? Writing a new programming language (dyon). Why are they doing that? Because rust is great for prototyping games in? no.
...rust is verbose. It is statically typed, it is less productive than some other languages and it is hard to learn.
Now, you get a whole lot of other benefits in exchange for that, absolutely, and technically speaking, rust is a super awesome and sophisticated language.
...but right now, it has neither the ecosystem nor simplicity for picking up and practically solving high level problems.
If you have a problem, right now, you want to solve: pick go.
...unless your problem is something that rust would be better at, and those things are low level things, like building game engines, not high level things like building web applications and cross platform desktop chat applications or machine learning solutions to driving cars.
You can build high level applications in rust, and in C++; the point I'm making is that unless you actually have a reason for picking them (and there are plenty...), don't.
Pick the tool for the job; rust is a great tool for the right job.
Go is a better tool for a lot of applications; and a totally useless one for others.
/shrug.
We don't need to pretend rust is general high level language you should pick up and use for any problem domain. It's not. You're shooting yourself in the foot if you use it as though it was.
I agree with that, Rust is not a scripting language. Dynamically-typed scripting languages have proven their efficiency for prototyping.
> rust is verbose. It is statically type, it is less productive than some other languages
Than scripting languages yes, but it's exactly on the same side than Go on this point. Scripting languages are extremely convenient for small projects, but are more difficult to maintain in the long run if the project grows too big. (I personally live coding JavaScript, and a the project grows we are progressively add a static-typing layer (flowtype.org) to our code for the sake of maintenance).
> it has neither the ecosystem nor simplicity for picking up and practically solving high level problems.
There is a real trade-off between scripting languages (Python, Ruby and Nodejs), and statically-typed ones (Java, Go, and Rust), but it's not related to being high-level or not. In term of abstractions and features, Rust is at least as high-level as Java & Go.
> If you have a problem, right now, you want to solve: pick go.
We are using some Go at my company because we wanted to follow the trend, but frankly unless you want to built a simple system with no dependencies, Go is not ready to solve problem «right now» either, because the ecosystem is still really poor. If you have a problem, right now, you want to solve, you should probably still pick Java over Go, even if a lot of people (me included) don't like Java … Basically I think Java is the most important factor of success of the Go language: Go feels like Java, but in a younger and trendier way.
> We don't need to pretend rust is general high level language you should pick up and use for any problem domain. It's not. You're shooting yourself in the foot if you use it as though it was.
Rust is a «general high level language», with the same high-level generality than Go or Java.
I bet one can chose any* Go or Java code sample, and rewrite it in Rust with around the same amount of code and without introducing any memory issues (what you wouldn't be able to do in C or C++). I think that's a good illustration of Rust being a «general high level language».
*unless it depends on a library that has no equivalent in Rust (as I said before, the youth of Rust's ecosystem is the reason not to use Rust in S1 2016).
> and it is hard to learn.
It is indeed, no discussion about that.
When you need to write high performance code this is a great maxim. I enjoy the simplicity of Go and the guarantees it provides. Being able to reason about code and not having to guess is a win for any development team.
1. Slices make it hard to reason about aliasing. bar = append(foo, val): does bar now alias foo? The answer is the worst possible: "sometimes."
2. Closure semantics make it hard to reason about thread safety. I converted this serial loop to parallel using goroutines; did I introduce a race condition? I have to look at each variable to decide. (Any sort of const capturing would go a long way here).
3. Goroutine leaks can be hard to reason about. For example, a channel that is not sufficiently buffered can result in a leak.
4. Nullable maps and channels reduce clarity.
5. The "redeclare" semantics means := sometimes does not introduce a new variable
Thanks for writing up these common mistakes.
I find append's semantics to be pretty intuitive. But then again, I'm familiar with realloc in C, which is where it came from. At any rate, slices are references to an underlying array. If you are making one slice from another slice in a way that potentially doesn't involve copying, you should expect the new thing to alias the old thing.
People often complain about channels having limited buffer sizes. But if channels had unlimited buffering, they'd complain about memory leaks and inefficiency.
A list of common mistakes in Go would be interesting. It would probably start with the "assigning a typed nil value to an interface leads to interface != nil" wart.
I love the "strictness" of the language - for example the code won't compile if you declare a variable and not use it, or import a library and not use it. I love that there is a standard gofmt which means code auto formats to a standard format. These features really help set some "discipline" when working in a team.
I love the way concurrent code can be called easily and the use of channels. I love the performance - it has been more than fast enough for my use cases so far. I love that I can get started with an HTTP server using just the standard library, and the most popular web frameworks in go are micro frameworks.
Overall, there's a kind of a simplicity about the language that underlies all of the above things, and that is what makes me excited about go.
I have used go in some minor projects that have been running peacefully for months without any hitches, and am using it in a big project mostly in the form of microservices and scripts. It has become my favorite language now.
I can't help but think this is specifically a dig in C++'s direction. Since C++11 lambda's I've been using <algorithm> a lot more and I don't think you could get me to go back at this point... Yes I had to learn exactly what a few methods do, but now I have beautiful straight line code...
It's actually kind of nice. Until I did this the first time, I hadn't realized just how much bullshit I had previously put up with, with setting up local web servers, trying to get configurations down, etc., etc. At some point, I think most web framework's configuration options just got too complex to be considered configuration options and became weird, poorly defined scripting languages for defining web servers. Having a real programming language to do that instead is just a wonderfully smooth experience.
Some things I plan on implementing with it:
* local file system access, to ultimately implement an FSN [1] clone in my WebVR project.
* my own Leap Motion WebSocket service, because the default one doesn't use the latest Orion beta and its associate JS library is complete garbage.
* A similar dude for MS Kinect data.
* Ultimately, get the previous two to run over WebRTC instead (not easy, there is no WebRTC library for Windows outside of major browser implementations) to be able to stream their respective camera data.
* Live raytracing of model textures for baked lighting in scenes in the WebVR session.
Right now, it's just a source file I drop into a standard C# console project. I'm thinking about making it a full-on library, though at this point there isn't much need.
Would love to play around with this
Go is great for actor based systems where you model things using channels and goroutines for what they stand conceptually - not when you use it to simulate Task.WhenAll/Promise.all with a timeout.
I think _that's_ what they should be selling - that your server's architecture should typically be different.
[1]: http://journal.stuffwithstuff.com/2015/02/01/what-color-is-y...
They look good, but completely failed to work on Firefox for Android.
Other than that, it really depends on what the server is for, but in general I would say Go is probably a better choice.
If you're interested in something similar to Swift for the server, I think Kotlin w/ Spring Boot would probably be a safer bet at this point.
We used Go at Hailo for our microservices platform and it served us incredibly well. I've gone on to create an open source project called Micro https://github.com/micro/micro that builds on those past experiences. It's just a joy to write micro services in Go.
Main pros for me there are:
- Easy to cross compile and deploy
- Daemons often need to do a lot of communication (some also for providing web APIs) and need to embrace concurrency. Both are covered very well by Go's ecosystem.
- Compile-to-binary eases distribution concerns in cases where you want to avoid to publish all source code (and thereby know-how) compared to VM languages or scripting languages.what i like the most about golang is that the end result is a binary where my production server doesn't need to have any dependencies except for the ability to run elf binaries. i like having this option, but in reality the binary size gets pretty unwieldy for upload, so i actually end up doing a pull on the source code, compiling and starting up.
package management has not been a problem for me.
i do find html template packages to be a bit deficient, amber, ace, there are ports of haml and jade, but they all seem pretty half baked. i had to have a lot of hacks in my code to get this stuff working.
also sucks that there isn't a standard orm, but i can hang and keep up with raw sql.
the language expressiveness is not as convenient as say ruby, but it's pretty close.
Perfect example for this is Hashicorps products, taking out Vagrant it is 100% written in Go.
Having a single executable tool that you can download and run anywhere is super powerful. You develop once and you build it for every system. It's the definition of delight to me.
Most of the things purported to be major wins for Golang on the server side are available or better in other environments.
For CLI programs that need to be a little more sophisticated than bash Golang is quite nice.
Unrelated: Rust would probably be around the right-most area in the horizontal axis, close to C and C++, and a little below Go in the vertical axis.
With Go you'll basically have to rewrite asp.net from scratch if you're used to that, because frankly the ecosystem is poor if you don't stick to data transformation/ marshaling with an HTTP server. No full featured ORM, no good Logging library, no Razor like view layer, piss poor web frameworks and an extremely rigid language with a rigid type system if you are used to F# and C#. The only advantage of Go is the fact that you can deploy a single executable with no dependencies on a server. That's it.
That being said, I still wonder what types of applications are so suitable for Go that people decide to use it instead of other languages?
I love Go and used it to build some very useful web hook and CLI tools. It just doesn't lend itself to something where you expect to have a vast set of APIs under one Go project.
- using case of a first letter of identifier as a public/private flag. You end up with half names starting in a lowercase letter, half in an uppercase (the code looks inconsistent) and forgetting how to spell them. And having to rename the function everywhere when you decide to change it from private to public.
- no official package manager. Unclear how to add external libraries to your project and how to set specific version you need. I ended up adding necessary files into a separate folder in my project.
- Go manual suggests you have single directory for all projects and libraries. That was inconvinient because I develop on Windows and use Linux only to test and run code in /tmp directory, I do not keep the code there. And why would I want to keep unrelated projects inside the same directory anyway?
- no rules how to split contants, types and functions into files and folders. For example in PHP there are certain rules: each class goes to its own file and you always know that class Some\Name is stored at src/Some/Name.php. Easy to remember. And in Go you never know what goes where. Large projects probably look like a mess of functions scattered around randomly
- no default values for struct members, no constructors
- no proper OOP with classes
- standard library is poor
- open source libraries you can find on github are not always good. I looked for library to handle config files and command line arguments and didn't like any.
- standard testing library doesn't have asserts
- easy to forget that you need to pass structures by pointer (in OOP objects are passed by reference by default). And generally use of pointers makes the code harder to read and to write.
- weird syntax for structure methods. They are declared separately from the structure.
- go has 2 assignment operators (= and :=) and it is easy to use the wrong one
- having to check and pass error value through function calls instead of using an exception. So most of functions in your code will have two return values - result and error
- no collections library
- simple things like reading a file by lines are not so simple to implement without mistakes
- static typing is good but sometimes you cannot use it. For example I wanted to have the options in a configuration file mapped to the fields of a structure. I had to use reflection and every mistake lead to runtime panic. And you cannot use complex types like "pointer to any structure" or "pointer to a reflect.Value containg structure" or "list of anything" or "bool, string or int".
Of course Go has also many good parts that might outweight its disadvantages but I am not writing about them. For example I have not used goroutines but they look like a simple solution for processing async tasks or writing servers.
I think Go is not ready yet for writing large applications. It might be ok if you write a small utility but I cannot imagine ORM like Hibernate or web application written in Go.
Also I took a look at the code in the presentation. I wouldn't want to write such code. For example, here https://talks.golang.org/2016/applicative.slide#20 they use static methods (http.HandleFunc(), log.Fatal()) instead of instance methods. So you cannot have two logs or two servers. Using static methods everywhere is bad especially in large applications. Google itself uses Go only for small utilities like simple proxy servers.