Re: Moving from PHP to Go and Back Again
blog.breakthru.solutions
blog.breakthru.solutions
Today my language usage looks like this:
- Web services / APIs: Node.js [1]
- Front-ends that require easily modifiable templates and quick command line scripts: PHP [2]
- When I need speed and low latency for a network connected app: Go [3]
- When I need speed on an app that requires no network: C
[1] The promise chain asynchronous nature of Node.js makes it great for web services in my opinion. And the ability to easily have global variables that persist across connections for things like caching and pooling is a huge plus over PHP.
[2] PHP is very good at spitting out HTML and making web service requests, the performance is acceptable in most cases, and it is really easy for most people to edit, even people without a CS background. Likewise, for quick command like scripts PHP is unbeatable in my opinion. The tools it provides out of the box means most common command line tasks can be done 100% with the standard library. No package manager required. Though if you need to add packages PHP is pretty good about that now. Incidentally the fact the standard lib does so much is also one of PHP weaknesses. The standard library is a mess of inconsistently named functions and classes that grew organically over 20 years.
[3] I've saturated my loopback network interface on a non-trivial app on my Macbook Pro using Go. PHP and node don't even come remotely close.
Promise.resolve().then(() => Promise.resolve().then(() => {throw new Error('Problem')})).catch((e) => console.log(e.message));It is worth noting that this was pre-PHP7. Post-PHP7 the out of the box performance is similar or better to what Facebook did with the HHVM.
99% of all PHP software will be fine with a quadcore server with 4GB RAM, running a LAMP stack. This can be scaled as needed (eg moving off mysql, adding a reverse proxy, real load balancing).
As stated above PHP7 has similar performance when compared to HHVM which was made by Facebook. Additionally PHP has an amazing performance debugger by FB called xhprof.
PHP performance could always be increased hugely by making sure is cache buckets have enough memory (opcode cache, realpath_cache_size).
Secondly with any web framework your app will most likely be limited by IO (database, file lookups, networking) before it becomes limited by actual code execution performance.
If anyone's ever worked on a project where the performance problem was the language and not IO I'd be really interested in hearing about it, but in my career of making websites I've never ran into this problem yet.
> Additionally PHP has an amazing performance debugger by FB called xhprof.
xhprof is unmaintained for years. The official version does not compile with PHP7. Various forks exist, but the only stable fork has been rebranded and defaults to sending all the performance data to the branding company.
> PHP performance could always be increased hugely by making sure is cache buckets have enough memory (opcode cache, realpath_cache_size).
Always, really? The history of PHP opcode's caches is complex. Before PHP5.6 where Zend published their opcache+, I've seen the various solutions (APC and others) cause vicious bugs.
> Secondly with any web framework your app will most likely be limited by IO (database, file lookups, networking) before it becomes limited by actual code execution performance.
I've seen quite a few PHP applications that were CPU-bound, and that were far from Facebook's scale. For instance, the learning platform Moodle is popular with universities, but getting it to handle hundreds of concurrent users cannot be done on a plain quad-core server.
Another poster suggested load balancing as an obvious solution, but adding this is not that easy. E.g. Moodle has to track various files, including uploads. So once you add a load balancer and several PHP servers, you need to use a network mount for most of your files, which has a big impact on IO performance.
I'm not saying that other languages are better, because I can't compare the exact same large application in two languages, but PHP7 isn't an Eldorado.
That depends if you set up cachefilesd correctly. Many people think it's enough to do the NFS mount and that's it, but it's not - NFS's mount parameters have a big impact on performance, and having cachefilesd enabled can make performance go through the roof, especially with big files. Without cachefilesd the only caching is in-kernel memory, which can and will lead to files being evicted from the kernel cache...
Same for MySQL - having configured it correctly (or incorrectly!) can make a life-or-server-death difference.
All without having to touch PHPs configuration... there's a reason why a good operations guy is worth his weight in gold.
Out of 8 downtime events, 5 were related to NFS mounts.
Such "hacks" have hit too many too big firms for me.
Out of interest, what issues have you had with NFS mounts? I run a fleet of virtual servers with their disks on an NFS-mounted NAS share and backed by cachefilesd, never had a problem with that setup.
It may be worth mentioning that we had decent throughput with NFS. Roughly 10 writes per second (from 100kb-250mb) and 20 reads per second (IIRC).
We use rclone to do a daily backup from primary -> secondary cloud file store, and use a little wrapper function in app to switch which host we're pulling files from so it's not too hard to failover during an outage.
I do agree with you about vendor lock-in though, it's nasty stuff. At the end of the day it comes down to time allocation. I'm a one-man ops show with too many other things to do than to wake up with a Pingdom alarm at 3AM because of NFS.
Might have been worth a try to get a RHEL support contract, but if you're a one-man show and happy with CDN, then that's the better solution for you definitely ;)
First of all realpath_cache_size is unrelated to opcache and has always worked well. The only problem with that configuration is that the default is waay too low for modern frameworks.
Also I think GP meant that now you can always finetune the opcode cache. The current opcache is built into php 5.5+ and just works. It works so well that there are almost no competitors because there is no need.
We are working on separating the extension that powers our SaaS APM for PHP and the original xhprof callgraph profiler again into two extensions in the near future :-) Then the extension will still be branded, but it has no code related to sending data to our service and just the backwards compatible profiling API.
Latency is additive; it's a sum() operation, not a max() operation. Yes, a large fraction of most web requests get eaten by blocking on IO, but everything on top of that adds up, and small numbers add up surprisingly quickly. And the more you try to be smart about that stuff, whether it's optimizing what you query, do extra caching, try to turn multiple DB roundtrips into a single trip, you often just trade IO time for CPU time (albeit lower). You still care about CPU performance.
This! And you can only discard some components latency when it disappears in the deviation of another components much larger latency. In most PHP (or Ruby/Python/etc for that matter), this is not the case. They add some 10-150ms on top, and often the db calls are <10ms.
Performance does matter, and is hard to improve once you have many KLOC of code in a slow language. Hence FB spend big bucks on PHP performance improvements.
Most are <10ms. Those nasty few ones with 100+ms (or sometimes 10+s!) are where the best money is spent optimizing. However good query/db schema optimization is a skill many developers do not possess... which is why a good DBA is worth his weight in gold.
Our company's product is CPU bound, and our language (Python) is definitely inhibiting our ability to meet basic performance goals. I've done a few crude benchmarks and I'm confident that a rewrite in Go would buy us at least a tenfold performance improvement, although the benchmarks themselves suggest it's closer to 100-200X. Besides being faster out of the box, Go is also easier to optimize--better profiling tooling but also the ability to control memory layout, allocations, and dispatch. And that's all without parallelism.
In any case, the application is still CPU bound, thereby making it an example of a web application which is not IO bound, per the OP's request.
You can start with things like Cython which will give you a modest boost over plain python. I agree it may not be useful in your case, but doing full-rewrites are generally awful, abysmal and a nightmare all combined. Sure, there are cases where you must for various reasons, but they should be avoided if possible.
That's the beauty of doing something like an FFI with C/Rust/etc. You can iteratively move that direction, get code deployed faster and get your performance gains, while also slowly moving into a full-rewrite, but it can happen gradually and you get all the perf enhancements during the re-write, plus you get code deployed in production faster, so you can get all the code tested, and make end-users lives much better in the process of your re-write, instead of making them wait until the bitter end and then finding out that X, Y and Z undocumented features customers were using didn't get included in the re-write.
Anyways all that said, it sounds like you know what you are doing for the most part, so my advice here may not apply to you directly at all, and that's certainly plausible. But I think in general it's fairly obvious to experienced devs that re-writes are an awful plan.
I don't think there's a virtual machine in Go.
But if you're building a big old MySQL CRUD app full of complicated business rules, PHP makes a lot more sense.
/s ?
I'd argue Rust is the "better" C. Go is a "simpler" C, at the expense of expressiveness, features, speed (only noticable in very low level usecases) and applicability for certain domains (Go is primarily for networked apps).
In the same way Java wanted to be a simpler C++ (which came with it's own drawbacks).
And for me Go is more of a competitor to Java (as Java is mostly used for networked applications) than it is to C.
Rust loves zero cost abstractions, and isn't afraid to be complicated. It gives the programmer as much power as possible.
Go is simple and actually very fast. The garbage collector is probably the biggest hurdle for performance and it's still best in class. Definitely higher level than C, but not enormously so.
C was also king of the zero cost abstractions.
> and isn't afraid to be complicated.
C sure is not afraid to be complicated. But at the time it was huge simplification. I'd say Rust's complexity is not there for it's own merit, but has huge advantages (though not that visible in a very small project).
> It gives the programmer as much power as possible.
C, C++, Rust are all in that corner.
Go obviously isn't.
C++ has static dispatch classes, templates, constexpr, and macros. C just has macros. Any other abstraction costs machine code. C++ also offers a lot of low cost abstraction like RAII-style scoping.
>C sure is not afraid to be complicated.
Not sure in what sense you're talking. C is not complicated. It's low level. It's exposing complications in the underlying model of a computer. Example: pointers in C are not complicated. Understanding how they work may be for beginners, but that just reflects how hard it is to understand what's going on in a computer.
C is accidentally complicated where it is flawed; the non-orthogonal behavior with arrays and the syntax for function pointers are examples. Go fixes some of these flaws, which is unsurprising since it was informed by people close to the origins of UNIX and C (y'know, like, Rob Pike?)
>I'd say Rust's complexity is not there for it's own merit, but has huge advantages (though not that visible in a very small project).
Sounds a lot like C++. It isn't accidental or coincidental that it is a favorite for high performance but complicated stuff like game and browser development. This is no surprise since Mozilla wrote it to replace usages of C++ for memory safety and concurrency, not because C++ didn't offer enough. C++ is flawed in ways Rust isnt, but that doesn't mean the two don't share a lot of traits, and it was Not by accident. Complexity is one of them.
>C, C++, Rust are all in that corner. > >Go obviously isn't.
Since you've offered no reasons for why this would be true, I can't actually refute it. But it doesn't make a ton of sense. Go and Rust both let you shoot yourself in the foot literally as much as you want. Go directly facilitates assembly code and allows direct memory access with unsafe. Rust also does this. Go tries to be memory safe and provide concurrency primitives. Rust goes about this in a different way. I don't see where they significantly differ.
Rust differs most in it's superior memory safety model and low cost abstractions. Go differs most in it's simplicity and built-in concurrency. But they both feel close to their own origins.
> Go differs most in it's [...] built-in concurrency.
That was what I was driving at, as well as Go not being fit for writing a kernel in. Sorry being so inarticulate.
On the other hand, I'm glad things are turning out the way they are. Rust and Go are both filling niches that C and C++ didn't, in ways that they couldn't have. I look forward to Rust-based OS kernels, for sure. It seems like with time, we can build very resilient foundations with Rust that wouldn't have been possible before.
You can use atomics and syscalls and even assembly in Go to have complete control over the system in the same way that you can in C/C++. It's definitely not trivial to bypass Go's memory model and get raw access to memory, but you can do it if you want. I'd say that Go discourages you from doing so, just the way Rust discourages the use of unsafe memory access even though you can if you want.
This I see as a stark difference.
Wrt concurrency, Go is more like Node: one way to do it.
Seriously? That's news to me. Only C zero cost abstractions I know of are based on external code generators. Or some macro abuse, but that's rather limited way to create abstractions.
But then again, when you really need to understand everything that is going on, abstractions are often not helping you.
(I write kernel drivers and bare bones embedded, where memory measured in kilobytes, not megabytes.)
Also OOP in Go is perfectly fine.. it's just by composition only and without inheritance.
† Although they have their fair share of issues, this is not a jab at UML nor Java themselves, but the way things have been taught, terribly, for so many.
Some time later I learned Lua for fun and almost instantly understood what this whole prototype based programming / composition was about :)
TLDR: While I learned about composition at university, they failed to really show how it is used and what it is good for..
IMO it's much better to explicitly reference all mixins, and compose by reference rather than by direct inclusion, unless the composition has strong reliance on the identity of 'this' / 'self' in its implementation.
I have a vague working model of object orientation but a lot of the finer details go straight over my head.
I've heard other people speak similarly of learning Perl's MOOSE after already being familiar with non-OO Perl. This probably is no coincidence since MOOSE is heavily inspired by CLOS.
IMHO it doesn't matter much how much you read about the differences, until you get in there it won't do much good. This is a good place to have a throwaway project on hand, because your first try is likely to be a very big mess.
If you know an inheritance model and a non-inheritance model, you'll be well on your way to understanding the nuances because you'll have the experience in the field.
(For reference, my personal definition of OO is pretty much any language where you can write object.method(arguments), some kind of polymorphism is made available on that, and that is either the primary or a very important element of design in the language. It's a very expansive definition because I find that having massive definition debates about what OO is to be nothing more than useless flamewars.)
Which took C’s place for user space applications on Inferno, the last Plan 9 iteration.
Plan9 3rd edition was released June 7, 2000
Plan9 4th edition was released in 2002
This version went into continuous improvement mode, the latest commit in the tree was Apr 29 2017
And yet we keep writing Go.
By comparison, I'm a bit put off by the Rust community's evangelism, but that might just be my personal experiences with Rust community members.
Other languages usually need a large number of dependencies, with Ruby and Node, often an entire build environment, with plenty of potential for dependency hell and hours wasted.
Some may advocate containers at this point, but it just hides the issue temporarily and may be too much for a certain category of end users. You now need to know how containers, ports, volumes and Linux systems work in far more detail when you actually just want to use an app.
Turbo Pascal compilation speed, in MS-DOS, using 90’s hardware was already faster than Go.
There are lots of languages with modules support, with static linking and native compilation to choose from.
What relevance does this have on the compiler landscape today ?
If you have to use a compiler from ~30 years ago to find a comparison supporting your claim, it sounds very much like Go is indeed much faster than what it competes against today.
If you want the 2017 version of it, it is called Delphi. Beats Go in language features and compilation speed.
Go's compilation speed only surprises those developers that never used anything else beyond C and C++.
And beat 99% of other compilers today, meaning that overall compiler complexity has grown.
>If you want the 2017 version of it, it is called Delphi.
Ok, this is something actually relevant.
>Go's compilation speed only surprises those developers that never used anything else beyond C and C++.
For me (tm), Go compilation speed has compared equal or favorably against C, C++, Java, C#, Rust at least.
Which ones?
> For me (tm), Go compilation speed has compared equal or favorably against C, C++, Java, C#, Rust at least.
Since when does Go compile faster than Java and C#?
When I hit Ctrl+S my binary is already on the disk, thanks to incremental compiler integration on the IDE.
I have a full blown WPF application with multiple plugins, including data visualization, talking to Oracle and Postgres, total compilation time after check out 12s.
Eiffel, D, Nim, Jai are other fast compilation examples.
In any case it doesn't change the fact that Go's compilation speed is nothing to brag about, it has been done before in many other languages, Turbo Pascal was just one example.
If you wish I can provide other examples of languages that compile as fast, on such old hardware while matching Go's compilation speed, with richer language features.
Or look at Python, which is also compiled. Or Ruby, or JavaScript, TypeScript, Dart…
Does not matter where the implementation comes from, if it is free or commercial, what matters is that it exists.
There are other C compilers to choose from, with libc implementations that properly support static linking.
Java 9 added linking support for custom runtimes.
I like it when they have a complaint but can see why the trade-off was made.
I don't like it when they're obviously parroting HN group-think.
I really don't like it when they have no complaints at all, but are able to recite the marketing happy-talk verbatim.
I admire people who can spot such things effectively and steer discussions in an productive manner. I see now that this is not really about interviews anymore but just everyday discussions.
I think for many people, me included, it's flawed but good enough for the job and fun.
Remember that Go is still a niche language, and the majority of programmers will never write a single line of Go.
There is a nice trend around Go nowadays, but most people are still writing PHP, Python or Java and Go isn't going to replace any of those.
Languages don’t get replaced, people just don’t use them as often for new projects.
Ouch, the lack of historical accuracy of your comment is painful. Just a few points :
- Sun Microsystem was founded in 1982, it's far from being a dot-com start-up.
- Java was already ubiquitous by 2000, it was embedded in your phones, your credit cards, in your browsers thanks to applets etc.
- in fact it did replace COBOL or C++ for a wide number of applications, not everywhere but it still had a enormous impact on the industry. Netscape even went as far as re-implementing their whole browser in Java[1]. It was a bad idea, but that gives you an idea of the revolutionary impact Java had.
Go is nowhere near where Java was in 2000, by several orders of magnitude. It's not a criticism of Go, I don't even think we'll ever have a language as popular as Java in that time, because in the 90s there was a massive window of opportunity for a language that was at the same time : safe, portable, and licence-free.
[1]: https://www.cnet.com/news/netscape-sharpens-javagator-plans/
What I remember from the time was that C and C++ was everywhere, and Java was this weird new thing with a bunch of promises that ran slowly (because the JIT wasn't standard until later). There were a lot of people who were dismissive of Java, which was stupid, and there are a lot of people today who are dismissive of Go, which doesn't make sense to me either.
Among the languages that came in last 10 years Go is most popular with exception of maybe Swift.
So compare to marketing juggernaut Java with billions sunk in by leading enterprise vendors Go is nowhere. But among non corporate driven language Go is definitely on top.
Go is indeed one of the most popular of the last 10 years, but I don't think it's the most popular one. Swift is way ahead (because of the iOS walled garden), and Typescript is probably more popular than Go (or at least in the same ballpark).
> But among non corporate driven language Go is definitely on top.
Go, «non corporate driven», really ? OK it's not «corporate-driven» like Java, but I don't think anyone would be using Go if Google wasn't behind it. I really think the impact of marketing in Go's success is bigger than its value-proposition (I'm not saying that Go doesn't have a value-proposition, I'm just arguing that marketing played a really big role in its adoption). Consider for instance the microscopic mindshare that Pony[1] has, despite being «Go from the 21th century» with a sound type system and a data-race-free concurrency model.
Pony is also pre-1.0, and it doesn't look much like Go to me.
What are the alternatives if you want something with type checking? Java? No, thanks. Haskel? Where are the libraries? C/C++?
I guess Typescript is the only alternative
> Haskel? Where are the libraries?
Well, I suppose the same drawback would apply to Pony. :)
As for libraries, what matters is if the desired use case is covered, not winning the App Store count.
There's Nim and D too, but I get the lack of big commercial backing could disqualify them.
https://github.com/PatrickLouys/professional-php-sample-code
What libraries are missing? The only issue I've had with libraries are that some client libraries are wrappers over C libraries and this makes static linking difficult (or seemingly impossible on a Mac)
A few years ago there was a lack of libraries in some areas but that's not the case these days.
But yes, if you're working on a modern PHP project, there's a lot to love: A solid module system, an enormous sea of high quality libraries, type checking, a really nice deployment and scalability story, decent performance, good tooling (IDEs, debuggers, etc.), a servicable C-style syntax. For many purposes (not all!) it's ten times better than, eg, nodejs. (Which might seem like a low bar, I admit...)
I quite like Typescript as far as syntax goes, but I think PHP 7.1+ is comparable. And PHP has a lot more support, libraries, and better tooling in my view. For example, my experience in node land is there aren't really any good ORMs; PHP has multiple, including one (Doctrine) which is easily the equal in my view of the highly regarded Python SQLAlchemy. Similarly with routing, frameworks, templating, etc., there's a huge amount of maturity on the PHP side that's missing from node.
The big question is going to be in the process model. Node has an event loop; PHP doesn't. For most purposes, I think an event loop makes writing good code harder to no real benefit, but in some cases (eg, acting as the endpoint for a ton of open websockets) it can be a big win. If you do need that, then you should probably lean towards node over PHP, and sure, why not use typescript? But for the general case, I'd still lean towards PHP.
(Then again, there's also a ton of other languages and frameworks. Just because PHP - or node - might be better than the other for some task doesn't mean there aren't a dozen more languages better than both.)
It's still the same as C, which is _not_ a solid module system.
Though it has improved dramatically.
The VO's I use trow exceptions when you construct them with some bad value. This is great because when you use for example a natural positive integer object you are sure it is one.
So now I have 'type checking' and more secure code in PHP.
http://php.net/manual/en/functions.arguments.php#functions.a...
And it is still the case with type declarations, that they make your code actually slower, because the runtime adds asserts in your code which gets evaluated at runtime?
Go is not OOP in any shape or form, no matter what “they”
try to tell you. Go is imperative language with procedural
style of writing code. Yes, you have objects and you can
attach methods to them, similarly to Ruby where everything
is an object, but that’s basically it. Never, ever, try to
repeat yourself in Go. You will crash and burn.
When it comes to Go, spaghetti code is what you want to write.
This was really funny. Definitely the rantings of someone who is used to too many layers of abstraction and coded themselves into a corner before finally blaming the language. I'm detecting a lack of self-awareness. Here is where the author should have used the gif that was used at the start of the articleI must have links to at least five different gzip middlewares in my favorites, and I'm sure there are more than that...
At which point is it easier to put the app behind an nginx reverse proxy? Chances are that you have a reverse proxy anyway since one Go app is not nearly enough to saturate a server CPU.
Not hating on it though. I like Go for network-y things.
edit: And in your example, is it a clear win to centralize compression at the proxy?
EDIT: p.s. thank you for designing your website so that can actually handle some traffic. That's worthy of the hacker news gold achievement
Not really. When I had a blogpost on the frontpage for the first time, I checked the monitoring and saw a CPU load of 6% of a single core and 1 megabit per second (that's bit, not byte). [1]
And it's simple, really. You just write some text on the page, add a small stylesheet. And then you just stop, resisting the urge to add any JS and tracking and hero images. You just stop. And instead of generating your HTML on the fly from a database, you just serve a static HTML file.
[1] Graphs: https://blog.bethselamin.de/posts/latency-matters-aftermath....
Maybe the only thing I'd add is a compiler warning when an object which does not declare itself as interface X but complies to it is used as interface X. (Typeclasses would be even better, but it opens the can of worms which is the support of generics.)
Also one should not forget that a company with 1000s of engineers is probably not you (yet); when you read that some company runs successfully on Node and saves $n amount of money by using it etc; when they have 1000s of engineers and devops on top of that it doesn't mean you can achieve the same (or any) success with it with 2 people. PHP for instance might be a much better choice with a small team; you don't need complex server setup, you don't need (or can handle) middle of the night alerts that require you to dive in vs just reboot the server etc.
This is not so for Go or Node for most hosters out-of-the-box. Sure in the HN echo chamber, every hoster offers this maybe, but there are literally 100000s of small/big hosting companies/resellers in the world that run, say, CPanel. And the only thing that is trivial there is LAMP (with PHP/MySQL) hosting; the rest is just not very convenient or even impossible.
So once you set it up, no there is no difference, but then you have to know how to set it up, secure it, have access to set it up and secure it and know how to maintain it which is the point i'm making (not meant about specific environments besides PHP/MySQL); if you are a small company that needs to make money, you might not(!) want to bother.
Edit: Cpanel, in some near-future version will offer Node, I cannot find Go though.
Edit2: I'm definitely not recommending anything here or saying Cpanel is any good; I just know it well and I know that it's the most installed 'admin panel' on hosting servers.
You don't have such things in other languages simply because they have not been initially created as glorified templating engines. More importantly: for example, Django in debugging mode allows you to swap templates on the fly, so is with the executable code. Except nobody does it because that's considered ridiculous.
In my opinion, Go is just such a bland-in-a-good-way language. And I enjoy writing it, for the record. Came back to it after a while not writing it and discovered warts I had missed before, but it's still pleasant. Can't help but think people just need to relax a bit when it comes to Go. Listen to Rob Pike speak about it compared to Rich speaking about Clojure: Go's not the language to get worked up about.
(Please put generics in Go 2!)
What Go takes away is mostly tools of abstraction. Some of them are removed for a reasonably good reason (hard to implement in 1.x). Well, people end up with codegen tools that replace not only templates and generics but also the C preprocessor.
This. At least this is easily added.
But why there is "nil" in Go I find less excusable, mainly because this "feature" is not easily (impossibly) removed.
If you come from C it is good, sure. And you can write big projects in it like in C (just think about Linux or Unix). But if you come from a high level language like Java (which is also performant by the way) Go feels like wearing a straitjacket! Go lacks the most basic tools which any seasoned developer can expect from a language (like generics). Just look at [my response](https://medium.com/@addamsson/this-article-is-wrong-in-so-ma...) to this topic elsewhere.
1. Go "is still not as fast as Java can be" [1]
2. "Go lacks the most basic tools which any seasoned developer can expect from a language (like generics)"
3. "Go does not have a de facto build system and you can’t handle dependency management in an easy way" [2]
4. odd error handling
5. not a lot of libraries to choose from [3]
6. possibly more arguments that I missed when summarizing your post
The way you paint it, people would be stupid to use Go. However, thousands of very talented developers use Go everyday. How can you explain this disconnect?
[1] I like how you didn't say that Go "is not as fast as Java". That's a subtle, but important difference.
[2] `go install` is the build system and I have solved dependency management for myself with literally a small shell script [4], and an official solution is in the works [5].
[3] I never had trouble finding libraries for use-cases both common and obscure).
Billions of people hold staunch religious beliefs, yet this doesn't mean they're stupid or mentally handicapped.
The lack of a preprocessor alone (as ugly as that may be) rules it out for a great many embedded and cross-platform scenarios. The binaries are also fairly enormous. 10M for a shell util on a desktop may be good enough. Beneath that level, it is a deal-breaker and a scandal.
Agree with the straitjacket part though. Comparing it to something like Clojure, the best I could say for it was, "At least I don't have to deal with the JVM..."
Yes, Uber is running a production Go service with massive QPS. This is exactly what the original author meant when referring to Go's strengths with single-purpose, high performance, "nano" services with relatively little business logic.
There is also the insistence that frameworks are bad and developers absolutely have to care about "granular control" and "manipulation of bytes and bits" and packets and IO (unless they're writing a "glorified todo list") which rubs me the wrong way. Why is it so hard to acknowledge that there are a large number of perfectly good websites and codebases that do well with popular frameworks?
We ourselves have a proxy layer and a couple other services written in Go, and they work great, but the rest of our stack is Java and some Python. Developers are free to choose the best tool for the job when starting new project, but after a few days of messing around in Go every new service is undoubtedly built using our existing web stack.
I don't think it was a very wise decision because not only are you doing things twice, you're doing it three times, because you have to serialize/deserialize to/from Thrift for every request. It adds development time, more tests, and Thrift's binary protocol makes debugging RPC almost impossible.
This isn't really an argument for/against Go, but it just shows that you should try to avoid using multiple codebases that have to be tightly integrated. Personally, I would've gone with a Ruby-only codebase that used Thrift RPC only if there was some backend task that was too slow in Ruby, and that Go's concurrency and speed might be better at. Then I'd serialize it and send it over to be processed by a better language. I wouldn't do it for every request.
That being said, if I had the choice between writing an API in Go vs Rails, I would do it in Rails for the faster iterative development speed and quick debugging capabilities that is made possible by an interpreted language.
Hard to debug binary-based RPC? You have picked the wrong technology for communication, having forgotten that you'd need to build the necessary tools in order to debug it. There's literally nothing wrong with binary protocols, except developers forgetting about the necessary overhead of re-parsing the passed data in the debugger. But it's not an overly expensive overhead, if the architect had taken this into account.
Having heard this point absolutely not for the first time, the only question that remains is: who and why did make a decision to have it this way?
> I’ve worked with RoR, and a variety of frameworks in the Node world – and I have never had a framework project where I didn’t end up fighting the very system that was supposed to make development “easy”.
This is not my experience with Rails, Django and Phoenix. Actually, I was probably fighting Rails in my very first project in 2006 (or was it 2005?) but I was writing it as if it were Struts (I was coming from Java.) Then I started coding as if it was Rails and got a great speedup in terms of coding time. I'm less proficient in Django. It seems that it doesn't really enforce a project structure and one can do almost what s/he wants. I've seen projects that look very different to a degree I never saw with Rails. Basically all Rails projects look the same. Phoenix is somewhat in the middle.
So, if the author is wrestling with frameworks either he's not proficient with them, but this doesn't seem to be the case, or he genuinely doesn't like to be constrained by the requirements of those frameworks. This is not a bad thing per se. If one feels like that, he's going to be a happier developer writing code with the architecture he designs. I'm not sure customers will be happy too, but I don't know what kind of projects and customers he has.
About me, I prefer to stick with standardized architectures that any developer after me will be able to understand in minutes. I'm a freelancer and I just don't have the time to spend a significant amount of my customers budget to learn (and make learn) more clever and optimized architectures before doing any real work. If I had my company running around one software product, then maybe I would design it from scratch. Reality check: I wrote so many MVPs in Rails, especially for customers. Given the usual outcome (failure to get traction) it would have been a waste of money to start with a more clever design.
For example, the labstack echo framework in Go is one of my favorite frameworks, it does a lot of work for me. On the downside, I can't hijack HTTP connections in the router, like for example, when I want to host something under customs domains and redirect internally to a subURL. I have to hack around the framework to do that, the solution is rather ugly. But there isn't much I can do otherwise that doesn't have various amounts of bugs.
Frameworks will always limit what you can do, period, you will have to code around them once you want to do something they don't allow out of the box.
On the other hand, the less the framework does for you, the less limiting it is but in the same moment it also does less work for you.
This isn't a problem with "frameworks" but a problem with the library you specifically chose which is bad since it doesn't even fulfill your needs apparently. I wrote my own go http router, and I have no problem hijacking the connection and filter according to hosts, at all.
I don't want to bother with writing my own router and this was one of the few times I had problems.
I think even if I wrote my own framework, I would eventually end up having to hack around it anyway when I inevitably need to do something the framework I wrote just fundamentally can't and I suggest this will be the case for your custom implementation too.
Suddenly, you'd like to have real-time comm? Don't add WebSockets, simply because they fit right above the whole of your stack based on HTTP. Use TCP.
There's a very gentle balance between using what you've already got and introducing a set of newer entities into the system; and sadly this is not always that clear, which one you should use.
A balance must be found, in one of the earlier examples, a quick hack was easier.
> Would you rather?
>
> A – Be able to write new code 50% faster
> B – Have 90% less errors in all new code you write
For my employer, this is the most important question of the 3, and the answer is A every time.If you have a ton of errors, B is going to be more important. If you have relatively few, then A is going to be a lot better.
My employer would probably pick A, too.
But there's a hidden side to this: If it's that much easier to code quickly, it's probably easier to understand the code as well. Which means fixing bugs is faster as well. At least, in my experience.
Not always, but often, I find this attitude in developers who either refuse to read documentation, or just entrenched in their ways and too stubborn to try it someone else's way.
Is every project you're starting really so cutting edge that the problems others have solved and come to a consensus on don't apply to you? Perhaps, but maybe you should also be taking a look in the mirror and making an honest assessment on just how difficult you are to work with.
There's a huge fuzzy region between that extreme and "application programming as a semi-skilled trade", and go seems to fill certain "systems programming" needs adequately as far as that goes.
I think it's pretty well accepted that no systems language has GC. Go is on the same abstraction layer as Java/C#. Everything in text can be taken as a slight, and to ensure that doesn't read that way, I am a believer in targeting that level of abstraction most of the time. I think it's the sweet spot. I'm not a fan of the dual language approach targeting high (Python) and low (C). Java or C# makes more sense to me, for most software. That's my opinion. If I needed more than what those heavy hitters provide, I'd just go all the way and reach for Rust myself.
So I don't necessary see the parent comment from ctf as combative. I think he's just seeking accuracy.
I think the other commenter is correct: it seems like a semantics argument, and a rather pointless one at that.
I suggest reading Project Oberon source code, it’s freely available.
Back to Go, for anyone else reading this thread and wondering what Rob Pike thinks it is, evidence of them removing "systems programming" off their website is here. He explicitly states that he regrets it and that Go is not an OS writing language[0]. Andrei Alexandrescu offers a litmus test shortly after with a property of a systems programming language that Go also fails. If the creator of a language says it's not a systems programming language, I'm not sure how it can be argued by outsiders that it is.
If there's more damning evidence that Go is not a systems programming language, I couldn't imagine what that would be. A shortlist of systems programming languages that would pass any litmus test would include C, C++, D and Rust.
[0]https://www.youtube.com/watch?v=BBbv1ej0fFo&feature=youtu.be...
If you bother to read Joe Duffy's postmortems, and talks he has made about Midori, you will get it had nothing to do with technical issues, rather internal political wars at Microsoft.
Also Microsoft did not fully backed out, the outcome of Singularity became the MDIL compiler for .NET on Windows 8.x.
Midori influenced async/await, TPL, .NET Native used in UWP and the new low level language features on C# 7.x.
> If the creator of a language says it's not a systems programming language, I'm not sure how it can be argued by outsiders that it is.
I don't have Go in much high regard, but it certainly can be used for systems programming, and is being used as such today, regardless of what the anti-GC systems language crowd thinks.
"G.E.R.T : Golang Embedded Run-Time"
https://github.com/ycoroneos/G.E.R.T
"Fuchsia TCP/IP stack", all network requests go through it.
https://groups.google.com/d/msg/golang-dev/2xuYHcP0Fdc/tKb1P...
https://fuchsia.googlesource.com/netstack/
"Fuchsia disk management utilities for file systems"
I did read Joe's blog, years ago. Your takeaway there also leaves you with a bone to pick with Microsoft, if it's just politics then you should be able to find someone in management at Microsoft to set straight. It'd be a real shame if there were no performance issues and it was shutdown due to politics alone.
That is a fact, easily validated in Fuchsia's repository.
According to you, Rob Pike should call management and let them know it is not a good idea to use Go for writing Fuchsia's TCP/IP stack.
You only read Joe's blog years ago, yet you missed the talks he gave.
Two years ago is not that long time ago,
http://joeduffyblog.com/2015/11/03/blogging-about-midori/
"My biggest regret is that we didn’t OSS it from the start, where the meritocracy of the Internet could judge its pieces appropriately. As with all big corporations, decisions around the destiny of Midori’s core technology weren’t entirely technology-driven, and sadly, not even entirely business-driven. But therein lies some important lessons too."
http://joeduffyblog.com/2015/12/19/safe-native-code/
"Over the course of 8 years, we were able to significantly narrow the gap between our version of C# and classical C/C++ systems, to the point where basic code quality, in both size of speed dimensions, was seldom the deciding factor when comparing Midori’s performance to existing workloads. In fact, something counter-intuitive happened. The ability to co-design the language, runtime, frameworks, operating system, and the compiler – making tradeoffs in one area to gain advantages in other areas – gave the compiler far more symbolic information than it ever had before about the program’s semantics and, so, I dare say, was able to exceed C and C++ performance in a non-trivial number of situations."
"Safe Systems Programming in C# and .NET"
https://www.infoq.com/presentations/csharp-systems-programmi...
"RustConf 2017 - Closing Keynote: Safe Systems Software and the Future of Computing"
https://www.youtube.com/watch?v=CuD7SCqHB7k
Around minute 30 he starts describing the uphill battle to convince other Microsoft teams to accept Midori achievements.
All of this was hashed out years ago upon Go's release, and the Go team took down the "systems language" moniker. That was the end of it. Google knows it's not going to fulfill stringent litmus tests for a systems-language. We'll review the subject again if the folks at Google are brazen enough to ever add it back to the website.
Now Rob doesn't have to call management and let them know it's not for systems programming, Rob & Google already know it's not. He said so himself. You're the only one in the dark on that front at this point.
Developers don't have to ask him permission or blessing for whatever they are trying to do with Go.
Google is using Go in system components in Fucshia, and the new GPU debugger for Android is also written in Go.
You are in the one in the dark about using GC enabled systems programming languages. I have real life experience using them and have seen it works.
I lost interest on Go due to its spartan design, but certainly will encourage anyone trying to use it to build an OS from scratch, regardless of what is written in a web site.
"They did not know it was impossible so they did it"
-- Mark Twain
A lot of things work, doesn't mean they meet strict litmus tests (which matter, because definitions matter), nor does it mean it's a good idea.
Anyone is free to just fork Go and do whatever they feel like with it, regardless of what Rob thinks. That is the beauty of MIT license.
So given that Oberon is accepted as a systems programming language in computer science, with multiple published papers and books across two decades, heavily used in OS research at a couple of European universities during the 90's and an influence to Go, with hardware and compilers still being sold for systems programming, although in small scale.
What are the actual technical features Go is lacking that makes it impossible to be used for systems programming, given Oberon's influence on its design?
1) A lot of things work, it doesn't make them good ideas.
2) Go doesn't meet the strictest litmus tests of a systems language, never did, never will. It's only a systems PL only if you relax your definition of what it is. Go's own creator says it's not and if any one person is the authority on this topic it's him. There are platforms that meet all definitions, those are definitely systems PLs.
I only care about what Computer Science books and ACM SIGPLAN papers accept as systems programming languages, not random opinions in online forums.
Thankfully both of our opinions are meaningless to Go users.
So we'll just settle on once there's a commercially successful operating system built in a GC'd language then I'll eat crow but till then they're all going to be C/C++/D/Rust or built on similar abstraction layers. Go ahead, wash away Linux, iOS and Windows in the competitive landscape with something written in Go. Let's see it, that's believing after all. It'll never happen because it's unsuited and inferior for that purpose.
Yes he did. He said it's a cloud-infrastructure language[0] and that he regrets calling it a systems language. That's why he took systems language off the Golang site.
>For fuck’s sake, give it a rest.
Why would we when we're right? Why don't you give it a rest, you've long been proven wrong.
You know, usage of the English language and the terms within matters. Claiming you have a systems language when you don't introduces confusion. You can loosen the terms all you want to but it will never change the fact that GC languages can never meet the strictest measure of a systems language. That's why it matters. No one should be apologizing to you because you don't like the facts.
[0]https://www.youtube.com/watch?v=BBbv1ej0fFo&feature=youtu.be...
At ETHZ Oberon workstations were used during a couple of years by several users across the department.
Most of those attempts failed due to losing the political and financial wars of bringing them into the wider market, not because of lack of features.
The way you say that, it sounds pretty unimpressive. Say, 2 years and 10 users, plus or minus one order of magnitude. That's not enough to tell anything. Was it going to be portable to other hardware? Was it going to be maintainable? Was it going to be comparable in performance? The answers are all "no data". The only thing you can say is that it could be successfully written and gotten to work, for a definition of "work" that allowed a few people to use it for a little while.
> Most of those attempts failed due to losing the political and financial wars of bringing them into the wider market, not because of lack of features.
Well... I wasn't there, but I took a look at the Wikipedia page (yeah, I know) giving the chronology of the Oberon OS, and it's quite unimpressive. For four years, it had "only simple text editing facilities". Those four years ended in 1991. That sounds very much like "lack of features" to me.
In particular, the competition was either DOS, Mac, or a Unix workstation. That feature set would not lead anyone to want to choose Oberon.
Now, I know, there were only a couple of people working on it part time. But all this really proves is that they were able to write an OS and get a text editor running on it. That's proof of concept, I suppose, but there's a huge difference between an OS like that and an OS you can "bring into the wider market".
I think you're idolizing a past that wasn't all that hot at the time...
In the meantime a new version of Oberon was re-done with Oberon-2, whose method declarations influenced how Go method declarations are done.
By this time there was a spin into a Swiss startup that designed Component Pascal, an Oberon-2 derivative, with a RAD development environment targeted mostly at Mac OS and Windows users.
The researchers at ETHZ created Blue Bottle OS, also known as A2, using Active Oberon. Yet another Oberon evolution, that had support for co-routines in async/await style, and probably one of the first environments with a multi-threaded compiler.
It was good enough to support applications like video playing, BeOS wasn't the only one doing it in the mid-90's.
If you want pictures, there are plenty of them here,
Oberon was used until early 2000s to teach systems programming at ETHZ, and many department computers used them as their main workstations.
Including file servers implemented in Oberon for distributing work across workstations, and an early version of applets concept called Juice.
ftp://ftp.cis.upenn.edu/pub/cis700/public_html/papers/Franz97b.pdf
Graz University had their own variant of Oberon, with Hanspeter Mössenböck leading some of the development efforts. This same department is nowadays heavily involved with Graal research together with Oracle Labs.
http://www.ssw.uni-linz.ac.at/General/Staff/HM/Publications/...
http://ssw.jku.at/Research/Projects/JVM/Graal.html
The Ulm university in Germany also implemented their own Oberon variant, including native versions running on top of several UNIXes and Windows.
Mostly broken links nowadays,
http://www.mathematik.uni-ulm.de/oberon/ulm.html
Niklaus Wirth later in 2013 redid the original Project Oberon, with an updated variant named Oberon-07 and targeting an FPGA instead.
So no, I am not idolizing a past and there was a little more there than just a plain text editor.
Sometimes the Wikipedia is not the best source.
Just because there is a GC doesn’t mean it is the only way to allocate memory.
Or not.
"Grail Quest: A New Proposal for HW-Assisted Garbage Collection" (PDF)
https://people.eecs.berkeley.edu/~maas/papers/maas-asbd16-hw...
Also Intel did have hardware GC with i432, but the chip suffered from many design errors that made it quite slow.
Here's Rust's runtime: https://github.com/rust-lang/rust/blob/master/src/libstd/rt....
Colloquially, this. There's historically been a fairly big gap between "very little runtime" and "more runtime", so "no runtime" and "runtime" are what people say.
That said, the word is generally ill-defined; some people use it to mean "interpreter" or "vm" rather than the classic definition, which is (as you say) that every non-assembly language has a runtime.
;-)
crt0.o is a very simple set of startup routines with a fixed and predictable behavior. It is typically run only once ("0" in the name is for startup), and has only a couple of assembly instructions.
With Python - not so much. Sure, I can rent a whole VPS but I don't want to do server administration. And there are some options for hosting Django / Flask apps, but not many. Is it any wonder people still use PHP? I have used it for a long time and I hate the language - but it is hands down the best solution for small web pages where hosting is concerned.
EDIT: thank you for the downvotes. It was nice having a constructive conversation. But then again, I knew in advance it is unpopular to mention on HN that PHP, MongoDB and similar technologies have their use cases.
One thing I used to hate about PHP but then kinda grew to like was variables being prefixed with a $, as it makes it real easy to distinguish between functions and variables at a glance.
Other than that, it's just programming. For me, who is making really simple things, 99% of the work is figuring out the pseudo-code and data structures, if the language doesn't get into my way, they're pretty much all the same. I haven't tried Rust yet, but from a casual glance I do like what I see.
I sincerely wish all languages with braces would have this feature! Even Javascript devs practically standardized in always putting braces at the end of the line. I prefer working with code that mixes tabs and spaces than with the old-ancient style of spoiling a nice and clean empty line with a brace (yeah, you can just leave a line empty if you want your code to look nicer and more separated).
Thank God I can do a lot of my work in Python and don't have to care about these things though. Would've been great if Go too borrowed the "indentation for code structure" amazing idea from Python ;)
I mean, really, even Lisps never put their parens at the beginning of otherwise empty lines...
This is great for a lot of code but it's probably my biggest complaint about the language these days. PHP supports first-class functions, which is great until you realize all your functions stored in variables have $ at the front. So now, not only can't you use $ to distinguish variables from functions (because sometimes they're both) but you have to remember if something is a Closure* or not.
* another minor pet peeve is that you have to explicitly tell a function what variables it can see from the surrounding scope, but all anonymous functions inherit from a class called Closure whether they can see anything outside their own scope (a closure) or not.
To me, the limited scope of variables with respect to functions makes debugging and code reading much easier, since everything I need to think about within a function scope is explicitly defined.
A large part of what makes me stick to Ruby over Python for example, is that I can't stand languages with significant indentation. It may seem minor, but it isn't to me, to the extent where I avoid Python whenever I can.
When your language enforces formatting like that, people will choose or choose away the language over the formatting.
It's that important. Especially with so many languages to choose for that you can often pick one that is sufficiently similar.
What I can’t stand in other languages is the Laisser-faire attitude regarding styles. Some people put whitespace here, some there, some put the curly brace here, some there. How about some consistency across all codedbases?
Making people who care about formatting to the extent I do refuse to use the language is the cost of tools that enforce those kind of rules.
That's of course their choice, just as it is mine to stay clear of tools (and languages) I don't consider worth my time.
More like 'consistent indentation' methinks.
I still have nightmares about trying to merge some GSOC student's code from their branch to trunk where the indentation was all over the place, it was so bad that lint couldn't even figure out what the hell they were up to -- well, I think lint was crapping out on macros more than anything but still...
So...someone got to put on their resume they did a GSOC for Blender but the work they did was basically wasted since it wasn't possible to clean it up enough to merge.
To me, even with super short lines, braces at the end of the line are messy, and consistently messy is still messy.
> Either you inforce a clear style guide which leaves you to explain the team why your style is the best, or you leave this task to the language itself
Which then leaves the language to explain why that style is best. Did Google ever do that?
https://golang.org/doc/faq#Is_there_a_Go_programming_style_g...
https://golang.org/doc/effective_go.html#formatting
Style guides are a matter of taste. None is better or worse. Yet, I really don't like discussing about my taste within a team of different tastes. It's like asking someone why he/she'd prefer black coffee over cappuccino. I'd prefer someone (or the language) making a clear decision upon code style and enforcing it rather than ending up with a messy, un-styled code base.
To me, they're just harder to spot. I think having them on their own line "frames" the inner block nicely.
That said, brace location is not the hill I'm willing to die on. It's a minor thing, not worth getting religious over. For my own code, I'll do it how I want. For a team, though, consistency really does matter. I'll make my case, and then I'll shut up and do what the group decides.
(And actually, I think consistency within a file matters more than consistency between files, so I'm fine with "The file author/main maintainer sets the style for the file. If you modify the file, keep the existing style.")
I, for instance, are not a big fan of reading and typing Lisp/Scheme/*, pretty printing or not, even though I understand why it is the way it is, or whether its otherwise fascinating.
:((((((((((
Go actually does use semicolons and the formatting has been forced onto users to allow easier automatic insertion of them. They were going to get removed but in the end it was easier just enforcing a format.
Leaning towards “satire” based on your last sentence.
Let us all know if I was right.
People actually sit there and say not even having the option saves them discussions, and that's not satire? I program entirely for my own utility and artsy experimental purposes, so I don't care what is useful for teams, that is 100% irrelevant for how useful or comfortable a specific language is for me. Which is what my comment referred to, how much I enjoy, or not enjoy, writing in Go so far.
I didn't call the language bad, I even said I'm too much of a simpleton coder to to have much use for arcane differences. I just said that after not even having finished my first project in Go I can already tell you, without any irony, that this brace style being enforced is a deal breaker for me. I'm still finishing the project, you know. If people have all these great reasons for not minding the lack of an option and not even having a choice, why are they so insecure about one individual minding it? My comment went to +5 shortly after posting and is now at -2, I think that's just hilarious ^^