210 comments

[ 3.6 ms ] story [ 229 ms ] thread
I am happy for you spf13, congratulations! And thanks again for software you wrote, like hugo!
> What is missing from the Go ecosystem?

Personally, golang "IDE" experience is not as good as Java or even C++.

For example, ycmd only supports subset of functions for golang. I miss ycmd-goto-references the most.

JetBrains WebStorm with the free Go plug-in provides an excellent Go IDE experience. There are some free community editions of JetBrains IDEs that are supposed to work with the Go plug-in (e.g. PyCharm, if I’m not wrong), so you do not even have to pay anything.

https://www.jetbrains.com/products.html?fromMenu#type=ide

It is not excellent. All other editors I used autoformat Go code after save. There are two types of format provided by IDEA - IDE Format & go fmt. Both not ideal. IDE Format does not format code according go guidelines. It can delete unused imports if you go through options. go fmt does not delete unused imports, and as result code is not compileble.

Refactorings are missing in IDEA. It is not excellent, it is something you can work with.

You can also use `goimports` with IDEA.
You can create a macro to gofmt when you save. If you desire removing unused imports, you can add “Optimize Imports” to the macro.
That looks like limitation of ycmd, not golang.

Most go modes for various editors use native go utilities as their backend, for example gocode/godef/golint/gorename/guru, etc.

My main iusses:

-) A proper package manager. (no, go get is not enough. They have realized this and have a team coming up with a draft for an official one)

-) Well written, well maintained libraries that do proper releases. There are very few of those out there. Might get better with an offical package manager and ideally package repository a la npm/crates.io

-) Generics. This will help the previous point also. Often it's hard to write proper reusable libraries due to the lack of generics. And no, they didn't keep generics out because they are to complicated for the language users. They just (quote) "didn't find a good way to implement them", and big language changes like that are out of scope before 2.0.

-) Macros probably won't ever come, but if not, please at least give us a language construct that reduces error handling boilerplate. (Rust has some nice macros for that).

> Generics

I was concerned by this at first as well, but after using Go full time for the past two years, I've never found a need/use for them. Go doesn't lean towards strict OO principles, where I feel that most of the Generics uses are applied (Arrays, sorting, etc.).

Not everyone's opinion, just my two cents.

You only have "generic" functionality for built in types though. Arrays. (In a certain way maps and channels).

That's fine if you only use those, but it makes it impossible to write generic functions for much else. See my comment about lack of libraries. I did miss them a lot.

Not when writing your one off app or program, but for libraries.

And you end up having to implement a lot yourself that's for free in other languages.

Promises and some other higher-order programming without generics are not really usable in Go.
Why would you need, or indeed want promises in Go?

Doesn't a channel/channel-select fulfill this requirement?

EDIT: the answer seems to be downvote. Okay.

I guess you are being downvoted because the comments above have nothing to do with promises.
Please do try atom with the go-plus package. It has goto def, can show "doc strings", and has decent integration with delve.
For me, using LiteIDE and Atom + go-plus was what got me comfortable with Go. Without it, I felt it was far too finicky and had lots of hidden gotchas (like no unused variables).
I have the same features form ycmd. ycmd actually works with atom as well and also supports go.

Pushing all "IDE" features into editor-agnostic daemon is a good path for the future. ycmd is taking this spot.

Atom has surprisingly consistent and useful support for go - fmt on save, debugging, automatically manages imports in a file, and the autocomplete works very well.
Why do people find the need to write about themselves in third person? https://stevefrancia.com/
It irks me too, but it is a convenient piece of ready-made press text that can be used for introducing you on stage or in other media.
It's better than first person plural form :)
As a habit it is bad, but this is actually standard for short bios. It allows it to be dropped in place directly for conferences, PR shots, news articles, etc without any rewrite.
Great to make it look like someone took the time to do a bio about you because you're important, while it's just you writing. Lack of self-confidence if you ask me.
Lack of self-confidence if you ask me.

How do you figure? Every time I've been asked for a bio for a conference or similar, they've asked for it in third person. Reading bios in conference proceeding in first person would just come across as weird to me.

The difference is having a bio on a website about yourself versus a bio on a website about a lot of people. No one thinks that your johndoe.com site was made by your official fan club.
You really named your user account after WHAM!? That's fucking awesome. Tell me you're either George Michael or Andrew Ridgey in deep disguise... please please.
Just another jitterbug, but you gotta have faith that I'm once bitten and twice shy.
I think it's just a convention that's used when writing "About The Author" sections. Not really a statement of personality.
I noticed that too. Also, "leader".
Congratulations, but what of Hugo? :)
Congratulations!

And never, ever, ever give up the fight for GNU-style double-dash command-line flags!

Context? Are people actually switching to single dash flags? If so I'll get my pitchfork out of the closet.
The default golang flag package (https://golang.org/pkg/flag/) does not implement gnu-style long-with-shortcut options. Instead, one and two-dash arguments are identical. For example, -enable-pants and --enable-pants are equivalent. Compare this with the GNU style where you can have -p or --enable-pants.

Most go programs I've read use spf13's flag library, which is GNU-compatible.

Is this a remnant of Plan9 or something? Ugh, this is why I don't dabble in ecosystems with overly opinionated leaders. You have to know when to have a strong opinion and when to do things the standard way, and some people can't do that.
Plan 9 doesn't have --long-options at all. In Plan 9 arguments are single letter.
Note that the std flag package accepts double-dashed arguments just fine, it only never advertises that it does.
> Go has the nearly perfect balance of readability, expressibility and simplicity

Is Go really expressive?

Fairly verbose. But he was talking about the "balance".
How it is a balance if expressiveness suffers?
I guess the claim is that any more expressiveness would necessitate losses in readability or simplicity that the expressiveness doesn't make up for.

Personally, I think you're sense of relative value of those has to be pretty unusual to thinks it's "perfect". Though valuing simplicity above almost everything else is what's written on the tin with Go.

No, it's verbose and recommends bad and repetitive code style which affects both readability and simplicity. The only people who'll find this language "simple" are those who never understood any more "complexities" than functions and loops:

" The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt. – Rob Pike "

+article: http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-in...

It is pretty readable, but really non-functional too. Eg, they still don't have math.round and you wind up writing a lot of code because it can be a little bare bones or does things in a way that isn't quit usable.

I wouldn't say it is very expressive either. Go can be very wordy and verbose at times, and some things are downright a pain or poorly thought out (e.g, while Java has finally and C++/Rust have RIAA for dealing with resource deallocation Go has defer and it doesn't work really well when you encounter an error in the dealloc logic).

