http://commandcenter.blogspot.co.il/2012/06/less-is-exponentially-more.html http://lambda-the-ultimate.org/node/4554 http://news.ycombinator.com/item?id=4158865
http://blog.golang.org/2010/07/gos-declaration-syntax.html
https://plus.google.com/116810148281701144465/posts/iqAiKAwP6Ce why Go uses errors instead of exceptions
https://plus.google.com/116810148281701144465/posts/iqAiKAwP6Ce why Go uses errors instead of exceptions
" In Go, the established convention is that functions return errors; they don't panic. If a file isn't found, os.Open returns an error; it doesn't panic. If you write to a broken network connection, the net.Conn's Write method returns an error; it doesn't panic. These conditions are expected in those kinds of programs. The operation is likely to fail, and you knew that going in, because the API designer made it clear by including an error result.
On the other hand, there are some operations that are incredibly unlikely to fail, and the context is such that there is no way to signal the failure, no way to proceed. These are what panic is for. The canonical example is that if a program evaluates x[j] but j is out of range, the code panics. An unexpected panic like this is a serious bug in the program and by default kills it. Unfortunately, this makes it difficult to write robust, defensive servers that can, for example, cope with the occasional buggy HTTP request handler while keeping the rest of the server up and running. To address that, we introduced recover, which allows a goroutine to recover from a panic some number of call frames below. However, the cost of a panic is the loss of at least one call frame from the stack. We did this intentionally. To quote from the original mail: "This proposal differs from the usual model of exceptions as a control structure, but that is a deliberate decision. We don't want to encourage the conflation of errors and exceptions that occur in languages such as Java."
The post I mentioned at the start asks "why is an array out of bounds any more cause for panic than a bad format string or a broken connection?" The answer is that there is no in-band way to report the error during the evaluation of x[j], while there is an in-band way to report an error in a bad format string or a broken connection. (The format string decision is interesting by itself but orthogonal to this discussion.) "
" The error returns used by Go are admittedly inconvenient to callers, but they also make the possibility of the error explicit both in the program and in the type system. While simple programs might want to just print an error and exit in all cases, it is common for more sophisticated programs to react differently depending on where the error came from, in which case the try + catch approach is actually more verbose than explicit error results. It is true that your 10-line Python program is probably more verbose in Go. Go's primary target, however, is not 10-line programs. "
" I frequently think back to a friend's comment on the Go compiler written by Ken Thompson: it's fast because it just doesn't do much, the code is very straightforward." -- http://neugierig.org/software/blog/2011/04/complexity.html
http://www.syntax-k.de/projekte/go-review
http://scienceblogs.com/goodmath/2009/11/11/googles-new-language-go/
http://www.acooke.org/cute/GoRocksHow0.html <-- good, read this one
http://blog.jgc.org/2012/07/things-i-like-about-programming-in-go.html
http://www.acooke.org/cute/GoRocksHow0.html
http://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html
http://news.ycombinator.com/item?id=4158865
http://lambda-the-ultimate.org/node/4629
http://www.syntax-k.de/projekte/go-review
http://blog.golang.org/2010/07/gos-declaration-syntax.html
http://scienceblogs.com/goodmath/2009/11/11/googles-new-language-go/
http://grenouille-bouillie.blogspot.com/2010/03/why-go-isnt-my-favourite-programming.html
http://monoc.mo.funpic.de/go-rant/
http://cowlark.com/2009-11-15-go/ go vs Brand X toread http://news.ycombinator.com/item?id=943554
http://news.ycombinator.com/item?id=1912728
" You probably heard about Go the Google sponsored, Rob Pike powered successor to C. I certainly like Go’s philosophy especially the fact that Go wants to combine the ease of use and fun of dynamically typed, interpreted languages with the correctnes and speed of statically typed, compiled languages. Also, Go aims for minimalism. In contrast to other languages Go has very few keywords4.
I also like the fact that concurrency is built into the language in the form of CSP. In that regard Go is armed for the future just like Clojure. Go’s novel, “tolerant” type system with it’s ad-hoc interfaces seems to by very convenient, too.
However I really must say that Go’s syntax is somehow ugly. I don’t know why but it seems hard to read. Maybe it is because I haven’t programmed in Go and if I started I would accustom to it. But the first impression is not good.
Then there are some questionable design decisions like no generics, defining the visibility of a variable/function by writing the first character in lowercase or uppercase, no enums5 and no exceptions6. " -- http://eugenkiss.com/blog/2010/the-next-big-language/
"
Seriously, how the heck is
var p *[]int = new([]int) // allocates slice structure; *p == nil; rarely useful
var v []int = make([]int, 100) // the slice v now refers to a new array of 100 ints
.. a better solution to “improving upon” C++ with a new language than, oh I don’t know ..
int[] p = null; // declares an array variable; p is null; rarely useful
var v = new int[100]; // the variable v now refers to a new array of 100 ints
..? I’m sure I’m missing something here, particularly since I don’t understand what a “slice” is, but I suspect I shouldn’t care. Oh, nevermind, I see now that it “is a three-item descriptor containing a pointer to the data (inside an array), the length, and the capacity; until those items are initialized, the slice is nil.” Great. More pointer gobbligook. C# offers richly defined System.Array and all this stuff is transparent to the coder who really doesn’t need to know that there are pointers, somewhere, associated with the reference to your array, isn’t that the way it all should be? Is it really necessary to have a completely different semantic (new() vs. make())? Ohh yeah. The frickin pointer vs. the reference. "" I see Go has a fmt.Printf(), plus a fmt.Fprintf(), plus a fmt.Sprintf(), plus Print() plus Println(). I’m beginning to wonder if function overloading is missing in Go. I think it is; http://golang.org/search?q=overloading "
" Go can't grab and schedule C routines properly" (is this true?!? seems unlikely)
---
" I'm pretty sure that go's compile speed is significantly faster than java. It's hard to compare though because java compilation is not the same thing. There is the bytecode in the class files and on the fly compilation in the vm. As well as some stuff that happens when the bytecode is loaded and run.
A lot of go's compile speed comes from how simple it's syntax is besides the gains it gets from avoiding C++ dependency issues. Java's syntax while less complex than C++ is still complex compared to go's. And it won't have go's parse time savings. "
"
> Why did go "win" over erlang, scala, and clojure?
Erlang sucks at string handling which is a no-go in Web developing.
Scala, Clojure, people don't even bother to setup JVM. Python is popular in some degree because it's installed by default on Linux and OS X. "
---
http://stackoverflow.com/questions/9339560/erlang-versus-go-versus-rust-comparison
---
etfb 9 hours ago
| link |
I grew up with Pascal and its derivatives, so I have a strong sense of the aesthetic of programming languages. I can't take Go seriously, or bring myself to use it, because it appears to have no aesthetic sense at all. It's ugly! Strings of keywords and punctuation, no rhythm to it, just a lot of mess. Like a cross between C and Prolog, perhaps, with a smattering of Python but only the ugly bits. I really don't like it.
Now, if you want to see a recent language with a bit of style to it -- and bear in mind I know nothing of how it is to use in practice, so I'm basing my opinions entirely on the look of it -- I think Rust is one of the best of the pack. So much smoother.
TL;DR (for any Redditors who may have stumbled in on their way to the Ron Paul fansite): languages have a flavour, and Go's flavour is "mess".
reply
lobster_johnson 5 hours ago
| link |
Sure, Go is ugly. I had the same reaction as you. But it's so damn functional. There are plenty of warts, syntax and design-wise, but once you get over them, it's actually a decent language.
Compared to Erlang, for example, it's positively beautiful. I like Erlang's execution model, but the unnecessarily gnarly syntax and the antique approaches to some things (no real strings, no Unicode, tuples that depend on positional values instead of named attributes, horrible stack traces, tail-call recursion as a looping construct, etc.) has made me stay away.
Go is a decent alternative to both C/C++ and Ruby for me these days. There are plenty of things I don't like about Go, but it's easy to forgive many of them when the language makes you so productive (at least for the things I need it for; it's pretty bad at web app development and completely useless for GUI development), so I do. Sometimes you just want something that works, with minimal amounts of pain. C++ works, but is always painful to me because it feels like the language is working against me, not with me.
I love the simple syntax in Go; the no-nonsense approach to object-orientation, the way the typing system allows adding methods to arbitrary types, which may have been inspired by Haskell's typeclasses. I love having native Unicode strings, first-class functions, a simple package system, built-in concurrency and decent networking in the standard libs. I love the built-in documentation generator (although it's too simplistic at this point; why not Markdown?).
Things I don't like:
Right now, Go is, in my opinion, mostly an inelegant, weirdly-shaped thing that fits into the weird hole not filled by C and C++, a stepping stone to the next big language. I don't love the language, but I love how I can do the same things I was planning to use C++ or Ruby for; as a C++ replacement I gain productivity and simplicity; as a Ruby replacement I gain performance.
Go is, if anything, a very pragmatic compromise that favours simplicity over complexity at the expense of structural and syntactical elegance. It looks a lot like Java around 1.3-1.4, before the enterprise stuff derailed its focus. My concern is that Go has no particular philosophy as a foundation; it bakes in some current concerns (concurrency, networking, ease of use) and made itself a very useful hammer for hammering today's nails, but may not be as easy to extend to work with tomorrow's screws.
PS. I, too, come from Pascal — specifically, Borland's Object Pascal. While I have fond memories of that language, I'm not sure elegance was one of its main traits.
reply
grey-area 2 hours ago
| link |
Nice list of frustrations with Go, though I wouldn't call it inelegant - the syntax may be homely, but the simplicity gives it a certain minimalist elegance.
Re nils, yes this still feels pretty ad-hoc, I wonder if they'd do anything differently there now if they could? Probably there is no easy way out now they're past 1.0.
It would be nice to see an extensible range and I've had this thought myself (as have others), there has been some discussion on the list, and they're not sure: https://groups.google.com/forum/?fromgroups=#!topic/golang-n...
but then you can also turn it around and iterate by passing in a function to the structure to iterate:
func (self *DataStructure) Iterate(fun IteratorFunc)
Re GOPATH, what do you mean here?
Re packages having one level - I actually love this - if you want to nest things in folders, Go is trying to tell you to split it into sub-packages (in that opinionated manner it sometimes adopts). Of course this might feel restrictive, but if a package has lots of files I'd rather it was split up and organised into packages with clear boundaries between them rather than into an interconnected set of files/folders which only makes sense to the author of the code because it's all in one package with no boundaries. This restriction means we will see apps composed of packages by default rather than all in one namespace because it's easier.
Re the versioning, they originally resisted versioning the language, but eventually gave up on that idea and used versions, so I suspect for packages they'll eventually recognise the need for this when the ecosystem of packages grows sufficiently. Versions do introduce problems of their own (dependency hell), but IMHO being able to reliably import snapshots of a package (tag, branch or version) will be essential long term without having to fork a repo and rename it just to do so. If go becomes popular you can expect this to be addressed by third parties if the go team doesn't bother.
Re the tagging, in a way I'm pleased that they avoid adding lots of features like this, as this is the stort of thing I hate even in the limited version they have (on struct fields) - it's untidy and gets misused and overridden to try to extend the language (see sql libraries in Go tagging fields with all sorts of their own meta-data).
Re commas on lists, this bothers me less than having to put semicolon & LF on every line, I think it's a fair trade.
Re philosophy, I can't speak for the Go authors, but I've found radical simplicity to be its overriding principle, which explains some of the limitations which annoy you above and the ditching of a lot of OO baggage which languages nowadays are expected to carry whether they want it or not. I've found the simplicity worth the trade for some small frustrations.
reply
... > Re GOPATH, what do you mean here?
I mean that the "go" suite of build tools (build, get, install) rely on a specific convention: Your GOPATH is supposed to point to folders each containing bin, pkg and src subfolders with all packages.
Let's say I am developing a package A that uses my own package B. Both on Github. You're supposed to then create: $GOPATH/src/A (which contains A's files as immediate children) and $GOPATH/src/B (ditto for B).
The manuals I believe suggest that you have something ~/projects/go, under which you create bin/src/pkg and put your work. But I don't organize my home folder like that and I find it presumptuous that the tools assume that I do, so I have ~/.go, which contains bin/src/pkg, and I symlink stuff into ~/.go/src. Acceptable if annoying.
> Re packages having one level - I actually love this
I want to use folders as an organizing unit, the way they are intended. It makes sense even for small packages.
Generic example (I have something very similar to this, but I don't want to go into details): I have a framework. There is a bunch of core interfaces, and then a bunch of implementations. Let's say that my interfaces are called Queue (with concrete implementations FooQueue?, BarQueue?, BazQueue? etc.), Block (again, a bunch of concrete impls) and Stream (same). For my brain not go insane every time I look at my source tree, I want to have the core interfaces in the root, and then subfolders queues/, blocks/, streams/.
That's not much to ask. Putting these things in separate packages with dependencies on the original package makes no sense, in particular because the original package has internal dependencies. For example, the framework has a configuration builder that connects queues, blocks and streams, and it knows certain things about the implementations and how they interconnect. Putting that into yet another package is just insanity.
It's one package. And it needs subfolders. (Especially with how Go mandates that tests be in the same folder as the unit being tested!)
I have encountered lots of C projects that pile all the files into a single root folder, instead of having a src/ folder with appropiate subfolders by category. I think that's what the Go guys are mimicking. I hate it.
I mean, just the fact that a package needs the Go files to be in the root is pretty bad. I may have a docs/ there, a readme file, an examples/ folder, a locales/ folder -- why must the source files go in the root? They're not that special. I know you can import directly from a src, but the convention is 'import "github.com/foo/bar"', not "github.com/foo/bar/src"'.
pjmlp 2 hours ago
| link |
I also am a Pascal refugee, having started using it with Turbo Pascal 3.0, and most of the versions until Turbo Pascal for Windows 1.5 and a few toy projects with Delphi.
What attracted me to Go initially, was Oberon's influence in the language, like the packages, method signatures, Pascal declaration way and low level tricks exposed via the unsafe package.
But like yourself after a while using the language, before the 1.0 release, I came to the conclusion that I am better served with more expressive languages.
So nowadays I play around with C++11, Rust and D.
" But you can criticize its aesthetic nevertheless? Maybe if you could bring yourself to use it you might appreciate the elegance of the Communicating Sequential Processes implementation. Or maybe the clean OOP practices derived from using interfaces. Or the beauty of coroutines mapped unto multiple OS threads. "
davidw 11 hours ago
| link |
I'm interested in tracking Go as a replacement for Erlang. Some things that should probably happen:
I think they'll get there eventually. Maybe not 100%, but 'good enough' sooner or later.
reply
jerf 7 hours ago
| link |
Right now, as near as I can tell, you basically can't implement an Erlang supervision tree in Go. You don't have anything like linking, which really has to be guaranteed by the runtime to work properly at scale, so bodging something together with some 'defer' really doesn't cut it. You also can't talk about "a goroutine", because you can't get a reference or a handle to one (no such thing), you can only get channels, but they aren't guaranteed to map in any particular way to goroutines.
I've done Erlang for years and Go for weeks, so I'm trying to withhold judgement, but I still feel like Erlang got it more right here; it's way easier to restrict yourself to a subset of Erlang that looks like a channel if that is desirable for some reason than to implement process features with channels in Go.
reply
JulianMorrison? 8 hours ago
| link |
That issue is quite simply a misinterpretation of goroutines.
Erlang: perform a maximum number of reductions, then switch, or switch on IO. The number of reductions is cleverly adjusted so that a process which is swamping other processes will be throttled.
Go: switch on IO.
Go's design is much simpler, and closer to Ruby Fibers than to Erlang processes, except that goroutine scheduling can use multiple threads. To cooperatively switch without doing IO, call runtime.Gosched().
reply
trailfox 10 hours ago
| link |
Akka is also a viable Erlang alternative.
reply
waffle_ss 6 hours ago
| link |
Looks like a nice library but I don't think it's a serious contender to replace Erlang because the JVM just isn't made for the level of concurrency that Erlang's VM is. Off the top of my head as an Erlang newbie:
[1]: http://doc.akka.io/docs/akka/snapshot/general/jmm.html
reply
---
GhotiFish? 6 hours ago
| link |
Whenever I look through golangs specs, I always get stuck on the same question.
Why are the methods we define restricted to the types we define? I'm SURE there is a good reason.
Others have said that it's because if you did allow that kind of thing to happen, you might get naming collisions in packages. I don't buy this argument, you could get naming collisions anyway from packages, Go resolves those issues by aliasing. Go also allows for polymorphic behavior by packaging the actual type of the method caller with its actual value, so resolving which method to use isn't any more complicated.
I don't get it, I'm sure there's a good reason! I just hope it's a good enough reason to throw out the kind of freedom that would allow you.
reply
Jabbles 6 hours ago
| link |
You can't add methods to a type in a different package as you might break that package. By locking the method set of types when a package is compiled you provide some guarantee of what it does, and it doesn't need to get recompiled again! This is central to Go's ideals of compiling fast.
Besides, embedding a type is very easy http://golang.org/ref/spec#Struct_types
reply
GhotiFish? 6 hours ago
| link |
Hmmm. I can see how adding methods to a type in a different package would require that package to be recompiled, but I don't see how I could break that package. Unless there's some reflection magic I'm not considering.
I'm reading through the embedded types now. I am new to golang so this one is lost on me. I thought if you wanted your own methods on a type from another package, you just aliased it with your own type def.
though it looks like there's some kinda prototyping behavior being described here?
If S contains an anonymous field T, the method sets of S and *S both include
promoted methods with receiver T. The method set of *S also includes promoted
methods with receiver *T.
If S contains an anonymous field *T, the method sets of S and *S both include
promoted methods with receiver T or *T.reply
Jabbles 5 hours ago
| link |
For example, if you do a runtime type assertion to see if a variable satisfies an interface:
v, ok := x.(T)
http://golang.org/ref/spec#Type_assertions
If you "monkey-patch" x to satisfy T in another package, the value of ok may change.
reply
GhotiFish? 5 hours ago
| link |
Hmm I can kind of see what you mean, but I don't see it as a big of a problem.
If you make package A depend on package B, package B monkey-patches x with method Foo so now x is a Fooer
x now satisfies the Fooer interface in package A, well that seems ok. You imported B after all. In things that don't import B, x doesn't satisfy Fooer. Is this unexpected behavior? If B depends on C, C's x won't satisfy Fooer right?
reply
enneff 4 hours ago
| link |
It's because Go was designed for large code bases, and doing what you describe leads to unmaintainable code.
You might be interested in this document: http://talks.golang.org/2012/splash.article
reply
pcwalton 5 hours ago
| link |
Because if you had package A that defined type T, package B that defined method Foo on T and, separately, package C that defined method Foo on T, then B and C could not be linked together.
reply
GhotiFish? 5 hours ago
| link |
I don't see why, personally, B defines Foo on T, so whenever B uses Foo, it should use B's Foo. C defines Foo on T, so whenever C uses Foo, it should use C's Foo. why is it ambiguous for the compiler which one to use?
reply
pcwalton 5 hours ago
| link |
If package D linked against B and C and called Foo(), which Foo() would it call?
reply
GhotiFish?