24 ms·
Why Go Is Not Good
- pilif 12y ago>I like Go. I use it for a number of things (including this blog) and yet it goes down once it is posted on HN. I have had some articles of mine end up on HN and I never went down, even when my blog was still WordPress hosted on a machine of mine. This is probably more of a shortcoming of the various cloud providers than of the language/environment itself I guess.
- chimeracoder 12y ago> and yet it goes down once it is posted on HN. The "Retry for a live version" button is powered by Cloudflare, which also uses Go for many of its core services. So I'd be willing to bet it's the programming environment and/or the particular program, not the language.
- IgorPartola 12y agoNot a great metric. My blog once got unexpectedly slash dotted (ended up on Reddit and HN front pages for a day; silly enough the post was the one I put the least work into by far and the idea was not even mine). I was at the time running WordPress with WP Supercache using only right PHP workers. The site never had a hiccup. Ergo PHP is the best language out there? :) In reality, do use something like WP Supercache. It will save your hide.
- deleted 12y ago[deleted]
- wyager 12y agoDang it! I wasn't intending this to hit HN so soon. I was planning beefing up my VPS before I shared this one on HN. Sorry. I'll try to keep it up. If you just let it hang, the Cloudflare cached page should kick in.
- zemo 12y agoprogramming language semantics and server availability are distinct topics. If you write a beautiful Haskell program that generates n+1 queries on a database, it will fall over. That doesn't make Haskell bad. Nine times out of ten, making a blog survive the heavy traffic of something like being on HN front page just means knowing how to cache things.
- s_kilk 12y agoThis was a good read. Can anyone comment on whether they find the problems outlined in the article to really be painful in day-to-day go development? From my initial dabblings with the language, it feels like its constraints may not actually be a big deal in practice, and may even be more of a help than a hindrance in large projects. It would be nice to get some commentary from more experienced go users.
- mholt 12y agoIn practice, Go has caused me less frustration than any other language I've used. I feel like the author's complaints here aren't really grounded in much experience, or maybe he's trying to use the wrong tool for the job. The author's conclusion: · Go doesn't really do anything new. · Go isn't well-designed from the ground up. · Go is a regression from other modern programming languages. is hardly sustainable. Go was production-ready in 2011 with a stable version 1.0. It has a surprisingly mature tool chain and vibrant community. Go cross-compiles from my 64-bit Mac to a 32-bit Raspberry Pi or ARM Android phone on a whim. I can deploy my app by copying a single, self-contained binary. Tell me again that Go does nothing new for us. Go makes concurrent programming safe and easy (with a nice syntax) -- something that we frankly should have done 30-40 years ago when we first started thinking about multiprocessing. Go was invented by folks like Ken Thompson (who created Unix) and Rob Pike (who created the Plan 9 operating system and co-created UTF-8). Tell me again that there isn't good engineering behind Go. Finally, Go attacks the needs of modern programming from a different paradigm than we have been using for the last 10-20 years. From the first paragraph of Effective Go: > ... thinking about the problem from a Go perspective could produce a successful but quite different program. In other words, to write Go well, it's important to understand its properties and idioms. So of course it's different than a lot of other aged languages. Go tackles newer problems in a newer way. Tell me again that Go is a regression from other programming languages.
- stock_toaster 12y agoAs much as I like Go, in many ways Go is not what I would consider "beautiful" in an esthetic sense. Go does, however, have a very pragmatic feel to it. The creators, in general, seem to take a very measured look at things before adding them, and are very careful to keep the compatibility promise for 1.x. The overall result feels very "engineered" (especially when using the tooling). Go clearly isn't perfect, but yet it feels rather robust for such a young language.
- aheu 12y agoCached version - http://webcache.googleusercontent.com/search?q=cache:gmYvtpFGhzsJ:yager.io/programming/go.html+&cd=1&hl=en&ct=clnk&gl=us http://webcache.googleusercontent.com/search?q=cache:gmYvtpF...
- deleted 12y ago[deleted]
- oscargrouch 12y agoGo, Rust, Haskell, come from diffent ways of thinking about how to solve problems using programming languages.. Go aims to be more simple and concise, in the end you write less code to do the same thing, as you would in C++, Haskell or Rust.. because those 3 languages decided to "cover everything" and are worried about other things, creating more burden to the programmer, but with something else to gain Go is more of a productivity language.. it remind us the we have better things to do in life, and not spend all the time coding, but enjoying that extra time with your family for instance.. Therefore Go is good.. its only MAYBE "not good" for the same thing that Rust, or Haskell are.. Besides.. this is the wrong way to market some technology or idea.. the best way would be "Why Rust or Haskell are Good" instead of envy the success of others.. Its all about tradeoffs.. and i think this article misses the point.. and care only some things that will obviouslly make some languages more fit.. like, if you care more about memory control,type systems and safety.. its obvious that Rust and Haskell will look good and "correct" But this is not all about it.. theres team working, productivity.. its a balance.. and always depends of the problem domains.. some language are more fit than others.. theres no need for bashing
- Dewie 12y ago> Go aims to be more simple and concise, in the end you write less code to do the same thing, as you would in C++, Haskell or Rust.. I sincerely doubt that Go is more concise than Haskell. I won't say whether concise is good or bad, but I very much doubt that Go is the most concise.
- ponce 12y agoGo doesn't allow to create reusable, zero-cost abstractions so I guess it's not more concise than C++ either.
- gipp 12y agoI don't know that much about Rust, but Haskell is among the more concise languages out there, and definitely more so than Go.
- codygman 12y ago
- xxchan 12y agoEvery single thing listed in the article can be added to Go at any point, since it currently has a very minimal feature set. Once something like generics are added, they have to support it until the end of time or risk having an unstable API like Rust did for a while there.
- pcwalton 12y ago> or risk having an unstable API like Rust did for a while there. Every language, including all the languages described in this article, goes through a period of instability while it figures out what works and what doesn't.
- xxchan 12y agoSure, I'd just say that Go has been extremely stable since before 1.0 (~2 years). Author's point was that we should not use "not good" languages for the fear that we might be stuck with them for next 20 years. I'd rather be stuck with a language whose designers are very resistant to change vs one that gets features haphazardly bolted on every few years (PHP comes to mind).
- wyager 12y ago>I'd rather be stuck with a language whose designers are very resistant to change vs one that gets features haphazardly bolted on every few years (PHP comes to mind). I absolutely agree! However, I don't think Rust will continue to go through wild changes for much longer. My guess is that it will settle and become pretty fixed. And Haskell certainly doesn't introduce breaking changes very often.
- pcwalton 12y ago> However, I don't think Rust will continue to go through wild changes for much longer. My guess is that it will settle and become pretty fixed. We're shooting for the end of the year, in fact. You can view the list of backwards incompatible language changes here: https://github.com/rust-lang/rust/issues?labels=P-backcompat-lang&milestone=20&state=open https://github.com/rust-lang/rust/issues?labels=P-backcompat...
- zkirill 12y agoHaskell (with third party library) http://snapframework.com/docs/tutorials/snap-api http://snapframework.com/docs/tutorials/snap-api main :: IO () main = quickHttpServe site site :: Snap () site = ifTop (writeBS "hello world") <|> route [ ("foo", writeBS "bar") , ("echo/:echoparam", echoHandler) ] <|> dir "static" (serveDirectory ".") echoHandler :: Snap () echoHandler = do param <- getParam "echoparam" maybe (writeBS "must specify echo/param in URL") writeBS param ----- Rust (with third party library) https://github.com/chris-morgan/rust-http/blob/master/src/examples/server/hello_world/main.rs https://github.com/chris-morgan/rust-http/blob/master/src/ex... //! A very simple HTTP server which responds with the plain text "Hello, World!" to every request. #![crate_id = "hello_world"] extern crate time; extern crate http; use std::io::net::ip::{SocketAddr, Ipv4Addr}; use std::io::Writer; use http::server::{Config, Server, Request, ResponseWriter}; use http::headers::content_type::MediaType; #[deriving(Clone)] struct HelloWorldServer; impl Server for HelloWorldServer { fn get_config(&self) -> Config { Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 } } } fn handle_request(&self, _r: Request, w: &mut ResponseWriter) { w.headers.date = Some(time::now_utc()); w.headers.content_length = Some(14); w.headers.content_type = Some(MediaType { type_: String::from_str("text"), subtype: String::from_str("plain"), parameters: vec!((String::from_str("charset"), String::from_str("UTF-8"))) }); w.headers.server = Some(String::from_str("Example")); w.write(b"Hello, World!\n").unwrap(); } } fn main() { HelloWorldServer.serve_forever(); } ----- Go (native) package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } ----- Yeah, ok.
- pcwalton 12y agoYour primary criticism of Rust is that one (community-maintained, and not "official") Web package requires setting headers explicitly. OK.
- stock_toaster 12y agoprefix code lines with two spaces to get a pre tag. like this
- andrejewski 12y agoI am completely in support of Haskell and functional languages in general. There are some gaps in Go and definitely some glaring problems. But this comparison also only lists the bad. Go is good for what it was intended for which is concurrent programming and server/web application. Just a note: I don't think it is fair to say Go has absolutely no immutability as it was defined, it does have "const". See http://golang.org/ref/spec#Constant_expressions http://golang.org/ref/spec#Constant_expressions
- Dewie 12y agoYeah, this post seems to be most about general purpose language features, and not so much about stuff that is relevant to the niche Go is trying to carve for itself.
- wyager 12y ago>Go is good for what it was intended for which is concurrent programming and server/web application. I absolutely agree that Go is nice for writing web servers! However, there is no reason that it can't still be nice for that and also a well-designed language in general. For example, Haskell has awesome concurrency features, and writing a web server in Haskell is reasonably nice (not quite as nice as in Go, IMO).
- AndreasFrom 12y ago`const` is for compile-time constants where something like `let` in Rust can be used for values generated on the fly. The latter is immensely more powerful and actually provides the described benefits like guaranteeing that data is not changing under your feet. Edit: While `const PI = 3.1415…` is threadsafe, it's not very useful in comparison to runtime-immutability :)
- andrejewski 12y agoYes, the guarantees provided by true immutability are not met by "const". I wrote the note loosely using the author's expectations and advantages of immutability, not the exact definition. But thank you for letting me clarify. Also I just noticed with Go's Unicode support we can write `const π = 3.14..` if we really wanted.
- tshadwell 12y agoFor fear of disagree downvotes: I would say that many of the qualms brought up in this article are problems that are encountered fighting the language. The problem of 'summing any kind of list' is not a problem that is solved in Go via the proposed kind of parametric polymorphism. Instead, one might define a type, `type Adder Interface{Add(Adder)Adder}`, and then a function to add anything you want is fairly trivial, `func Sum(a ...Adder) Adder`, put anything you want in it, then assert the type of what comes out. When it comes to iteration, there is the generator pattern, in which a channel is returned, and then the thread 'drinks' the channel until it is dry, for example `func (m myType) Walk() chan->myType` can be iterated over via `range v := mt.Walk(){ [...] }`. Non-channel based patterns also exist, tokenisers usually have a Next() which can be used to step into the next token, etc. The Nil pointer is not unsafe as far as I know, from the FAQ: http://golang.org/doc/faq#no_pointer_arithmetic http://golang.org/doc/faq#no_pointer_arithmetic The writer seems to believe that functions on nil pointers crash the program, this is not the case. It's a common pattern in lazy construction to check if the receiving pointer is nil before continuing. Go is not flawless by any means, but it warrants a specific style of simplistic but powerful programming that I personally enjoy.
- wyager 12y ago>The writer seems to believe that functions on nil pointers crash the program, this is not the case. It's a common pattern in lazy construction to check if the receiving pointer is nil before continuing. And what happens when you don't check? It crashes. That's the unsafe part. These crashes are simply not possible in Rust and Haskell, and the type system notifies you if failure is possible (because the function will return an Option/Maybe).
- deleted 12y ago[deleted]
- Dewie 12y agoMaybe "unsafe" is being used to mean different things, here. Some may interpret it as to refer to unsafe memory access. Others may use it to mean possibility of crashing at run time (due to null pointer dereference).
- mseepgood 12y agoSo he wants Haskell. Haskell already exists and has all the features he wants. He should have written his blog in Haskell, but he didn't, and I know why: because a language, which throws all these features together is no longer a practical language. He only sees the benefits of features, not the cost they introduce.
- wyager 12y ago>He should have written his blog in Haskell, but he didn't, and I know why: because a language, which throws all these features together is no longer a practical language. Actually, it's because I like Go's standard library HTTP server implementation! I'm not claiming that Haskell or Rust are magic bullets, or that Go is useless. Far from it!
- thinkpad20 12y agoHindley-Milner inferrence, operators-as-functions, and certain other features, I guess I can see arguments against (although I think they're overstated). However, I don't see any reason why generics, no null pointers, pattern matching, and certain other features would be problematic, let alone not be useful, in a language like Go. I'd be curious as to hear your justification of the claim that "a language, which throws all these features together is no longer a practical language."
- Paradigma11 12y agoI do think that Meijer and Griesemer agree somewhere in this intervew that generics are hard to get right (co and contravariance) and that forgoing generics is a valid design choice: http://channel9.msdn.com/Blogs/Charles/Erik-Meijer-and-Robert-Griesemer-Go http://channel9.msdn.com/Blogs/Charles/Erik-Meijer-and-Rober... It's been a while and might have been another interview tough.
- Shorel 12y agoI think D got generics right.
- 12y ago
- mholt 12y agoThe author is using a sharp blade as his implication for good: features that make a language more complex. If the added complexity is "good" to you, then fine. In modern systems, simplicity is a powerful debugger. Adding all those features that the author talks about -- "Constraint-based Generics and Parametric Polymorphism", "Algebraic Types and Type-safe Failure Modes", and "Pattern Matching and Compound Expressions" -- even if useful, would defeat the purpose of Go.
- autodidakto 12y agoPeople use the word "complex" in different ways. Do you mean number of features? Do you mean the size of the compiler? By some measures, operator overloading adds complexity; By another measure, it add simplicity.
- mholt 12y agoI use complexity here the same way the Go community does: it is whatever its authors and users consider it to be. So chances are, if it slows down compilation, it's complexity. If it adds significantly to the grammar or syntax or keyword list, it's complexity. If it does things that can already be done, just differently, it's complexity. If it makes code less clear, it's probably complexity. (You get the idea.)
- wyager 12y ago>If it does things that can already be done, just differently, it's complexity. Doesn't that make programming languages themselves complexity? After all, you can already do anything in assembly. That seems like a really weak argument. Sometimes having a more "complex" (in your terms) system leads to simplicity. For example, programming languages in general. Programming languages add "complexity" to computers over machine language programming, but the result is that making a program is a much simpler task.
- twic 12y ago> I use complexity here the same way the Go community does To mean anything Go doesn't currently have?
- autodidakto 12y agoPossible error: >If you want to modify a data structure, you have to create an entirely new data structure with the correct changes. This is still pretty fast because Haskell uses lazy evaluation. I believe the issue is persistent data structures -- the new data structure "remembers" the old one (instead of recreating it) and records changes. (Clojure works like this as well) -- and not lazy evaluation.
- wyager 12y agoI meant that, despite the fact that adding an element to a tree in Haskell naively constitutes "making a new tree", Haskell usually doesn't end up actually make a whole new tree (because of lazy evaluation), so trees are still really fast.
- chris_j 12y agoThat's still not quite right. It's not lazy evaluation that makes it feasible to "make a new tree" in Haskell (although it doesn't hurt), it's the fact that the new tree shares most of the state of the old tree and the data structures make the asymptotic time complexity of both update and retrieval very close to (but not quite) O(n). If you haven't looked at persistent data structures yet then I'd definitely recommend doing so because they are fascinating. A few people have written about Clojure's data structures and the following article looks like it gives a good introduction: http://hypirion.com/musings/understanding-persistent-vector-pt-1 http://hypirion.com/musings/understanding-persistent-vector-...
- wyager 12y agoThat's fair. I'll fix the article. Thanks!
- eikenberry 12y agoI agree with almost all points but still think Go is a good language for the long term because it follows in the tradition of worse-is-better design. And while worse-is-better produces systems with a lot of warts, it seems to work better in practice than systems that do it 'right'.
- whocares 12y agoSheesh. A laundry list of issues. So why use Go at all? Quit yer whining and just use Haskell or whatever. Go works for some people, not for others. Why hang around and complain? Move on, use something else.
- wyager 12y ago>So why use Go at all? Quit yer whining and just use Haskell or whatever. [...] Why hang around and complain? Well, I think it's a good idea to get people thinking about programming language design. Sometimes it's really hard to tell what's wrong with something if you don't know about anything better.
- coldtea 12y ago>Go works for some people, not for others. Why hang around and complain? Because if everybody was selfish and self-absorbed enough to do that there wouldn't be any evalutation of languages outside the personal level? The way things move forward is through (1) criticizing stuff, (2) fixing stuff, (3) making new stuff (in that order). And all three steps are necessary.
- mustpax 12y agoThere's something very seductive about languages like Rust or Scala or Haskell or even C++. These languages whisper in our ears "you are brilliant and here's a blank canvas where you can design the most perfect abstraction the world has ever seen." But, for systems programming, abstractions suck. They always, always have a cost. When abstractions break, you not only have to deal with a broken system but the broken abstraction itself too. (Anyone who has ever seen a gcc compiler error for C++ knows how this feels.) Therein lies Go's value proposition. It does not make it possible to make things pretty (ugh, nil). It just makes it impossible (ok, really hard) to overcomplicate things. When you write Go code, you can picture what the C equivalent would look like. You want to deal with errors? Here's an if statement. Data structures? Here's a struct. Generics? Here's another if statement, put it inside your for loop. Obviously, Go is not the right choice of language for most things. When you're doing application development, you may be able to afford the cost of abstractions. But for tools that only need to do one thing and do it extremely well, it's either that or C. And I'm not going back to managing my own memory anytime soon.
- wyager 12y ago>But, for systems programming, abstractions suck. Could you clarify what you mean by "systems programming"? To me, that means working with embedded systems, which Go is certainly not appropriate for.
- EpicEng 12y agoSystems does not necessarily imply embedded. I work in systems and, as far as I am aware, the term simply means software which primarily services the hardware (as opposed to the user). Drivers, HW interfaces, anything which has to make assumptions about the underlying hardware it is running on/servicing.
- mustpax 12y agoBy systems programming I mean writing the code that applications and distributed systems run on top of. Raft (https://github.com/goraft/raft https://github.com/goraft/raft) and groupcache (https://github.com/golang/groupcache https://github.com/golang/groupcache) come to mind as examples. That's a good point though. A lot of people mean different things by systems programming.
- deleted 12y ago[deleted]
- tjholowaychuk 12y agoI also don't get why the for-loop uses a "range" keyword at all, isn't that what typing is for, can't it just figure out that the type is enumerable? I like most of Go so far, but interface{} is possibly the ugliest artifact of a programming language that I've seen, next to pretty much all of c++ Rust and Go should have a baby
- jamesmiller5 12y agoThere is a subtle yet key difference between range and for. Ranges will only start execution on input of known size and guarantee termination. Regular for loops do not require a terminating state.
- burntsushi 12y ago> Ranges will only start execution on input of known size and guarantee termination. `range` can be used to receive values on a channel, which is certainly not a known size and doesn't have guaranteed termination.
- Shorel 12y agoMay be D will interest you.
- jackielii 12y agoI see you wrote "It would be nice"
- vorg 12y agoI've recently tryed out Go for its Unicode integration. What I liked at first sight... * the indexing makes a map[something]boolean act like a set. Sets and maps are so similar it always felt wrong for them to be two separate constructs. * making exported functions/vars/etc begin with a capital letter. When naming important stuff, it's a relief not worrying about naming conflicts with keywords. When naming locals, just use i,j,p,q,p2 anyway. * using defer and recover instead of catch and finally. The catch clause is really two functionalities rolled into one and using defer and recover decomplects them. Other languages should copy those. What I'm concerned about... * printf and regex notation are used so much they're really part of the language, but have an entirely separate syntax embedded within strings which must be learnt. But unlike the rest of Go's syntax, they're unintuitive, especially regexes for Unicode. Unicode is meant to be one of Go's strengths. I understand quick parsing is one of Go's primary reason's for existing, but the regex and printf notations could have been cleaner. When you think about it, why are the arithmetic and bitwise operators generally part of a language's primary syntax, but string matching and formatting delegated to sub-languages? * statements, like if/else and ++/--, don't return values in Go which is hard to get used to. I understand making statements generally be shorter so the code looks good after running through gofmt could have motivated this. Overall, I think Go's a systems language intended for quick parsing and eliminating C++'s complexity, and the author's comparing it to languages with far higher level constructs. The correct solution is for people to implement languages like Haskell and Clojure in Go, making them execute as fast as possible.
- wyager 12y ago>The correct solution is for people to implement languages like Haskell and Clojure in Go, making them execute as fast as possible. Uh, what? Haskell already compiles to native code, and is faster than Go in many cases. Also, if you were implementing a programming language, there are much better languages to do it in than Go.
- stcredzero 12y agoDepends on your particular value of "better." If you're optimizing for programmer time, writing a language in Go is not a bad tactic. You get out of having to write your own GC, you can incorporate a few nice concurrency features with little effort, and you still get pretty good performance. (Admittedly, far from the best performance, though.)
- bayesianhorse 12y agoGo is designed to be a niche language. A very big niche, but essentially still a niche: service components in clouds, where computing efficiency financially trumps development times. Go is more productive than C++, but less so than Python or some other alternatives. Go's tooling, linking and libraries make it useful in the Cloud, less so on mobile or personal computers. And the lack of third party libraries, combined with a relatively slower speed of developing these libraries (again compared to Python, javascript and others) means that Go will have a hard time going beyond cloud services.
- xkarga00 12y ago"Go does not support immutability declarations." Doesn't Go have constants (const) which are immutable? What am i getting wrong here?
- dbaupp 12y agoThose are just compile time constants, you cannot have a value computed at runtime stored in an immutable variable (i.e. one the compiler will complain about if you attempt to mutate it, to assist with program correctness).
- oscargrouch 12y agomaybe he means a immutable var.. assign once, and never changes.. its not the same as the const construction in Go
- eloff 12y agoI just spent the weekend learning Go and writing a single writer multi-reader hashtable for threadsafe access. I picked it deliberately because it's against the philosophy of the language, which is to share by communicating instead of sharing data structures directly. It was painful to write: // Do NOT reorder this, otherwise parallel lookup could find key but see empty value atomic.StoreInt32((*int32)(unsafe.Pointer(uintptr(uint64(slot)+4))), val) atomic.StoreInt32((*int32)(unsafe.Pointer(slot)), key) However, the non volatile, non unsafe parts of the code were an absolute joy. Testing was a joy, compiling was a joy, and benchmarking was a joy. I was impressed that it allowed me to bypass the type system completely and do nasty, nasty things in the pursuit of performance. I want a language that lets me do nasty things where I must, but that makes the other 95% of the program, and the job of compiling, testing, and maintaining that program easy. Go excels here. Rust, C++, Haskell, Scala will never be good at that because they're too damn complicated (although each of them make the nasty parts a little less painful!) The end result of my weekend's hacking? On an i7-4770K @ 3.5ghz BenchmarkGoMapInsert-4 20000000 110 ns/op BenchmarkHashIndexInsert-4 100000000 25.6 ns/op BenchmarkGoMapLookup-4 50000000 78.5 ns/op BenchmarkHashIndexLookup-4 100000000 17.7 ns/op About 4x faster than Go's builtin map, for int32 key/value on both insert and lookup. And it allows any number of reader threads concurrent access with a writer without any synchronization or blocking, unlike Go maps. It doesn't allow zero keys, unlike go maps, and it doesn't allow deletes. Hardly apples to apples, but the performance of pure Go code is impressive nonetheless. 200 LOC, not counting tests.
- stcredzero 12y agoit allows any number of reader threads concurrent access without any synchronization or blocking, unlike Go maps. You mean readers concurrent with a writer? AFAIK, any number of reader threads can get values out of a Go map when it isn't being written to.
- eloff 12y agoYes, concurrent with a writer. If there is more than one writer, the writers must use a mutex, but the single writer and readers don't block each other. I updated the text to make it clear.
- plainOldText 12y agoReading this article and the HN comments made me realize, how people want to use the same language for everything. Unfortunately, this is not possible, since each language was design with certain use cases in mind. I too, am guilty of wanting a language to do everything, to be fast, memory efficient and also easy to program in. Perhaps our ultimate quest in terms of designing languages is to design one smart enough that can be used to program toasters and clusters alike. Until then, we might as well use the right tool for the job.
- jamesaguilar 12y ago> to be fast, memory efficient and also easy to program in. I think the issue Go detractors have is that it is none of those things, nor is there any pair of those things for which there is no better alternative than Go. If you want fast and memory efficient, you could pick C++ or C. If you want something a little easier to program in, you could pick C#, which dominates Go in all three categories. If you want to go easier to program in, there are plenty of languages like Python that are more powerful than Go.
- deleted 12y ago[deleted]
- lmm 12y agoI'd make the case for Scala for almost anything (nothing so low-level that you need to avoid GC, and I guess not command-line utilities (JVM startup time), but other than that). Haskell or OCaml could probably make a case for being suitable for just about anything. There are big advantages to using a single language in terms of code reuse, deployment tooling and so on.
- platz 12y agoFor robots, Haskell is not used directly, but can be used as a DSL to generate the appropriate C code. Here's one example: http://smaccmpilot.org/languages/index.html http://smaccmpilot.org/languages/index.html
- wyager 12y agoTrue! Embedded programming DSLs are a very cool area of research. I figured they might be a bit beyond the scope of the article.
- otikik 12y agoOne man's "must haves" are other man's "cruft".
- briantakita 12y agoThis article presumes that everybody wants an elaborate type system. I'm not sure that is the case. I still see an elaborate type system as incidental complexity. I may be in the minority and I may not have worked in domains which benefit from such modeling. Maybe I'm stuck in a blub paradigm. Here's my reasoning. I'm a fan of human language & domain ontologies. Word definitions are quite flexible & do not have an elaborate type system. I don't feel the need to have a provably correct logical system to have a useful conceptual tool (i.e. analogies). I enjoy ambiguity. Ambiguity can lead to paradoxes, which in turn leads to exploration & novelty. Strongly typed systems, by default, give me the impression that the domain ontology is figured out on a highly precise level. That is never the case. You can almost always go deeper. Domain language precision is tough to model & express. I prefer data structures to drive operations. I suppose that a schema is often useful, however I don't feel like I need the programming language to enforce the schema. I also like to evolve the design, using tests. Tests are really examples to exercise the program's API with expected I/O. People often equate an evolved programming language/paradigm as being better. In the case of Javascript, they point out that is was created in a few days as evidence that it's "bad". The thing about an evolved language/paradigm is it has evolved down a certain path. That often means restricting the freedom of the programmer to evolve the program down another path. I'm not picking one way to be better than another. However, I do see tradoffs to both approaches. I personally prefer a more flexible language. It can be evolved, as long as the evolution does not restrict my freedom to evolve the program.
- djur 12y agoThis is a good argument in favor of dynamic typing, but Go is not dynamically typed. It has a static type system that its critics consider insufficiently powerful.
- Perceptes 12y agoAmbiguity is not something that's generally, if ever, desirable in a program, so if a simpler type system has that to offer, I'm not sure it's a benefit. You could also argue that a more elaborate type system allows you to be more expressive in the design of your programs, rather than restricting you.
- 12y ago
- dcposch 12y ago> A Good Solution: Constraint Based Generics and Parametric Polymorphism > A Good Solution: Operators are Functions > A Good Solution: Algebraic Types and Type-safe Failure > A Good Solution: Pattern Matching and Compound Expressions People have tried this approach. See languages like C++ and Scala, with hundreds of features and language specification that run into the thousands of pages. For an unintentional parody of this way of thinking, see Martin Odersky's "Scala levels": http://www.scala-lang.org/old/node/8610 http://www.scala-lang.org/old/node/8610 For additional hilarity, note that it is an undecidable problem whether a given C++ program will compile or not. http://stackoverflow.com/questions/189172/c-templates-turing-complete http://stackoverflow.com/questions/189172/c-templates-turing... -- Go was created by the forefathers of C and Unix. They left out all of those features on purpose. Not unlike the original C or the original Unix, Go is "as simple as possible, but no simpler". Go's feature set is not merely a subset of other langages. It also has canonical solutions to important practical problems that most other languages leave do not solve out of the box: * Testing * Documentation * Sharing code and specifying dependencies * Formatting * Cross compiling Go's feature set is small but carefully chosen. I've found it to be productive and a joy to work with.
- seanmcdirmid 12y agoI get what you are saying, but why convolute C++ and Scala? One is a horribly designed complex language with macro-like templates rather than modular parametric polymorphism. The other is much more well designed but, as you say, still complicated. You could have stayed at Scala without degrading into a comparison with C++, which is a universally kicked dog anyways. It is possible to do type parameters in a way that is simple yet effective. But I can understand why it wasn't done this early in Go's lifetime, especially since Rob Pike isn't exactly well into generics (vs. Odersky's experience with Java/Pizza).
- wyager 12y ago>See languages like C++ and Scala Of the 4 you mentioned (Constraint based generics and parametric polymorphism, operators as functions, algebraic types and type-safe failures, and pattern matching/compound expression) C++ really only has 1 (operators as functions). >with hundreds of features and language specification that run into the thousands of pages. This describes neither Rust nor Haskell. >Go is "as simple as possible, but no simpler". It has mandatory heap usage, garbage collection, green threads. It's more than generous to call that "as simple as possible". Of the 5 features you mention that Go has "canonical solutions" to (in the form of external tools), I know off the top of my head that Haskell's Cabal takes care of at least 4 of them. I'm not sure about formatting. Rust probably has similar tools, or if it doesn't, they can certainly be added without changing the language.
- personZ 12y agoWe've seen this same article re-written countless ways. Seriously, this is (intentionally or not) a rewording of every existing criticism of Go, by people who complain that it isn't a language that it isn't. No, Go's solution to generics is not interface{}. The moment you say that, you have lost. You are trying to fight Go and make it a language that it is not. Always remarkable that such critiques always focus on the utterly trivial, while absolutely ignoring things like concurrency or composing complex systems. As always, the color of the shed is what the laymen want to argue about.
- jeremyjh 12y agoSince concurrency and composition are important, why doesn't Go have support for immutable variables and monitoring/linking ? These are features proven to make it easier to reason about concurrent systems and to manage failures in a distributed system. From what I can tell it is completely impossible to implement supervisors in Go.
- Laremere 12y agoImmutable values will complicate a type system and implementation. The Go creators are very strict about adding features to the language without enough justification, which is one of the biggest features of the language imo. There are more synchronization features than channels in Go. Channels and switches solve most problems very well. However when another synchronization method is just simply required, check out: http://golang.org/pkg/sync/ http://golang.org/pkg/sync/
- Peaker 12y agoRefusing to complicate the language is nice, unless it means complicating or making every program in that language less safe. Repeatedly, Go chooses the latter, and many people hail it while writing programs that crash on nil dereferences or duplicate their code for various basic types.
- jeremyjh 12y agoIt is fine to say you want a simple language, but then please do not talk up how great it is at concurrency. It lacks basic features common to every other language with a good concurrency story.
- ludamad 12y agoAs a love-hater of C++, Go did indeed feel like nothing new under the sun.
- wtbob 12y agoRegarding generic data structures, the author should consult the sort package, which has typed generics; much the same approach can be used for generic data structures. More complex type inference requires a more complex (and hence buggier) compiler. Finally, the author should investigate the unsafe package; I believe the following code will do what he wants: *(*byte)(unsafe.Pointer(uintptr(0x1234))) = 0xFF Verbose? Sure.
- ChikkaChiChi 12y agoPosting articles about how Go sucks because it lacks generics and operator overloading has become the "I'm going to be different and grow a moustache" of the programming set. Go is a tool in your kit like any other language. You can't blame the architects for not providing an end all be all solution for every person's needs 100% of the time.
- jvermillard 12y agoI'm reading that while doing my daily Java code and I stumble on this error : Bound mismatch: The generic method immutableEnumSet(Iterable<E>) of type Sets is not applicable for the arguments (Integer). The inferred type Integer is not a valid substitute for the bounded parameter <E extends Enum<E>> Sorry for advanced type systems but I really want to go back hacking Go code :)
- steveklabnik 12y agoYou have an Integer where it expects a Set.
- TheCoelacanth 12y agoJava's type system is hardly advanced; in fact it's quite primitive.
- KMag 12y agoWho holds Java up as a poster child for advanced type systems? You've mad an unintentional straw man argument. In this particular case, you're using an Integer where a subclass of Enum is called for. The value you're passing may very well be a valid value for the Enum you're trying to use. You may be doing something silly, or it's possible that this is an artifact of generics being bolted on to Java after the fact. In this case, it may be possible for the compiler to infer which Enum you really wanted and insert a runtime check and cast, but then it would be doing you a disservice by silently inserting an opportunity for a runtime error. I'm not advocating Java's type system, but be glad Java at least has typesafe enums. Every couple of years (across several employers) I run into a very bad bug due to two different return code enums happening to use either 0 or 1 as their "ok" values, and enums of one type being silently cast to the other, resulting in silently okay behavior in the common case and spectacularly bad error recovery in corner cases. Just today I fixed an error where someone had designed an API where an enum of one type was passed to a function needing an enum of a different type, without any translation. Some users had gotten correct behavior by passing an enum of the incorrect type to the API, and some users had followed the API documentation and gotten wrong behavior.
- exabrial 12y ago"A Good Solution: Operators are Functions" NO. No. No. Allowing users to change the language specification and side effects on a per-file, per-project, per-anything basis is a terrible terrible terrible idea. "This is all covered in Knuth, and we don't have time to go over it again."
- Dewie 12y ago"users to change the language specification" ? How does that make sense?
- sparkie 12y agoPerhaps you've not used Haskell? There are no "built in" operators in Haskell, other than " ", which is function application, and which cannot be overridden. Additionally, any "infix operator" can be used in prefix form, by surrounding it in parens - and any function name can be used in infix form, by surrounding it in `backticks`. All other operators, like +, -, $, <, <$>, >>=, are defined in libraries (specifically in Prelude, the "standard library") - these operators cannot be overloaded in ad-hoc manner as operator overloading is done in other languages (bar qualified module imports) - to make use of one of these operators you must implement an instance of the class which contains it, such as Num for +, -. There's also the requirement to implement fromInteger, signum, negate, etc in Num. (If you can't think of a valid "fromInteger" implementation for your custom type, it's obviously not a Num). Also, some classes have associated laws which should prevent you from using them incorrectly Admittedly the class/instance scenario could be improved with further checking of these "laws", but that would basically require a full theorem prover baked into the language - something that Haskell will probably get sooner or later. There's still what I would consider "operator abuse" in Haskell - it's not that of overloading existing operators, but that of introducing new operator aliases for virtually every function in your library, as http://hackage.haskell.org/package/lens-4.1.2/docs/Control-Lens-Operators.html http://hackage.haskell.org/package/lens-4.1.2/docs/Control-L... does (yuck). A nice convenient feature of Haskell is that you can scrap the official Prelude library (-XNoImplicitPrelude) and roll your own, as some others have done (e.g, http://hackage.haskell.org/package/classy-prelude http://hackage.haskell.org/package/classy-prelude). This allows you to effectively "clean up" some of the warts from the early design of the language, so it can continually improve - rather than needing to invent a whole new language when we decide it's not what we want. Num is an example of a class which gets lots of stick, because we'd often like to implement either of addition or mulitplication, but not both.
- koffiezet 12y agoTo be honest, I feel a lot of people are missing the point of Go, and I think none of the points made are important. The single most important thing about Go is it's simplicity: For me it is a language that feels like a hybrid between a scripting language and a 'real' programming language. Simple syntax with some powerful, easy to use features, impressive library support for being only a few years old, but compiles (static) to native code. That fills a gap that Haskell and Rust don't, These more advanced languages sacrifice simplicity for an attempt to be perfect. Go makes the clear statement of being simple above everything else. Give an average python/ruby/<insert scripting language here> coder the link to "A 30-minute Introduction to Rust" ( http://doc.rust-lang.org/intro.html http://doc.rust-lang.org/intro.html ), and he/she will give you a strange look and not understand half of what is being said there. In the end they'll conclude it's not something for them. Give it to a C++ coder and he'll say 'oh nice, but I can do that in C++, use Boost<whatever>, because C++ is superior to all!' - and that coder there is their target audience. A decent C++ coder will have invested too much time to learn another language to solve problems he already learned to solve for himself in C++ a long time ago. Rust might be better and would make his life easier in a lot of cases, but still the majority won't make the switch. Give the same <insert scripting language here> coder the Go documentation, and he'll be off in no time, writing better code than he used to do, producing a single binary which will not be an absolute nightmare to deploy. And that's what every coder of scripting languages has always dreamed of - being able to make programs in a simple straight-forward way, with as little dependencies as possible, without needing a <language X> runtime. On top of that, Go makes cross-compilation dead-easy. There are a LOT more <insert scripting language here> coders out-there than there are C++ programmers. Giving them Go makes running the stuff they write more efficient confronts them with Git/source control (you would be surprised how many don't know about SCM)
- swah 12y agoI agree with you partially, but OTOH Go, I don't know exactly why, feels pragmatic and ready for production. Maybe its because of the creators, Google backing it, or the promise that 1.x remains compatible, or that it ships with a standard library good enough to write useful server stuff. So despite all those flaws (I miss generics the most), I think it will become the static Python replacement for the next 10 years. (Its like how Factor handled 3rd party contributions: one library for some particular task is blessed and shipped w/ Factor. Of course it doesn't scale..)
- lein 12y agokudos, i totally agree with your arguments.
- kazuho 12y agoType inference and operator overloading often leads to less-readable code. IMO when evaluating programming languages, we should not only consider writability but also its readability. This is especially true if many engineers are going to be involved in the development. It is good to have type inference and operator overloading in terms of writability. Nobody wants to type verbose code. OTOH some verbosity within the source code helps reading the code. And type information (which type inference and operator overloading tries to hide) is one of them. So I can respect Go's decision not to support operator overloading / only support some part of type inference.