Simplicity is about Java 1.0. Give Go some time to add some technical debt before you get too excited about it simplicity.

It isn't a bad language. This is my second run thought the language, and I'm neither excited nor turned off by it.

... R-RIAA? You probably meant RAII right: http://www.riaa.com/

Resource management by litigation sounds innovative though

> It is pretty readable, but really non-functional too

There are projects starting to fix that: https://github.com/asteris-llc/gofpher

(comment deleted)
I think he meant non-functional in the sense of "not functioning", not functional programming. Neither of his immediately following complaints have anything to do with functional programming.
Not really. It's very verbose compared to Python, almost like Java.
Noo that's an overstatement.

Of course it's not as clean as Python, it's statically typed.

But type inference makes code way cleaner than your typical Java code (Javas type inference is improving, though).

> Noo that's an overstatement.

No, it isn't since go lacks generics and dynamic types - which helps to reduce boilerplate(even if the latter isn't that effective).

> Of course it's not as clean as Python, it's statically typed.

There are cleaner statically typed languages then python - look at fp languages with type inference(ML dialect)

> But type inference makes code way cleaner than your typical Java code (Javas type inference is improving, though).

The typical java code is legacy, but for a fair comparison you should check out projectlombok [1]. Otherwise, Java is on the JVM which means there are alternatives like Scala/Kotlin etc.

[1]https://projectlombok.org/

* Interfaces which can have fields would be really, really great.

* A rust-style borrow checker would make dealing with channels and pointers a lot safer.

* Equality operations for slices would clean up some ugly parts of the standard net library (addresses are []byte, so a direct x == y doesn't work but seems like it should).

* Closed enum sets: some ability to setup an enum type which can be "complete" when used in a switch statement without needing a "default" and which will only panic/fail when a bad type conversion is made. Let me sanitize out a whole bunch of possible errors at one point in my code when I want to use constants (and be warned when I break the guarantees).

My two Golang pet peeves, not very important either:

-still no math.round WTF?

-make() should be syntax and not this quasi-function that takes this vast array of argument types, and while you're at it, you should just rename it `new`, because that's what it is.

note that new() already exists in the language.
Yes, and make() is completely superfluous. make() and new() can be completely rolled into one piece of syntax without ambiguity because they are the same thing.
Haha, no number rounding function/method in the standard math lib? And I thought Dlang missing a BigFloat type was a deal breaker.
I'm using C# mainly because of debugger integration in Visual Studio.

Make decent visual debugger and devs will come.

Visual Studio code has pretty decent debugger for Go.
Is that delve? If so, it doesn't work debugging tests, which makes it, depending on your style either totally useless or just quite annoying to use.
Yes, it is a visual interface over delve.
Delve supports debugging tests.
What are you developing with C#? I see Go more for server-side stuff, and C# for Unity/Desktop development...
some legacy Windows server stuff - part of this could be rewritten to Linux/Go/whatever_server_lang just team mates are not willing to leave their comfortable VS env. if not provided with decent IDE/debugger
Interesting. I've used C# heavily at my last couple of jobs and it has all been server side web work - mostly back ends of web apps, but also services and microservices of various kinds.

From talks with coworkers, the impression I've gotten is that most C# in the wild is running server side, though there's obviously a lot of it in desktop apps, and on mobile with Xamarin.

On our case desktop applications for interacting with healthcare and manufacturing devices, web sites and distributed computing.
In general make good tooling and others will come. Look at Java/Eclipse
Can confirm. At work we're moving from Clojure 8 to Java 8 partially because IntelliJ is amazing and partially because Java 8 plus the right libraries is close enough to Clojure anyway, except much faster.
I think as developers we are so used to pain that we forget how "easy" development can be if we allow people the right tools.

If any language had the tooling and development Java did it would hold the market share. It's my opinion that if Rust makes a similar IDE experience (even just using Eclipse's platform) with every feature like code completion, formatting, debugging, the hole 9 yards and integrate Cargo into it they'll win. But, here's the caveat: It needs to be FLAWLESS integration.

I've been a java developer for my entire programming career. Java was my first language when I was 12 and I'm 19 now. I still can't use javac without looking at a compiler guide since I never use it. Eclipse does the business and I don't ever even need to think about what's going on outside my code. Not once.

Java like tooling already existed before Java was born.

We had it in the form of Common Lisp, Smalltalk, Delphi and Visual Basic, IBuilder (for those rich enough), CA Objects, C++ Builder.

To add to this: in school I found Java a complete waste of time.

Started working and someone showed me how to productively use eclipse and suddenly it was acceptable.

That you need an IDE to make a language bearable speaks volumes to the design of the language.

Go is doing well because it realizes we can strip so much away, stay with the standard lib, and get real work done quickly.

That's not to say that Java, in particular the JVM, isn't an impressive piece of engineering, but more that we should be careful when we choose our tools so as to not overly complicate things.

While Java may be somewhat verbose, good tooling is not just about "making the language bearable".

Things like being able to jump to a definition, rename it throughout the project correctly and jump back without even thinking about it are hugely valuable in any language.

And maybe you have ways of doing that in your workflow too, in which case great, you too appreciate the value of good tooling.

Sure, agreed, but I think you misunderstand my point. If I took away your Java IDE would you be able to get very far?
Thanks for your comment. It inspires me to write a blog post on why Java is my new favorite language, especially in comparison to Go.
Rather than looking at it as a language that needs an IDE to be bearable, it might be more helpful to look at it as a language that is most pleasant to use in concert with well build tools.

I look at it similarly to the way I look at Smalltalk. It's possible to use it as just a series of text files (with GNU Smalltalk), but using it with tools that understand the language (such as Visualworks or Squeak/Pharo) turns it into a very different experience.

I know that a Smalltalk dev environment feels alive in a way that Java doesn't, but using Java with a tool like IntelliJ is a nice experience. Using something like JRebel or HotSwapAgent to swap code changes into a running application also improves the dev experience significantly.

I'm not a Java developer, so I'm interested to know what the amazing parts of IntelliJ are. When I look at it it just looks like they ripped off the skin from Sublime Text and it has some debugging features that are readily available in other editors. I get pretty much everything on https://www.jetbrains.com/idea/whatsnew/ in my vim setup.
All the refactorings and context-aware code completion, for starters. And as for ripping off, IntelliJ came out 7 years before Sublime Text.
Cool, show me a screenshot from, say, 5 years ago that looks like Sublime? From what I can see it looks something like this:

https://blog.jetbrains.com/idea/2011/10/new-in-intellij-idea...

