Go for C++ Programmers
github.com
github.com
That's only true for single-thread Go. Go is not memory-safe in multithread mode, because exploits using race conditions are known.[1] This, incidentally, is why Go is locked down to one thread when running under Google's AppEngine.
Go is a good language for server-side web work - all the expected libraries are there and in good shape. That makes sense; that's why Google had Go created. Go is a good option when Python and Javascript/node.js are too slow. But Go's concurrency isn't as clean as its enthusiasts claim.
I'd recommend Go for programmers coming from the Javascript/Python/Perl world. Although Go is a hard-compiled language, it's surprisingly similar to the scripting languages when writing routine server-side code. C++ programmers will find Go easy, mainly because it's garbage collected.
(The replacement for C++ will, if we're lucky, be Rust. Rust has roughly the complexity level, headaches, and gotchas of C++, but it catches all the memory-related bugs at compile time. Rust isn't ready for production use yet, though. Give it a year.)
if (i < (int)container.size())
This is because container.size() returns an unsigned type, and I try to avoid unsigneds in everyday code, and I like to use -Wall -Werror which, amongst other things, produces errors for signed/unsigned comparison warnings.I don't want to have to make the variable "i" unsigned, because using unsigneds for anything other than bit arithmetic is quite hazardous in practice (http://soundsoftware.ac.uk/c-pitfall-unsigned).
How do others resolve this problem?
I'm guilty of a few C-style casts, but certainly prefer catching things at compile time than runtime. So +1 unsigned types for me. At least the compiler helps with catching signedness issues.
$ cat unsigned.cpp
#include <iostream>
void f(unsigned int x) { std::cout << "x = " << x << std::endl; }
int main()
{
f(-1);
}
$ g++ -Wall -Wextra -Wconversion -Werror unsigned.cpp
$ ./a.out
x = 4294967295
No error, no warning. The two are not really distinct types. See the link I posted above for more argumentation along these lines.You should not care about signed/unsigned, use auto.
I find I have to do this quite often, and I'm not going to write static_cast<int>() every time.
Yes, I can see why this isn't a good idea -- I'm pained by it myself. I'm just wondering what I might have overlooked among the possibilities available for this kind of code.
For example, assuming 64 bit, suppose i is 0x1000 and container.size() is 0x100000fff. Now (int)container.size() is very likely to be 0xfff, meaning i is greater, and something goes wrong.
Or - and this would be very likely true for 32 bit systems as well - suppose container.size() is 0x80000000. Now (int)container.size() is -2147483648, meaning i is greater, and something goes wrong again.
A better option would be (assuming size_t is at least as wide as int, which is vanishingly unlikely not to be true on modern systems, and can anyway be checked for using a static assert) i>=0&&(size_t)i<container.size(). Then you know the cast won't produce nonsense.
Maybe I need a little helper:
template<typename T, typename C>
bool is_in_range(T i, const C &container)
{
if (i < 0) return false;
if (sizeof(T) > sizeof(typename C::size_type)) {
return i < static_cast<T>(container.size());
} else {
return static_cast<typename C::size_type>(i) < container.size();
}
}
then if (is_in_range(i, container)) ...The "exploit" rsc is referring to here is hypothetical.
To wit: if there existed some service (like multithreaded GAE, or an especially weird browser) that allowed content-controlled Golang code to run, that code could exploit mutability to violate assumptions made by other code, in much the same way as you could by dropping down to "unsafe" in Golang and Rust.
For that vulnerability to matter, you have to suppose a system that rigorously constrains the runtime to block system calls, containerize I/O, shut off the "unsafe" APIs, and somehow fence off state for crypto. Nothing does that. Real-world systems that allow users to upload arbitrary Golang code give up on protecting the runtime, and use OS-level protections to maintain integrity.
I agree that Golang isn't a great fit for C++ programmers. If you're still writing C++ in 2015, it's because you're productive using all the bells and whistles C++ provides. Golang is very much a one bell, no whistle language.
Google AppEngine does exactly that.
This is not an attractive statement to C++ programmers like the author probably imagines it is. We like being in control of our memory. C++ programmers who would prefer to not manage memory have probably already switched to Java or C#.
EDIT: Personally, I would start in something like Haskell or Scala just to do a proof-of-concept without having to worry too much about undefined behavior (C/C++) or absurd verbosity (Java), but then I am pretty familiar with those two languages. Maybe it would be worth learning one or two very terse languages to start with, just in case you hit upon a great idea? (Btw, I think Python or Perl qualifies.)
EDIT#2: As a sort of second or third order bit of advice, I'd encourage anyone to brush up on programming languages that might make you faster. It's a sort of "propellant" and can increase your speed exponentially.
Still, Go is far faster than what most people use on the web.
Performance: Go vs Python - http://benchmarksgame.alioth.debian.org/u64q/compare.php?lan... Go vs C++ - http://benchmarksgame.alioth.debian.org/u64q/compare.php?lan...
Scala I'm not familiar with.
C++ is great. Very fast and powerful, and really not as complicated or difficult as people make out. The manual memory management thing isn't really an issue if you do it right. However writing multithreaded C++ code is never fun.
Go is very simple and easy. I think of it like Simple English. It's very easy to write, and everyone will understand what you are saying, but you'll end up being way more verbose and often a bit more clunky than you might be in a more powerful language like C++. Huge limitations are that there is no overloading at all. I.e. you have to implement `minFloat64(a, b float64)`, `minFloat32(a, b float32)`, `minInt(a, b int)` and so on, whereas in C++ function overloading means it is just `min()`, and templates mean you only need to write it ones. The other big issue is lack of templates (AKA generics), so containers (list, map, etc.) are a pain in the arse to use.
However Go does have great concurrency support, and is close enough in speed to C++ that I'd probably always choose it to write servers in.
So I'd say Go, maybe C++. In a year reconsider Rust.
In go, the std library offers very good support, and if you need more, there are things such as gorilla (a web toolkit that enhances the std lib). There are also frameworks, of course, but many people find there is much less of a need for that.
The goroutine support is really great, and servicing concurrent client requests with them is effortless.
If your performance (throughput and latency) requirement is not very critical, language really doesn't matter. Even scripting languages like Python, Javascript or Ruby performs very well by spawning servers on each cores.
But if your performance requirements goes serious, I believe you will get unusual bottleneck (e.g. GC, VM, memory usage pattern, specific hardware,... ), then you'll want a kind of "full-control". In this case, the only traditional choice was C/C++, and that's why many large-scale companies like Google and Facebook are using C++ internally.
Anyway C/C++ cannot provide enough level of safety that required to provide good productivity. As a workaround, you can use a sort of dynamic checkers (sanitisers), but the dynamic checkers are very immature, and fundamentally dynamic.
A new, and the only current alternative for this case is Rust. Rust provides far batter safety from first at "compile time". It also provides far better linguistic constructs and semantics. But the language itself is immature.
Anyway, (1) there is huge demand for this kind of features from C++ community and (2) Rust is completely engineer community driven (3) and fully open-sourced. So I expect the maturing speed of the language will be incredible that never been existed in language history. And it's fully open sourced.
Now, don't get me wrong. I actually like Go for the things I use it for: replacing Python.
What bugs me most is this popularity contest. For example, the idea that go will go mainstream and writers of the future will write about people that did keep a straight face when explaining what you said. You know how people unwittingly revise history. This field has too much fashion going on and not enough engineering.
So is it just that the subset of applications that still get written, for some reason, in 2015 C++ are heavily dependent on specialized Sort implementations? Or is it instead the case that really Sort just isn't that big a deal?
It's pretty easy to look around briefly and see that a fair amount of ambitious stuff is being built in Golang. Somehow, they manage to do it without sum types and generics!
So people were productive without higher level abstractions, but then they moved on.
Likewise, people were once productive using languages without generics during 60 - 2004(Oberon, C, Java < 1.5, Turbo Pascal, Modula-2), but then they moved on.
I remember having to fight to use this new strange thing called C++.
Programming language design is all about tradeoffs. The makers of Go went for simplicity. There are pros and cons about their approach. What do you do when you run into something like this? You put your head down and work through it, like I have done every time I've had to write those three functions for sorting something in Go.
We can talk about the cons of an approach without having to point out that people work through it. After all, it's pretty easy to look around and see that a lot of ambitious stuff is being built in C. Somehow, they manage to do it without memory safety and generics.
So I'm not sure I agree on your first two points. For me, lack of exceptions and generics means Go code is at least as verbose as Java, if not more so. Multi-threadedness is a wash for me; channels vs fork-join and executors are just not that different.
I think Java can produce native code today, but it isn't worth it for most scenarios where you would actually use Java. I think we'll see that change if Oracle ships an AOT compiler in "official Java".
http://cr.openjdk.java.net/~jrose/pres/201502-JVMChallenges....
Slide 12.
I do not use exceptions in C++ so that was not a big change for me. Our code needs to be relatively deterministic (even though we are not hard real-time yet) and exceptions hamper with that goal.
I incorrectly used the word "multi-threadedness". Concurrency in go is very straightforward. Channels are extremely lightweight and are different from forking (which creates a new process with its own address-space).
Available in Aonix, IBM J9, Jamaica JVM, Excelsior JET
Just because OpenJDK doesn't offer it, doesn't mean others don't.
But if you are used to generic programming and you think in terms of it, type handling in Go and might think it is a step backwards and Java might be close to what you'd want.
Even better, I think as C++, Rust is starting to look interesting. I am waiting for them stabilize it more (maybe get to beta 1.0 status), because I think it has some very cool things going for it.