8 ms·
My impression is that Go is a language that was cobbled together to simplify the coding of some specific applications, such as simple servers. It lacks any kind
by greg7mdp 10y ago
My impression is that Go is a language that was cobbled together to simplify the coding of some specific applications, such as simple servers. It lacks any kind of purity, is not the best choice for any specific task, but is just good enough for some (many?) tasks. And poor type safety!
Frankly, I can't help being disappointed by how bland this language is, and I have zero interest in using it. Maybe because I like coding, and the IMHO using Go or Java would totally kill the fun of it.
- aczerepinski 10y agoBut if you like typing `if err != nil` it's actually the most fun language.
- rpercy 10y agoHeh, it does feel repetitive. But after ~10 years with Java, I'm happy to avoid the cognitive load from deciding how to most politely generate/propagate an exception. Obviously, there's no perfect solution, and preference is subjective.
- stefano 10y agoIt's the same cognitive load, really. Instead of deciding how to best propagate exceptions, you're now deciding how to best propagate the error value.
- rpercy 10y agoNot really. In a language like Java, some of the questions I'd have to ask myself are: - Should I try to catch the exception, or just let it bubble up and edit my interface to include it? - Should I create a new exception type or reuse an existing one? - Should I throw a checked or unchecked exception? - Am I exposing implementation details via my interface? (eg I don't want to throw an SQLException from GenericDataSourceWidget.connect()) In golang, I know there's really just the one pattern: check if err != nil, prepend a descriptive message, and return it.
- Groxx 10y ago>check if err != nil, prepend a descriptive message, and return it. That'd be the RuntimeException equivalent, sure. But what do you do for the equivalent of checked exceptions? Errors are frequently recoverable, "err != nil" alone does nothing to help you there, and string manipulation is a horrific alternative to types.
- cdelsolar 10y agoYou can have typed errors too. This is fairly common in Go. As long as it implements the Error interface.
- Groxx 10y agoAt which point you're back to the original complaint of: - Should I try to catch the exception, or just let it bubble up and edit my interface to include it? - Should I create a new exception type or reuse an existing one? - Am I exposing implementation details via my interface? (eg I don't want to throw an SQLException from GenericDataSourceWidget.connect()) (except for "- Should I throw a checked or unchecked exception?" since that's fairly Java-specific) To me, those questions seem unavoidable, and sweeping them under the rug is a false simplicity. You're exposing things - what do you expose? How should the caller deal with it? Is it the same as [other thing]? I'd much rather have the type system involved, since error handling is pretty critical to correctness/stability. If go's giving up the safety, what does it get in return?
- XorNot 10y agoI feel like the type system is involved? If there's a problem it's that Go doesn't make throwing typed errors a common convention (and we lack the tooling to make handling them a habit I.e. inspect this call and find me all the error types which can come back.
- candiodari 10y agoIn reality Go makes it worse, if you truly keep track of all possible cases. After calling a method, in Go you have to 1) "if err != nil" after every statement 2) give some serious thought to whether the previous statement could panic or not Good luck if it's a library call that may get updated or call other libraries ! 3) Think about the non-error error cases that can't be abstracted out. Go is like C, in the sense that there is an ERETRY "error" (unsurprisingly, you should simply try again, you should NOT fail) And there are cases where there can be an error and yet error is nil. Easy example of this would be sscanf. And we now see practical Go code published online : how these problems are dealt with, real world edition: 1) either mindlessly putting "if err != nil { return err }", which is a very bad information-erasing exception system, or just outright ignoring errors. Don't you know you can also use "_" as the error variable ? Maybe they should make that implicit like in perl. Of course perl is likely to tell you this happened ... unlike C and Go. (really brings back the C days doesn't it ?) 2) most people either don't know or just deny this. Thankfully panics at least do list where they occur. They also kill your program and print stacktraces. Pages and pages and pages of stacktraces. 3) very few people even know about these problems ... so they're ignored, and the standard Go tools themselves don't behave according to unix specifications.
- cube2222 10y agoPanic is pretty much never used (so you don't really have to think if the previous statement can panic. If it does it means something is SO wrong that your application can't continue anyways because it's broken) You should really use a library like github.com/pkg/errors so you get to wrap the error you return with additional information. Errors are just a worse Either monad after allm they're much more pleasant to use than exceptions.
- geoka9 10y ago> Panic is pretty much never used (so you don't really have to think if the previous statement can panic. If it does it means something is SO wrong that your application can't continue anyways because it's broken) That's it. I think OP just assumed panics in Go are what exceptions are in other languages.
- hota_mazi 10y ago> I'm happy to avoid the cognitive load from deciding how to most politely generate/propagate an exception This is like saying "I'm happy to avoid the cognitive load of having to specify how my code should behave in case of an error". Sure, your code is simpler as a result. It's also more buggy.
- shurcooL 10y agoHow's that different from typing `for`, `switch`, or any other way of using a language?
- _ak 10y agoIt makes cyclomatic complexity explicit that is otherwise hidden by exceptions.
- jrs95 10y agoIt's used very heavily for everything container related. It seems to be an excellent fit there, at the very least. It's also becoming an increasingly popular choice for startups when they need performance, which used to be something Java or C++ were typically used for. Personally I've had a lot of fun using it, but prior to starting with it I'd mostly done Java and Node, so that may have something to do with it.
- greg7mdp 10y agoHow can you write an efficient container without generics?
- deleted 10y ago[deleted]
- labrador 10y agoI keep reading this and I keep wondering what's stopping someone familiar with language design from writing generics code
- Zach_the_Lizard 10y agoThey seem to take a lazy approach to feature development. Generics are complicated and bad, but having makeIntMap or makeStringSlice is...not great for developer productivity. So let's special case `make()`, slices, channels, etc. so that some productivity is possible. Then as they add library features they violate their own tenants as they find utility in these verboten constructs. Exceptions are bad...But we have panics which are in no way the same thing renamed. Never expose them outside a package...But closing an already closed channel panics. Random number generator functions panic on mundane and expected things, just like Java checked exceptions. Example: https://golang.org/pkg/math/rand/ https://golang.org/pkg/math/rand/ ``` func (Rand) Int31n func (r Rand) Int31n(n int32) int32 Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). It panics if n <= 0. ``` Standard behavior would be returning an error, not panicking, See this: https://blog.golang.org/defer-panic-and-recover https://blog.golang.org/defer-panic-and-recover ``` The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values. ``` It's just an inconsistent and, quite frankly, disappointing language outside of goroutines and its interfaces. Those two make it possible to be productive, but with generics for instance a whole slew of new possibilities will emerge. The simplicity is nice, but it's too simple and too inconsistent. All the verbosity of Java combined with the impenetrable inconsistency and abbreviations of C.
- mseepgood 10y ago> And no type safety! 90% type safety (probably even more) is more than no type safety. It's not a holy grail that all programming must strive for.
- deleted 10y ago[deleted]
- dtech 10y agoIt's a balance, but I am fairly disappointing that such an up-and-coming language has such a limited type system. In the days where even traditionally fully untyped languages are moving toward inferred, optional and static typing [1],[2],[3] I'm disappointed to see `interface {}` sprinkled throughout Go API's. [1] JS Typescript and flow: https://www.typescriptlang.org/ https://www.typescriptlang.org/, https://flowtype.org/ https://flowtype.org/ [2] Python with mypy: http://mypy-lang.org/ http://mypy-lang.org/ [3] PHP with Hack: http://hacklang.org/ http://hacklang.org/
- mseepgood 10y ago> In the days where even traditionally fully untyped languages are moving toward inferred, optional and static typing This only shows that the sweet spot is probably not in the extremes, but somewhere in between the dynamic type system - paranoid type system spectrum.
- holydude 10y agoSo what means fun for you ? What kind of language meets your criteria ?
- hlandau 10y agoPersonally I like Go; it's a very fun language for me. It's true that it sometimes feels like a language designed for the precise purpose of writing daemons, but that's exactly why I like it. The thing about Go is that its opinions on concurrency are ones I share, to the point where I was practically waiting for something like Go to be invented. Other than say, Erlang, I'm not aware of many alternatives which provide a) ultra-cheap coroutines (10,000 coroutines? fine!), b) an I/O system which is seamlessly integrated with that concurrency system (and in a totalitarian manner at that; if you're using Go, you're using its event-based I/O scheduler, no exceptions), and c) a rock-solid runtime. [IO SYSTEM.] The imposition of Go's I/O system is important, because it means all Go code is written using the same I/O system, which makes code reuse much more feasible. The chances of you being able to integrate a random OSS library that you discover in say, C++ into your C++ project is much lower: I call design decisions that pervade every line of code in a project "cross-cutting considerations" (CCCs). These are design decisions where changing your mind means rewriting every line of code, or at least reviewing every line to see if it needs rewriting. Your ability to consume a library depends on where your project and the library sit in CCC-space, an n-dimensional space. If your project is written using an asynchronous I/O reactor, and the library uses a traditional synchronous, sockets-based programming model, you're screwed. You can't use that code, unless you maintain a fork (and in that case you'd have to transform the library into the continuation-passing style, etc.). If the I/O is pluggable, you have to go through the effort of plumbing it into the reactor library you've chosen to use, just to be able to consume that library. Not only does "using Go" imply the I/O system that goes with it, Go's tightness in language design means you don't see the feature rejection that you see in a language like C++. C++ isn't a language, it's a family of languages; everyone chooses their own subset of C++ to code in. Some people think exceptions are bad and avoid them, and some people think templates are bad and avoid them, etc. What this means is that the statement "this library is written in Go" is a hell of a lot more meaningful than the statement "this library is written in C++". It's not just C++ either; Python for example now offers a wide variety of choices for I/O, which inflates the CCC-space across which the language's ecosystem of libraries are distributed. One library could use asyncio, one something Twisted-like, one synchronous calls, one threads, etc. [COROUTINES.] It's the right way to do concurrency. Not the continuation passing style; it's truly preposterous that programmers have been made to write in a format originally intended to be implemented as a compiler transformation. Only recently are we seeing languages augmented with async/await keywords to allow this transformation to be performed behind the scenes (JavaScript, Python 3, C#). Erlang has been around a long time making the CPS look ridiculous, and later there was Stackless Python, an ignored gift horse to the Python community. Stackless Python failed to be a real alternative to Erlang, Go, etc. because it never managed to get a thriving ecosystem or IIRC, a standard I/O system around it. I also perceive that Go has almost completely accidentially obtained some additional fondness for the fact that it produces statically linked, portable binaries. If you're shipping only Go code, you may often be able to get away without using containers when they'd otherwise be essential. You see Go binaries for Linux being distributed officially by OSS projects when normally for Linux that's very rare; it's left to package managers, and you have distro differences making compatibility potentially tricky. The fact that Go shipped with a standard, configuration-free build system also makes creating new libraries, or bringing in existing ones almost completely frictionless. Even if you think Go is boring as a language, what really makes it stand out is its execution. Just look at how they're improving the GC with every release. (This turned into an essay... I guess my ultimate point is that getting a coroutine-based highly-scalable I/O programming environment to work as an ecosystem requires you to standardize on one runtime completely and utterly, and be able to trust that runtime with production workloads. The only such systems I can think of which are stack based and which formed successful ecosystems are Go and Erlang; though now we're seeing a lot more CPS-based systems using async/await annotation, which are probably more than good enough for the same applications. Although I would point out that neither Python 3 nor JavaScript are trying to occupy the multi-thread m:n scheduling space in the same way that Go and (I think?) Erlang are. They're constrained to essentially single-thread operation.)
- rpercy 10y agoTo each their own. I enjoy writing Go almost as much as writing Python. But more importantly I find reading Go easier than any other language - mostly due to its explicitness and consistency between authors. That has made it much easier to dig into code bases that solve some very complex and interesting (to me, anyway) problems. Also, I assume the 'no type safety' statement is just hyperbole?
- bitexploder 10y agoThey probably mean you can use interface{} and create a typing black hole if you really wanted to. Otherwise, I don't know.
- kuschku 10y agoOr maybe they mean that you HAVE to use interface{} for any reasonable kind of generics, such as developing generic data structures, or generic handlers for RPC interfaces allowing arbitrary nesting? Even the stdlib uses interface{} everywhere now: https://tip.golang.org/pkg/sort/#Slice https://tip.golang.org/pkg/sort/#Slice
- bitexploder 10y agoIs a good point. Smells of void pointers and old school Java collections.
- donpark 10y agoGo's blandness is a feature to me. It's not a joy to write but pleasant to read and understand which, sadly, won't matter unless Golang gains more popularity.
- rpercy 10y ago100% agree re: readability (as I've mentioned elsewhere). I've actually been very surprised at the near-ubiquity of Go in the modern infrastructure/tools space though. Seems like each new OSS product I evaluate is written in Go. See companies like Cloudflare, Hashicorp, InfluxData, CoreOS, and, obviously, big projects like Kubernetes.
- user5994461 10y agoGo is meant for distributed systems. All these companies, and generally speaking a lot of infrastructure thing is in that domain. They use the right tool for the job.
- IshKebab 10y agoI think that's mostly because Go trivially generates static binaries, and cross-compiling is also trivial (as long as you don't use CGo). I can't actually think of a single other language that matches that. Rust might get there one day but cross-compiling still requires a C cross-compiler (ugh) and C dependencies (e.g. OpenSSL) are often dynamically linked.
- Thaxll 10y agoNot using Java the #1 server language? What do you code your server in C++?
- rcpt 10y agoI've always believed that blandness is the reason why the language was created. Google has a ton of developers working on a giant codebase. If Google were written in something interesting and complex (eg scala or ocaml) then some parts of the codebase would be remarkably complex while others would be simply a ton of library imports and then something procedural. Whether you are in the former or the later would be developer dependent. Now, say you're a Google exec, you know you're losing a ton of developer hours as people ramp up to different parts of the codebase and that some parts are so complicated that only a few (expensive) engineers could ever work on them. The more you can remove differentiation between engineers and commoditize programming the less expensive specialists you'll have to deal with and (hopefully) things will get cheaper. There's a size at which the investment in creating a new, bland, language will pay off for you - hence golang.
- stcredzero 10y agoIt's more than "bland." There's a whole lot of "just works" in the whole ecosystem. Now, say you're a Google exec, you know you're losing a ton of developer hours as people ramp up Why wouldn't ramp-up time be a big company's most significant cost?
- shurcooL 10y agoFor me, Go is the most fun language I've ever used after 15+ years of programming. I like how simple and consistent, yet powerful it is.
- spraak 10y agoI don't disagree about the type safety and general qualities of the language, but saying "Maybe because I like coding" is really unnecessary language egotism. There are many, many people who love coding and love doing it in Go.
- stcredzero 10y agoIt lacks any kind of purity What language is pure anything? Even Smalltalk wasn't pure Objects. Programming languages are pretty complex. If you look deep enough, you'll find the leak in the abstractions.
- bsg75 10y ago> It lacks any kind of purity Example of lack of purity?
- geodel 10y agoSome(A lot of?) people use programing language just for day job. For them Java or Go would just do fine.