I didn't say features, I said skin. Of course IntelliJ has been around longer.

If you like an IDE that's cool, no hate. I just get frustrated with the idea that I need one to be productive in certain languages. Give me Go and vim, maybe inside tmux, and I'll be productive immediately.

whoa!! this is huge - can you talk a bit more about your stack please. This is the first time I have heard something like this - what libraries, code style, etc would get you the same "feel" as clojure ?
I'm assuming Lombok and using the new Lambdas. Maybe even a fibers library.
Yep, mostly Lombok (especially @Data for immutable typed objects with automatic constructors without boilerplate), streams, and lambdas.
Personally I think Lombok should be mainlined at some point. It's just so perfect in everything I've tried.
are there any opensource github projects that illustrate the use of this infrastructure (java 8 + lombok + streams + lambda) in a very clojure-ish way ?

its hard to find good examples of this style of coding. For example, it is hard to figure out which app server (Spring Boot, undertow, dropwizard, wildfly). I'm sure you can use any... but it would be nice to learn from your experiences.

Could you provide an example project that you'd like to see implemented and I'll give it a go? I'm not the person who's doing this but I think I'd like to mess around with functional programming and I love Java.
Nice! Drip campaigns - https://www.sendwithus.com/resources/guide#ch2-drip

This is an example of a project that is not UI centric, has quite a bit of database integrations (postgres), mailer integrations (mailgun), scheduler (https://dzone.com/articles/distributed-tasks-execution-and-s...). It has also has a bit of math to compute stuff.

Even without a UI - it is something that could be very useful!

Sounds pretty good. I've sent you an email for more details. I'm interested in doing this. It's a cool project idea.
Make decent unit test coverage and you'll hardly ever see a debugger again. Neither will you need a fancy code editor.
Nope. It is absolutely false. You will always need a debugger and there are some problems that are not unit testable at all. How do you unit test a random WPF bug? And you'll always need a fancy code editor unless you're masochist.
Go doesn't have yet anything capable of matching WPF and Blend.
If WPF was designed from the get-go using TDD, there would be less of a problem here in this case.

I myself have hardly ever needed a debugger in any code i've worked on that has been TDD from the ground up. And it is almost ALWAYS related to OTHER code that was clearly not written with TDD in mind.

Tell me something: What exactly is a "bug"? It is literally just a state the programmer did not expect, correct? So how do you keep all states expected? By constraining them (types, guards, etc.), by testing them in the small (unit testing, TDD), and by making them (ideally) immutable values (preventing unexpected changes to values within one stack frame). If you can control all possible states in the small, you can largely eliminate bugs in the large.

At least, I've found this to be the case after 20 years of working on procedural and OO code...

I am yet to see TDD work with native GUIs.
http://stackoverflow.com/questions/382946/how-to-apply-test-...

It's possible, and it works. Read the topvoted comment there and follow its links.

"This approach removes the GUI layer from TDD and unit testing. It does not mean the GUI is never tested but just acknowledges that it is not cost effective to pursue automated GUI testing, particularly as part of TDD. Integration and user testing should cover the GUI."

Hence, not tested at all via TDD.

I'm not going to say categorically that you never need a debugger...

But, I've been working with Go for years and have never used a debugger. I don't feel like I'm missing out on anything.

That is true, I used to work in legacy Java code base and the debugger was my Lord and Saviour. I am now working in fresh, well tested (both unit and integration) Go codebase and I yet to have to use debugger. Usually adding few debug logs (which usually just stay there for future) and writing test case for new discovered edge case is enough.
Finally, someone who's had the same experience i have had and which i got downvoted for!
Programming in C# feels almost like scripting. Blazing-fast compilation with the added benefit of static type system. If only MS took a different path of cross-platform support in the beginning.
That was already our experience in Turbo Pascal, Delphi, Oberon, .... :)

My only complaint is that they took the CLR path instead of the Ext-VOS one, with is now reborn as UWP (aka WinRT).

What is your favorite opening? I like the High Chinese.
If someone makes an alternative go implementation, they should name it baduk or weiqi.
At least it would make the language and ecosystem [slightly] more Google-able.
It would collide with the game. It should be worst in the beginning.
>As I had before, I recognized that this technology had the potential to revolutionize how software was written at a fundamental level.

Congrats and all, and I love Hugo (use it all the time).

That said, I think the kool-aid was spiked with something.

Sorry, but in what way is Go "revolutionizing"?

I'd buy "refreshing simplicity" and "yay, static builds again" but it's hardly revolutionary, even in its most touted feature (channels).

And it hardly changed how people write software. At best, it introduced some dynamic language programmers to static types and static builds.

All the rest, including creating a language that's easy for average programmers to program at scale was already the goal, and a success at that, of Java.

Some of the harder more time consuming things in high level programming include abstraction/polymorphism, concurrency and dependency management which are all simpler and clearer in Go than in Java. Think about how many hours you have to invest to learn any of these things in either language.
> abstraction/polymorphism, concurrency and dependency management which are all simpler and clearer in Go than in Java

Really? A lot of copy/pasted code, generics replaced with casts on empty interfaces, poor support for collections, only very primitive concurrency tools, and so on...

I can understand that simplicity is good for small CLI/network tools, but it is hardly an alternative for really big applications where Java is vastly used

Your big application shouldn't be that big first?
So you're saying we shouldn't have operating systems, browsers, video games and all that good stuff?

Most actual engineering is very far from writing a dumb server for yet another CRUD app :)

What I'm saying is Golang is a recent programming language so it works best when used for multi tier/services, not to create a giant monolithic Java app that has a huge number of loc.
What does Java have to do with big monolithic apps? I think you're confusing complex application domains with bloat.

Go is supposed to be a systems programming language. That means a very, very wide range of possible domains, where for many of them even network latency is unacceptable. For example, Photoshop would have a terrible user experience if it wasn't the monolith it is. A game engine wouldn't go above ~20FPS (even 60FPS games have a network loop that is capped around 20FPS).

If I can't do systems-level programming in Go, what's its advantage over real systems languages or higher-level languages then? Especially when you consider what Go offers (CSP) comes in opt-in libraries in many other languages.

I feel like Go should be put in the same category as C# and Java. They're just above systems languages but just below scripting languages; giving you the worst of both worlds. Not bare-metal, but also not that productive.

Java does run bare metal and there are commercial JDKs with real-time GCs.

PTC is one such those vendors,

http://www.ptc.com/developer-tools/perc

Go might eventually be used in such scenarios, but the toolchain is not yet there.

That depends on business needs, not what some programming language designer thinks.
Think about how many hours you have to invest in writing workarounds for features available out of the box in other languages.
Think of all the hours you save not having to work around the misfeatures available out of the box in other languages. I know, you don't make mistakes or use those nasty features, but think of your coworkers.
My coworkers are savvy enough to handle those features.
Then you are a very lucky person. For the rest of us, it is very good to have a manageable language at hand.
We can easily manage Java, C#, C++, Swift, Objective-C, JavaScript across our consulting projects....
Of course you can. None of those languages would be in use, if projects could not be managed at all. The question is: are you benefiting from their "features" or are you able to succeed despite of the challenges brought up to you because of those features and their complexity?
It was the simplicity of Java 1.0 that lead to some of the famous patterns we see in some frameworks, that were initially created to workaround language limitations.

The same path that is being followed by those that rely on libraries to reduce error handling boilerplate and go generate, just as two examples.

Who is using libraries to reduce error handling boilerplate? I rarely see `go generate` used for things that don't require static code gen (e.g., automatically generating bindings to C libraries). Sounds like you're inventing problems...
Go's big success, in my opinion, was to fuse the lightweight, spawn a million threads we don't care, style of programming to conventional imperative, conventional static-type programming. I know of several other runtimes that had that lightweight threading capability, I've been using them since years before Go was even a thing, but they all required programmers to learn a new paradigm. At times, a radically new paradigm (Haskell).

You may complain that programmers have a professional obligation to learn those new paradigms. You may complain that programmers should consider "learning a new paradigm" a smaller strike against a language, especially if it brings other good things with it. But that won't change observed reality, in which programmers do want to not have to risk several months to a year on something they aren't sure will pay off. By contrast, if you know any of the existing manifestly-typed languages at all (Java, C, C++), which most programmers do to some extent, you'll be writing fancy concurrent code in Go next week. Possibly even "tomorrow". You can be shipping production code in a month.

The language nerd in me really wishes Go had isolated its goroutines from each other and only passed things by value. (While I like Rust's much finer-grained handling of that for a lot of other reasons, you can get a lot of the benefits in a language where the threads aren't supposed to be that large by isolating to small threads, and it's way easier to implement.) The pragmatist in me is forced to reluctantly admit that had it done so it probably wouldn't have succeeded as much, because while that may not have been a "full" paradigm shift if the rest of the language was still imperative, it still would have been at least half of one. That affects how you design larger programs. In a lot of good ways, I think, but still, change with an unknown prospect of payoff.

So... it depends on your point of view. It's not revolutionary in the sense that there's anything new in it. But it is a somewhat revolutionary combination of concepts.

You're even free to join me in being a bit sad that fusing your concepts to an Algol-descended language is basically mandatory for success right now. But, one step at a time. We are slowly creeping away from it. As I've often observed, programming as a profession does not move anywhere near as quickly as some people think; there's a constant surface churn of technologies and languages, but deep paradigm shifts take decades.

I take no issue with your take on the language, but the OPs' opposing views on "revolutionizing how we write software" isn't really addressed by you.

Go is popular because it is accessible. The cognitize load of the language is in effect ammortized by being spread over the life cycle of the dev process (i.e. run vet to do x) instead at localized in cycle/space of code-time/source-code, so even professionals not bothered by complexity can see an incentive to using the language.

But I am not aware of the language enabling a class of software systems, etc., that have become more feasable because of the language.

As has been pointed out by many, at some point even the novice programmer has to get serious given the mix of pointers and channels and sync constructs which demands a degree of sophistication, so the accessibility aspect degrades over time.

And then -- and here is why I feel there is pushback regarding Go koolaid -- this somewhat on 'the fence' approach of the language towards concurrency (originally "communicate don't share memory") gives this impression of a glorious hack but a hack aspect to this "revolutionary mix" that you refer to. At some point, the ala cart type system of Go presents issues to people who have invested the time to get serious about these matters but find that their favorite light-weight language is not fully up to the task of keeping up with our conceptual models of thinking about our software.

> I know of several other runtimes that had that lightweight threading capability, I've been using them since years before Go was even a thing, but they all required programmers to learn a new paradigm.

One of those runtimes is Ruby (Ruby uses lightweight threads, not OS threads), and Ruby is not a new paradigm.

Ruby (that is, the main implementation, from 1.9 on) uses OS threads with a global lock so that only one thread running Ruby code is executing at a time in a process, same as, e.g., Python.

Up through 1.8.x, Ruby used N:1 lightweight threads (multiple lightweight threads on one OS threads.)

Go uses M:N threading (multiple lightweight threads, which may be distributed among 1 or more OS threads.)

M:N threading is a different model than either the Ruby 1.9+ model (1:1 threading on OS threads with a global lock) or the older Ruby approach (N:1 threading), or even the JRuby approach (1:1 threading on OS threads with no global lock.)

Was it stable enough to really use, though? Python also had gevent and stackless, but as far as I can tell, it never really got to the point where you could just count on it in production at high loads. It was never as stable as Erlang. They were more on the toy side that production-reliable side.

For further proof of my point, I submit the fact that you are basically correct, yet those technologies never took off, even in their own communities. The dominant way all the scripting languages are written are as single threaded code, and the second most popular way is as event-based code. It's not easy to bolt that stuff on ten years after the fact, which is what most of those technologies did.

Lua would probably be the better thing to cite as the possible counterexample, in that it does seem like a lot of the people using it are at least using coroutines, though I believe it is not possible/feasible to get them threading in any nontrivial way.

(I'm not taking the out of claiming dynamic typing counts as a "new paradigm"... probably the single largest true programming change in the last 20 years is the mainstreaming of dynamically-typed programming languages. Which I think was still a good thing for static languages because it raised the competitive bar for them; I've personally swung back over to static typing, but the easy of the dynamic world has pushed the static world to greatly improve its cost/benefit proposition, in both categories. If my only choice was dynamic typing or what we had in the 1990s, I'd still be in the dynamic world.)

As a final postscript, may I observe that while I think that Go was a modestly revolutionary combination of concepts, I consider it an indictment of the programming community that it did not happen sooner. I don't see Go as if it somehow won a big race by being the best... I see it as a situation where it's the first thing that bothered to show up, years late, somewhat desultorily.

>You're even free to join me in being a bit sad that fusing your concepts to an Algol-descended language is basically mandatory for success right now.

I'm ok with the Algol part as it pertains to syntax.

Semantics and expression though, is another thing...

>Sorry, but in what way is Go "revolutionizing"?

By offering simplicity. Taking a step back to before C++. And providing a better C. C + strings + GC + map + slice(array) + json/xml parsing + http transport layer (server & client). What else do you need? Ideal for minimalists. That's its beauty. Programs are very stable. Takes less memory than Java (some amount more than C/C++). Faster compilation time compared to C++. A convenient C. For minimalists, who like to cut down all the jargon, and solve the problem. Looking at it that way, you see its beauty.

edit: typo

> And providing a better C.

I keep seeing this come up and I wonder if people have actually used C in the domains where it matters.

Go is not a C replacement/better C. You don't have control over what goes on the stack/heap which means you can't control memory layout. If you can't do that you're throwing away one of the key reasons you'd use C. Memory layout is critical to getting that 10-50x performance that you can't get in a managed language.

There's a bunch of domains where Go excels but if you're on constrained hardware where you really need the last bit of perf/memory it would not be the tool I reach for.

> Go is not a C replacement/better C.

Its not a replacement for C in most of the places where C is far and away the best existing choice for a whole project, it is a replacement for C in the zone where C's performance and static typing are attractive and would decided the choice in its favor, but Python's expressiveness, batteries-included stdlib, etc. also make it attractive and make it a little bit painful that the other factors weigh in C's favor. For a system that you might be otherwise do polyglot Python (or some similar dynamic language)/C development for that reason (or where you might do C-only somewhat reluctantly for that reason), Go could be a reasonable replacement for C (and, in the case where the alternative would be polyglot, Python or whatever else.)

Sure, but in those cases Java/Swift/C#/etc are also reasonable replacements. If you're not taking advantage of data locality then it's possible to approach C's performance in any of those languages.

If your primary concern is performance(which is the only reason I'd reach for C today, esp w/ security concerns) then Go is not going to replace C in that domain.

> Sure, but in those cases Java/Swift/C#/etc are also reasonable replacements.

Well, Swift certainly wasn't when Go was introduced, but, yes, Java and C# were competitors in that role when Go was introduced (Java, even moreso at the time, tended to fall short on expressiveness -- which some argue Go does too, though in different ways -- and C# was deeply tied to .NET, which only had a first-class implementation on Windows; both of those have improved somewhat since Go was introduced.)

Swift probably, but Java and C# still suffer in a lot of situations from the lack of good AOT compilation options. There are implementations for both, but they're incredibly primitive compared to the JIT reference implementations.
Not .NET Native, which uses the same backend as Visual C++.
Unfortunately .NET Native is still for UWP only, so for most places you'd use Go it's pretty useless. Microsoft appears to have no plans to even bring it to ASP.NET: https://github.com/aspnet/Home/issues/285
Probably not, but they have CoreRT instead.

https://github.com/dotnet/corert

Many of us are actually mostly working on Windows, so NGEN, RyuJIT and .NET Native are all very good nice toolchain features.

And if I compare Go with the whole .NET stack and tooling, there are lots of things I see missing, in spite of better AOT support across the board.

... which is still in a fairly early state, like I said. And NGEN doesn't help the issue of runtime dependence at all.

I'm not really a fan of Go, but being able to write small tools in it without pulling in a huge runtime is a big drawback.

But that isn't a language feature, rather a toolchain one.

Once upon a time, on the PC we only had static compilation, regardless of the language.

.NET Core would help with the runtime dependencies (XCopy Deploy), but currently it is also WIP for those of us that care about desktop applications.

Is the .NET stack and tooling any more a language feature? You were happy to argue that tooling was important a moment ago.

In any case, when choosing a language for a project which doesn't fit your requirements because maybe the tooling will get there someday, I think you're going to pretty consistently end up in a sticky situation. I like C# a lot more than Go for most things, and some of the reasons are things you listed, but the goalpost shifting is getting ridiculous.

I am just digressing, sorry if you see it as goalpost shifting.
>it is a replacement for C in the zone where C's performance and static typing are attractive

Was C's "static" typing ever attractive as a static type system?

> You don't have control over what goes on the stack/heap

You do have this control. There is escape analysis, but I've never had to dance with it to make it put things on the stack when I need them to. I can get very close to C speeds with Go without much effort.

Can I say X is a value-type(or better annotate it in declaration)? If not then I don't have that control.

Your compiler doesn't know your data access patterns, dataset size or a myriad of other factors that you need to tune if you really want to get full utilization from your hardware. To be clear I'm talking about ~5% of software out there, but when you need it you really need it.

Yes, the distinction between value and pointer types is explicit in the language, so you have all the control. This is, why you also have more control about the memory layout than in Java, which makes a huge difference in performance.
For the time being, until Java 10 gets released.

But how things are going regarding Java releases, Go could even get generics before Java 10 gets released.

Yes, it has value and pointer types, just like C (except without pointer arithmetic).
In that sense, Java and C# both have control too.

There are lots of cases in which escape analysis falls down. In particular, higher order control flow (closures/interfaces) will always cause it to fail, until Go implements some sort of higher order control flow analysis (which I doubt it will). Go uses interfaces a lot.

C# doesn't have escape analysis, but it has stack-allocated value types. Java doesn't have stack-allocated value types (yet), but it has escape analysis. It seems a lot harder to me to reason about escape analysis without value types, and I have no idea what happens in C# if you take a reference to a value type (i.e., is it moved to the heap?).

I never meant to imply escape analysis was somehow perfect; only that it is (mostly) easy to reason about.

If the constrained hardware is more powerful than a Xerox PARC Dorado (Mesa/Cedar), a ETHZ Ceres Workstation (Oberon), DEC Firefly (Modula-3), then Go is certainly a better C.

Nothing prevents you to make use of statically allocated data structures, hands off from the GC if really needed.

In spite of lacking a few features that I consider any modern language should have, ability to create memory friendly data structures isn't one them.

> Nothing prevents you to make use of statically allocated data structures, hands off from the GC if really needed.

Only if you give up closures, interfaces, defer, strings, the entire standard library, and all sorts of other things that don't immediately come to mind.

Programming without the GC in Go is technically possible, but impractical. The language just wasn't designed for that (and this isn't a knock against the language--it just was a non-goal).

I didn't say to not use the GC at all, rather to use it less.

We can use the GC for the 90% of the code that isn't performance critical, enjoying the programming productivity of using a GC enabled language.

After profiling the application and find out where those 10% performance/memory critical hotspots are, re-architect the data structures to use static allocation, either via the stack (compiling with escape analysis validation) or the global memory. Or even doing off-GC Heap allocation via syscalls.

Then make use of pointers or array indexes to access the static allocated data.

Plenty of examples in Modula-3, Oberon, Mesa/Cedar research papers.

There are plenty of languages that I would rather use for systems programming instead of Go, but the language is certainly capable of being used in the same scenarios as Oberon.

For example Astrobe, which sells bare metal Oberon compilers for ARM Cortex-M4, Cortex-M3 and Xilinx FPGA Systems.

If anything, comparing Oberon's SYSTEM with Go's unsafe packages, Go could use a few more intrinsics like CPU register access, but those as also doable with a bit of Assembly help. Which ANSI C also doesn't support.

My goal is just creating awareness that alternatives are possible, it doesn't need to be always C.

Just to make myself clear, on the point of 'providing a better C'. I just made that comment from language evolution point of view. And did not at all mean that Go is better than C, in all respects. I dare not say that.

What I meant was taking a step back to a point before C++ was created. And looking ahead, and choosing what works and is essential (strings, GC,... and some modern Internet usage things...concurrency...etc), and getting rid of all the bloat, which actually comes in the way, especially the opinionated bloat on how software should be done e.g. OO. And making a language based on that.

For some reason, this discussion reminds me of Linus Torvald's angry defense of using C, for git[1] :-)

[1] http://harmful.cat-v.org/software/c++/linus

How do you know this isn't just a new language thing ? All of the advantages you say always result from essentially any redesign, and they never last.

A quote from "Java in a Nutshell", from (I believe, 2002):

"Because Java is a simple and elegant language with a well-designed, intuitive set of APIs, programmers write better code with fewer bugs than for other platforms, again reducing development time."

Reads pretty similar to your argument for Go. I remember similar quotes for Modula-2, ML, (a lot of versions of) LISP, C itself, and I'm sure there's many more. It seems to me pretty likely that we're seeing the same evolution : Go currently is a simple, easy language that matches the current hotness (microservices) pretty well, because it was directly written to support that. The current hotness will go away and Go will have effectively-mandatory bloated libraries to support the next hotness, just like today it's becoming close to embarassing to use Go's standard library's http server for anything non-trivial.

Additionally, many of the criticisms of C apply to Go. It's looooooooooooooooooong simple code doing "a; if error { ... }; b; if error { ... }; c; if error { ... } ...". Many abstractions just don't work, and have to be "fixed" with crutches (like sorting, logging, ...)

Aah, Seeing such a good reply, so late. Does HN need notification? Probably not :-)

So, I agree with you a lot. There are no guarantees that Go will remain good for ever. It would be a challenge and need effort on the part of the language developers.

That said, I believe, when a language evolves over a period of 20 years. You get the benefit of hindsight to introduce the good things in a new language. So, Java's garbage collection is a big success. And Go developers incorporated it. Its a tradeoff with extreme (C like) performance, and devs went with convenience and security. Good call, in my opinion.

But the object oriented part of Java, in my opinion, is just a C++ inheritance, as at that point of time (mid 1990s). OO was the silver bullet, to all your sofware spaghetti problems. But as it turns out, it got more complex, if the design/architecture was bad. And good engineers design good enough without the OO.

So Go has taken that approach, which gels with me and lot other developers.

Your comment regarding the error handling part. Yes, it is cumbersome. But surprisingly, it seems to look better than exception handling when you write couple of modules with it. And for some reason, which others have articulated better than I can at this time, your programs are more stable as a result.

So overall what I like about Go, is the minimalist approach of just having the proven things which are good. And avoiding which are grey area or bad.

>By offering simplicity. Taking a step back to before C++. And providing a better C. C + strings + GC + map + slice(array) + json/xml parsing + http transport layer (server & client). What else do you need?

Language consistency (no magical functions like "make" or magical items like slices), DRYness (generics), better type-safety than C (interface{} is the void * of the 21st century), would be a good start.

Due to the mandatory GC, it's also not a C replacement where C is good at. Hence the backtrack on "systems", etc.

My question was more rhetorical. But thanks.

After posting, I realized its concurrent programming model, is another thing which I (and many others) am a fan of. I found the channel and go based approach, much better compared to explicit spawning of threads in languages like Java and C++.

> Due to the mandatory GC, it's also not a C replacement where C is good at. Hence the backtrack on "systems", etc.

I tend to complain on Go's design decisions and don't have any actual use for it, but given my experience with Oberon, I do believe there are use cases where it would be possible to use Go as systems language.

For sure not in when targeting 8 or 16 bit CPUs with a few KBs, or timing constraints that cannot deal with possible GC pauses.

But for more beefy micro-computers like the original PI, it can certainly be an option.

This would a good starting point for anyone trying to attempt it

http://wiki.osdev.org/Go_Bare_Bones

Also I consider the ability to write compilers to be systems programming use cases and Go is already bootstrapped.

Having said this, yes there are better options to do systems programming with less need of Assembly help.

It's not really surprising though is it. He worked for MongoDB. He's a "magpie developer".
>At best, it introduced some dynamic language programmers to static types and static builds.

Can confirm (well, add another point of anecdote), I played with it a bit in order to get some experience with static stuff before diving into the whole C ecosystem.

Next thing I build that needs that kind of development will probably be C though.

(comment deleted)
I'm sorry to hear that. Go is not revolutionary (unless you count "completely ignoring runtime errors" to be revolutionary). If anything, functional languages are the new, old, revolutionary thing.
How does Go completely ignore run-time errors? For all I know it forces you to deal with them by treating them as values instead of exceptions.
However it treats them as product values (tuples) instead of sum values (Either), so it's perfectly possible to ignore the error and take the result anyway.
Ignoring on purpose is fine. The problem is when the only return value is an error which can be ignored simply by not assigning the result to a variable. Forcing the user to do:

    _ = f.Close()
... in order to explicitly ignore the error would be nicer, but then, there are many functions which are known to never be checked for their errors, like fmt.Println. That's why the typical advice is to use errcheck, which has filters to avoid "false"-positives (I am not convinced that some function never should be checked for errors).
> functions which are known to never be checked for their errors, like fmt.Println

In Java println is checked for errors, as it should be. Every Java program that does println either aborts or deals with the error in some way.

It matters. Take any program that writes to stdout and run it with ">&-" to close stdout. Because of unix, the next file it opens will be file descriptor 1 and the program will start writing the console output to the file. You want the program to abort instead of trashing a file, and especially not to trash /etc/passwd.

That's why you don't want to ignore errors, because any time you do there can be unintended and hard to imagine consequences -- even something as simple as writing to the console. Simply put, Go encourages buggy programs with poor error handling.

And the cynic in me says that, if you do that with a program that handles the password file, you almost deserve what you're going to get...
I tried your example, and observed an error: write /dev/stdout: bad file descriptor

What "next file it opens" are you talking about exactly? How does what you're describing work?

In unix when you open a file it gets the lowest available file descriptor number. So if you run a program with no stdout (file descriptor 1) then it gets a "bad file descriptor" error anytime it prints something until a file is opened, gets file descriptor 1, then it starts writing to the file.

Example:

    #include <stdio.h>
    int main(int argc, char **argv) {
      printf("first message\n");
      fflush(stdout);
    
      fopen("output", "w");
    
      printf("second message\n");
      fflush(stdout);
    }
Output:

    # ./a.out
    first message
    second message
    # ./a.out 1>&-
    # cat output
    second message
By ignoring the error, the program continued on and then wrote console output messages to the file after it was opened. There have been exploits due to this bug, but the real point is that you could never predict this failure without good knowledge of unix and careful consideration. This is why error codes should not be cavalierly ignored, because it's really hard to know what might happen if you do.

Last I checked, Go operates the same way as this C example. Java fails on the "first message" if stdout is closed so it doesn't trash the file, not because they even specifically thought of this scenario but just because errors are not ignored by default and are not easy to ignore.

How does treating them as values force you to deal with them (except on principle)? Does the language force you to check the return value of every line of code? And the checking would only encompass expected errors, not unexpected ones, no? The unexpected ones (read: bugs) would simply be swallowed up and the actual problem would finally turn up far away in some other stack scope, no?
True, you can discard errors on purpose by assigning them to "_", which is an explicit way of saying "I do not care about this error happening". If you do that and get a panic down the line, you already know where to start debugging. That's much better than having an exception bubble up from deeeeep inside your code with some context-less cryptic message or number, isn't it?
> If you do that and get a panic down the line...

No, you don't panic, you are most likely to corrupt your data and maybe continue working as if everything was fine. If you are lucky, your code panics.

> ... you already know where to start debugging.

Grep all occurrences of "_"?

> That's much better than having an exception bubble up from deeeeep inside your code with some context-less cryptic message or number, isn't it?

No, the exception carries all the context you need. If you ignored a previous exception, the next one won't be as useful as it could, but at least your code breaks loudly.

Also "_" means the programmer chose to ignore the errors that he knew about at the time.

There's no way to know whether the programmer actually considered all the error cases (they are generally very poorly documented in Go code), and there's no way to know if the called function added errors at some later date. If it's though an interface, there's no way to know that all implementations have the same errors.

It's really an 80s-era approach to error handling, and that's bad.

> That's much better than having an exception bubble up from deeeeep inside your code with some context-less cryptic message or number, isn't it?

I don't see how that follows. A stack trace (as initially cryptic as it seems) is a record of all the code that would have affected the current buggy state you find yourself in. If anything, a stack trace isn't comprehensive enough, ideally it would include all known/named values at every level of the stack... a large quantity of information, to be sure, but perhaps it could be narrowed down by diffing each stack level with the previous one or something. But if you could have those 2 things, you would have literally ALL the information you needed to fix the bug. Since bugs are programmer-unexpected states, and the stack trace plus the known values at each stack level are LITERALLY the entire state.

So correct me if I'm wrong, if you don't assign an error to a variable on the same line in Go, it throws? Because it was my understanding that there were absolutely no throws at all in Go. Or is it only that certain kinds of statements are expected to possibly error, and must therefore be assigned to a variable (or _)?

Any error return values in go must be assigned to a variable at call time, otherwise it's a compile error. Unused variables are also a compile error, so you are forced to do something with it.

Assigning to _ effectively ignores the error, but is considered a very bad practice.

Unavoidable runtime errors (eg divide by 0) will generate a panic, which is similar to an exception, but is uncatchable within the Go routine it originates in.

Any error return values in go must be assigned to a variable at call time, otherwise it's a compile error.

Nonsense.

   fmt.Println("Hello world!")
I just ignored an error and it compiles fine. Go check the return type of Println:

https://golang.org/pkg/fmt/#Println

tl;dr, it's very easy to accidentally ignore errors in functions that are side-effecting or modify parameters. Been there, done that.

Yeah, that's what I thought. And I've also been there, done that. Is there basically some willful blindness around this issue with Go fans, or something? Or a lack of experience doing code? Or am I completely missing something?
To illustrate my point: If I implemented some network program which converses with a remote server in multiple steps in an language with exceptions and something fails I might get a stack trace and the message:

"Syntax error, expected token HTTP_METHOD but got 'B'"

In Go, with proper error handling I'd get a message like:

"Couldn't do flubber transfer: Unable to negotiate protocol: Sent supported protocols but remote responded with HTTP 400 "Bad Request": Missing required field 'version' in protocol definition"

As "error" is an interface, this message is only the tip of the iceberg: the error object itself may contain the address of the remote server, the protocol definitions that were sent, the response body that we got and any other relevant contextual payload.

This is all due to the error being treated in-context as opposed to just bubbling up.

>In Go, with proper error handling

Well yeah, if you handle errors properly, you get better results than if you don't.

The point is that with exceptions, it fails loudly and you get the cryptic message even if you forget, whereas with Go, if you forget to handle an error, you just get weird behaviour and corrupt data.

And if you want more helpful error messages, you can catch the exceptions and report the context just as easily as you can in Go.

> > That's much better than having an exception bubble up from deeeeep inside your code with some context-less cryptic message or number, isn't it?

> I don't see how that follows. A stack trace (as initially cryptic as it seems) is a record of all the code that would have affected the current buggy state you find yourself in.

You get stack traces in Java, C#, Python, etc. You don't get them in C++ (well, you aren't guaranteed to get them).

But you agree that a stack trace is a tool to mentally reconstruct (read: "realign") your mental model of the state the code produces, with what really happened?
You won't know where to start debugging if you do that more than 3 or 4 times.
Dave Cheney gave a talk about error handling in Go that sheds some light on how the Go community thinks about errors:

https://www.youtube.com/watch?v=lsBF58Q-DnY

Wow, that talk just demonstrates that all downsides about error handling in Go are due to its lack of exceptions (at least how they work in languages like C#). It's a step backwards, it's ludicrous.
I watched this, and what I saw was a heck of a lot of information about how to extract information from error values and percolate them together up to a handler, all of which would automatically be present in your everyday stack trace in a language that actually threw unexpected runtime errors. ;)

I frankly don't see how this is OK, nor better. Errors are real in the sense that they are evidence that the programmer's mental model of state did not line up with the actual state (usually in some corner case). There is literally NO circumstance in which being in a programmer-unknown state (yet still "alive" so to speak) is better than being in a programmer-known-and-accounted-for state. (For an example of being in a programmer-unknown yet alive state, see: Every Security Hole Ever.) This is why "throwing" is appropriate, no matter how much the Go creator didn't like it. If even a single runtime error goes undetected/unhandled, you will end up further and further into an unknown state due to state corruption, and your behavior will soon become completely nondeterministic (or at least, nondeterministic-appearing). Losing determinism is the first step on the road to dragons.

I literally can't see how this wouldn't happen, and what I AM seeing is a lot of chatter in Go communities about how to manage this problem, when the solution is already there: Just fucking throw a stack trace. Or, even better, do what Erlang/Elixir do: Throw it, log it, and have a supervisor process kill it and restart it, all in 1 millisecond or less. If the error keeps happening above a certain threshold rate, kill and restart the supervisor as well. The reason this works (and has resulted in the INSANE uptimes that Erlang-backed services have) is that it resets state to programmer-known conditions.

I don't think the original Go authors ever truly thought that exceptions are "bad" per se. I think they just took it off the table because of the complexity it added to the language, both conceptually and implementation wise. A (the?) primary main goal of Go from the beginning has always been to make implementation as obvious as possible; in other words, to make it a slightly thicker layer on top of assembly than C was (they seemed to like Java 1's idea of interfaces), while still keeping in mind that it will map to assembly. The language's design is inherently tied to its compilation model. And to add exceptions would add complexity to it which for some reason they considered to be "too much". Same story with generics fwiw.
To whom is the implementation of a generational, concurrent GC obvious? It requires a lot of compiler infrastructure and complex runtime support, much more than stack unwinding. I'm not a fan of, say C#'s, exception model, but it's far from the complexity of features Go already has in either implementation or programmer understanding.

On top of that, unwinding isn't the only way to get something where errors have to be handled or the program dies. Look at Swift's error handling for example: it's basically sugar over returned errors with correctness checks. Dead simple implementation, and dead simple to explain to users.

What I don't buy about the justifications for Go's design is that they were driven by the pure guiding hand of simplicity. It looks more to me like the designers simply treated language features they had seen done badly before as anathema and didn't try to think about how the mistakes could be corrected.

You do also have panic available which is for exceptional cases
Go forces you to use errcheck.
(comment deleted)
(comment deleted)
You're "sorry to hear" that he got a great job doing something he's excited and passionate about? Wow.
Funny how taking things out of context can change the meaning. If you look at the second sentence, you can infer what the first one is about.
Not really. It's a top-level comment. If it were a reply to the "in what way is Go revolutionary" comment, the "sorry to hear that" could reasonably be inferred to mean "sorry, but..."

    I'm joining the Go team at Google
    Sorry to hear that
    Go is not revolutionary...
> > Funny how taking things out of context can change the meaning.

> Not really.

I can assure you that it is indeed funny.

The one request I make is, please do not give in to complexity in order to accommodate to all users' requests.
One thing I liked the most about JavaScript was chaining methods.

One thing I liked the most about c# was the libraries in one place.

One thing I liked the most about PHP is the many array methods and easy to call methods from objects.

One thing I liked the most about Python is the readability and built in debugger into the language.

One thing I didn't like about all of them is all the libraries you have to memorize.

How does this guy just stumble his way into Mongo and Docker. WTF am I doing with my life?
I dunno, perhaps develop very good open source projects like Viper, Hugo, etc...
(comment deleted)
(comment deleted)
I interviewed at Mongo a long time ago for a Drupal developer position. It was strange, they took me through a bunch of whiteboard algorithm crap that had nothing to do with Drupal. Obviously they weren't Drupal devs and didn't know how to interview for one so they just gave me the standard CS stuff. Obviously I was a Drupal dev so I didn't know shit about actual CS topics. I failed hard and learned a lot from it.

Steve was the only one of the 3 that I interviewed with that didn't come across as a self-important asshole. He was kind and helpful and overall seemed like the perfect guy for a Developer Advocate or whatever the title was. I wish him luck.

> they took me through a bunch of whiteboard algorithm crap that had nothing to do with Drupal.

Oh I hate that type of interview. I had a similar experience getting interviewed for a front-end dev position by two backend devs at a consumer VPN company in Toronto who asked me to write common CS algorithms while they both sat there staring at me.

Even ignoring the total lack of connection between the content of the algo with the job in question, I've never coded like that in my life. Largely because I also never took a CS course and didn't bothered to study cliche interview questions because I don't apply to big cos. But most importantly, I don't solve problems on the spot in front of other people IRL, so what aptitude are they testing for exactly?

I'm an introvert who always codes with headphones on and likes to spend time thinking through problems on my own - but can also work with other devs to solve problems when needed. I also had OSS projects, private repos I could show them, and live production apps with tens of thousands of visitors I built myself to point to my aptitude. That's been more than enough for other smart teams to hire me. It's also the content I look for most when I've hired people myself.

The non-technical founder also never told me ahead of time they were going to do this type of interview so I was surprised when they sat me down.

Also during a telephone interview with their other semi-technical founder asked me to describe how NAT works (yes asking a front-end dev to describe network implementation details). I figured he was just confused about what I would be doing for them... then I showed up to meet the two backend devs the next day.

I just walked out of the interview and told the founder his hiring process was silly, even though I liked the company (product). I'm happy I did.

I should note that I'm not against the idea of measuring aptitude during the hiring process, if companies want to be thorough. For example. during another interview process with a different company a dev team gave me a problem to solve (with ample warning before I arrived that day) and let me solve it on my own, using my own laptop in a quiet room, while they went back to work at their own desks for an hour or two (taking however long I needed). I was fine with that process and it worked out. There was also a collaborative element to it as well. That was a test better grounded in the reality of software development.

Person who interviewed you here. Our interview process may not be perfect, but surely going into a technical interview, you could expect some coding questions. You mentioned that we "asked [you] to write common CS algorithms", like we asked you to do invert a binary tree. That, indeed, would be ridiculous.

In fact, if I recall, we asked you to reverse a string. This is not an "algorithm" question, it's a basic programming aptitute test and if you can't do it on a piece of paper, this is a major red flag for us. Furthermore, you demonstrated a lack of understanding of basic JavaScript concepts like prototypes and scoping. This, and your personal attitude, were the reason why we did not hire you for the front end deveoper position.

You are no doubt a hardworking and resourceful individual, but we were looking for something more than ability to glue JavaScript libraries together. I wish you, and "other smart teams that hire [you]", all the best.

Hey, what was the acceptable answer to reverse a string in javascript?