“I feel like writing about the Go programming language (or ‘Golang’) today, so instead today’s topic is computer stuff. For the record, the language I’ve programmed the most in has been Python, so that’s the perspective I’m analyzing it from.” Some good and bad things about Go.
I like most of the things I’ve seen with Go so far… Seems like it’s closer to C or C++ done right with the benefit of hindsight rather than a replacement for scripting languages.
I’d love to see a first rate UI toolkit for Go, it really seems like a good use for it instead of building a monster from C or C++ and _insert_toolkit_here_.
Unfortunately in my day to day job, Java is a better fit (server-side web stuff), but using Go for a REST layer is probably a near future project for me.
Go was designed to displace Java in server-side web apps. The Go standard library includes a concurrent HTTP server, and Google App Engine provides a complete web framework in Go. REST layers are almost trivial and a few are already available on GitHub and Google Code.
I’d love Go bindings for Qt (imagine signals and slots mapped to channels in Go), but I’m told that it would be prohibitively difficult to implement
https://github.com/visualfc/go-ui is a start.
You cannot easily replicate exact Qt C++ experience (like Python did), but you can create a nice wrapper anyway.
Which you can already do in C++ and Java, etc. In C++, there’s nothing to stop you declaring everything in a class public – which is what a struct is in C++.
The merits of why this is better can be debated, but just because he learnt it one way and never considered the alternative until he came across Go is a poor excuse.
Java does this already.
I quite like LLVM’s IR for integers. i8, i16, i32 etc.
John McCarthy used lists, but the implementation need not be linked lists. Most LISPs these days don’t claim “list only”. Even with the traditional LISP list structure, you’re not actually limited to linked lists. The ability to create trees with cons cells was realized early.
I really wish I could like Go, specially given the Oberon influence the language has, but they just left too much out:
– exceptions
panic/recover feels like a hack
– enumerations
Possible using typed consts with iota, but it feels bad when compared with languages that have language support for enumerations.
– generic types
Most likely it will never get them.
– direct use of OS APIs, without the need of writing wrappers
Requires the use of CGO and a C compiler, while the majority of languages with native compilers allow direct binding to foreign code via some form of extern declarations
– only static compilation is available;
Complicates some plugin architectures, which is debatable given security concerns.
Does not allow for open source licenses that forbid the use of static linking in commercial software.
– no support for meta-programming;
As for some of the good things:
– fast compilation
Nice that they keep on mentioning it. Modula-2 was doing it in 1978, like any language that followed it in the Pascal family.
Only C and C++ suffer from lack of compilation speed.
– the PR about go routines and channels
Similar features are available as library concepts in more powerful languages.
– interfaces
The only feature Go interfaces have over Java and C# interfaces is that you are not required to directly reference them. This also complicates tracking down which interfaces a given type supports without help of an IDE like LiteIDE.
I spent one year doing Go projects on the side (2011), even did an initial contribution to the windows package for os.user, after realizing I would be better off with D and Rust.
Edited 2013-02-12 06:42 UTC
I took a look at Rust awhile ago… but it just didn’t look like a fun language to use. So I’m curious about why you find it more suitable than Go.
D is one of those languages that I keep meaning to poke at, but never get around to (because there’s really nothing there except nicer syntax.)
As for Go:
I don’t care for exceptions. Multiple returns with an error works well in my opinion.
I don’t frequently use enumerations.
Generic types would be nice (or rather better polymorphism support in the same vein as Haskell’s would be nice, but then again most of my complaints with Go end up being “well if it was more like Haskell…”.)
CGO is certainly a weak point of Go’s…
I have no great desire for dynamic linking, so I really don’t care if only static linking is available by default.
I’m not a huge meta-programming fan… so the lack there isn’t a big deal to me either.
To me, the nicest thing about Go is its standard library and documentation. I also like its clean syntax (for a C-like language.)
– Macros
– Proper type inference a la ML
– generics
– non nullable types
– sum types
– exceptions
The only thing I don’t like in Rust is the Perl syntax influence in how pointers get declared.
It is really a better C++, not only syntax.
You get to do meta-programming with proper language support, not the C++ template hacks.
Safer than C++, because you are require to state which code is unsafe. In C++ even if you restrict yourself to the safe language constructs, you need a static analyzer to proof it.
Whereas D is safe by default unless you make use of system modules/sections.
Go strides exited already in D before Go was created.
Additionally both languages have:
– some form of automatic memory management
– modules
– support for concurrency
– follow the school of thought where the developers have the same facilities as the compiler writers to create data structures.
As I said, I keep meaning to get around to looking at D, but safe by default and meta-programming aren’t things that are new to me (so there’s not really much motivation to learn.)
Of the things you listed for Rust, sum types are really the only thing I miss in Go… and it’s hardly worth learning a language for a feature that can be found better elsewhere.
Really, I only learned Go because of it’s built in co-routine syntax. I felt it was as good of a place as any to really buckle down on concurrency (since I don’t have to do much/any in my day job.)
Rust is more flexible than Go, since it gives an option to manage memory when needed.
That’s fine, but it’s not a feature that’s unique to Rust. So that’s not really going to motivate me.
Edited 2013-02-12 18:13 UTC
You may want to check out the ATS language, though I’m still warming up to the “look” of the syntax. No time to post my thoughts, so here’s the blurb from their site. (There’s also a kernel and some linux drivers written in ATS):
“ATS is a statically typed programming language that unifies implementation with formal specification. It is equipped with a highly expressive type system rooted in the framework Applied Type System, which gives the language its name. In particular, both dependent types and linear types are available in ATS. The current implementation of ATS (ATS/Anairiats) is written in ATS itself. It can be as efficient as C/C++ (see The Computer Language Benchmarks Game for concrete evidence) and supports a variety of programming paradigms that include:
Functional programming. The core of ATS is a functional language based on eager (aka. call-by-value) evaluation, which can also accommodate lazy (aka. call-by-need) evaluation. The availability of linear types in ATS often makes functional programs written in it run not only with surprisingly high efficiency (when compared to C) but also with surprisingly small (memory) footprint (when compared to C as well).
Imperative programming. The novel and unique approach to imperative programming in ATS is firmly rooted in the paradigm of programming with theorem-proving. The type system of ATS allows many features considered dangerous in other languages (e.g., explicit pointer arithmetic and explicit memory allocation/deallocation) to be safely supported in ATS, making ATS a viable programming language for low-level systems programming.
Concurrent programming. ATS, equipped with a multicore-safe implementation of garbage collection, can support multithreaded programming through the use of pthreads. The availability of linear types for tracking and safely manipulating resources provides an effective means to constructing reliable programs that can take advantage of multicore architectures.
Modular programming. The module system of ATS is largely infuenced by that of Modula-3, which is both simple and general as well as effective in supporting large scale programming.
In addition, ATS contains a subsystem ATS/LF that supports a form of (interactive) theorem-proving, where proofs are constructed as total functions. With this component, ATS advocates a programmer-centric approach to program verification that combines programming with theorem-proving in a syntactically intertwined manner. Furthermore, this component can serve as a logical framework for encoding deduction systems and their (meta-)properties.
What is ATS good for?
ATS can enforce great precision in practical programming.
ATS allows the programmer to write efficient functional programs that directly manipulate native unboxed data representation.
ATS allows the programmer to reduce the memory footprint of a program by making use of linear types.
ATS allows the programmer to enhance the safety (and efficiency) of a program by making use of theorem-proving.
ATS allows the programmer to write safe low-level code that runs in OS kernels.
ATS can help teach type theory, demonstrating concretely the power and potential of types in constructing high-quality software.”
Edited 2013-02-12 13:28 UTC
I have been following it for a while as well.
My strong points in the university were distributed computing and compiler design.
As such I try to keep up with research on programming languages.
I’ve started perusing ATS’ tutorials but like you I also had syntax issues.
By your description, ATS seems like pretty much an opposite of Go, philosophically. Go aims to be pragmatic above all.
I think that ATS may be pragmatic, especially in kernel land or “mission critical” code, sort of like a new spin on . Go is probably not the best comparison; I was posting that as a followup on a comment about Rust, D, and C++. More apt would perhaps be as a functional alternative to Ada+SPARK, though my initial impression is that it would have many improvements on these in the way of proof facilities and type system flexibility. But, that’s just my impression … I’m certainly no expert.
Goroutines are not really available as simple libraries in other environments, since they don’t map 1:1 to OS threads.
Python equivalent would probably be “Greenlets”.
You mean co-routines, continuations, Java Tasks, .NET tasks, C++11 futures, Win32 fibers and many other examples?
All of those do a M:N mapping of tasks to threads.
Edit: added some extra information
Edited 2013-02-12 12:50 UTC
Syntax:
Very thoughtful and concise, a breath of fresh air from a lot of other languages. At first it seemed confusing but over time I’ve come to appreciate it.
Read left to right and having the variable be described exactly as read is valuable.
Exceptions:
This is an egregious omission. While it is true that Exceptions encourage bad devs from making non-exceptional situations exceptional, the problem is that it isn’t black and white.
My method X may be perfectly fine with accepting a null reference, it may even have a specific code path for dealing with it.
Method Y may fail fast when taking a null because there isn’t much it can do with it. It wouldn’t make sense to try.
Therefore it is at the discretion of the programmer to decide which instances call for an exceptional situation and which don’t.
Defer/Panic/Recover are Try/Catch/Finally/Using in an almost comically worse syntax.
Exceptions are also about proving the end user context at run time to perform corrective action and fix the state to potentially try and recover. Error codes or multi return values on their own don’t convey this information.
Goroutines / Channels:
I’m not sure I like this as much as I like async/await operations in C# using the TPL. It seems like a much more natural fit to the language without resorting to channels. I’m not sure I like Goroutine isolation.
I’m not really a fan of blocking to receive from a channel when it is all asynchronous in C# and fits elegantly with the language in the form of return values being coerced from Futures.
consider:
it is clear to see the GetNumberAsync() is an asynchronous operation that returns 42 (which may or may not happen immediately)
when I do
all the code following this statement gets spun off as a continuation of this operation and the current method returns immediately.
To me it makes async code much less of a disjointed experience when writing it in a sequential fashion. Imagine a chain of awaits in C# vs trying to get a bunch of Goroutines to understand each other via channels that have a non trivial cost.
Still, the intention is a good one. Get people to stop thinking about threads, cores, and pools and start thinking on a higher level. I wonder how their Task (or Goroutine) scheduler compares to the Work stealing task scheduler in .NET
Pointers:
Love the lack of pointer arithmetic. Smart move and +1 for safety.
Overall my problem with Go is that it is just one solution to a multi-faceted problem. Its hard to for example promote asynchrony when you need to maintain support for things like the STD C Lib which destroys the advantages of async code (making async code behave like sync code kills any gains, and degrades perf) and in addition to this, Go requires an IDE effort to make it productive.
I’m a fan of their simplified inheritance model, but you need IDE support to make up for the difference in productivity that’s provided out of the box. Its hard at a glance to know which types implement which given interfaces.
It’d probably be worth while for them to do something like explicit interface declarations where a class can explicitly state to support an interface and it can be checked in much the same manner they currently do. What they have now seems to be an inference based inheritance model
Edited 2013-02-12 08:26 UTC
I’m curious why you feel you need an IDE? Go has been perfectly fine in most editors in my experience.
The language doesn’t inherently afford you a lot of the expressiveness of other OO languages in their object model. You can’t for example, at a glance, tell which interfaces a given “object” (as loose as the term is used in Go) implements.
That’s where I think an IDE and the language can split the difference and make up for that. There are other small instances too like the fact that IDEs can help remove the stigma surrounding some of the more exotic syntax choices. That’s valuable too.
it is my belief that a programming language is nothing without the tooling, a complete stack from beginning to end.
Ah, I suppose we’ll have to agree to disagree. While IDEs can be important, I feel a language should stand on its own. Which I feel Go does fine on.
I don’t think it does in the first few paragraphs I knew I would absolutely hate it.
Silly implied naming conventions, lack of proper encapsulation just turned me straight off.
Edited 2013-02-12 18:23 UTC
Personal preferences are bound to differ, but I do write Go in a regular text editor… so take that as you will.
I think my personal preferences are actually important as they are pretty basic criticisms. Which the article basically addresses with “haters will be haters”.
While you might be able to write code without an IDE.
I wonder how writing a project would work with Go, with the accessibility modifiers down to the naming convention. While I like naming conventions I do think code should be blindingly obvious to read.
I find it difficult enough (I don’t have TFS access to force naming convention conformance … yet) to get 4 devs to use the same naming conventions.
Maybe Go isn’t meant for this, but then I wonder who its target audience is then?
Edited 2013-02-12 19:20 UTC
Previously you hadn’t given me much to work with (i.e. what silly naming convention,) but now I think I can actually address your points.
So for starters, it’s not really a naming convention. If someone doesn’t uppercase their functions/variables/etc. then it’s unavailable. You don’t really have a choice in the matter, it must be capitalized if you want to use it. (which makes it not a naming convention since there’s no choice in the matter.)
So since it’s a requirement it quickly becomes very obvious whether something is available or not. This maybe takes some getting used to since caps in other languages are ignored.
As far as I can tell, the Go community doesn’t have any issue with it (even on projects) so it doesn’t seem like this is a big deal.
I question the readability of this approach.
Edited 2013-02-13 08:49 UTC
I question your questioning.
See, doesn’t do much for conversation. Provide reasons so we can debate or don’t say anything at all.
I think it is pretty obvious. But if I do have to elaborate I will.
Putting private, protected, internal (C#) and public make it blindingly obvious what the protection level is at a cursory look.
I am not a go developer, I don’t work with the community … so all I am saying is while the reasoning is sound, I question the readability.
Maybe it would take getting used to, but it’s perfectly natural once you know to look for it. I’ve never once had issues and I don’t think many people do.
This talk may be of some interest…
http://www.youtube.com/watch?v=5kj5ApnhPAE
I don’t want to get used to it.
The fact is that I think it happens to be bloody stupid.
When there are more obvious and viable ways to do the same thing. Like using a word before the variable that says its level of protection. What a great Idea I have just invented keywords for a protection level.
It is simple and unambiguous.
Edited 2013-02-14 19:55 UTC
lucas_maximus,
“I think my personal preferences are actually important as they are pretty basic criticisms. Which the article basically addresses with ‘haters will be haters'”
Your absolutely right, the author attempts to deflect criticism with immature ad-hominem quotes like the following.
“Controversial with [Internet controversialists]. People who complain about this are complainers. Features like this are useful because they let you know who likes to complain about things for no good reason. Go has a lot of features like this.”
I find the attitude unfortunate because it seems to detract from an otherwise reasonable overview of the language.
Don’t get me wrong, I love Go and I think it does stand on its own, and while it has weaknesses, it also has clear advantages, in a neat simple little package.
Go is simple. The compilers are simple to deploy and cross compiler. The inheritance story is dead simple. They seem to be carefully planning out design before throwing in features willy nilly (Generics, Exceptions, etc.) .
I just think it’d be augmented by an IDE. Without one its still perfectly usable, these are just nit picks.
Ah, yes then I suppose we agree. I read your previous post as “Go isn’t very good without an IDE”
That’s my fault, I tend to be rather hyperbolic.
For example, list all the interfaces the following type does support:
type Example struct {
afield int
}
func (e *Example) MyMethod () int {
}
Without the help of a tool that searches all visible interfaces and checks if Example fullfils the required set of methods, it is not possible by reading the code to know which set of interfaces are supported by Example.
You don’t need to know all the interfaces Example implements. You just have to know what the interface you’re using requires and if your object has it.
In other words, you’re looking at the code backwards compared to how Go works. Which may be an issue if ideal mental models of Go end up being backwards compared to other languages.
How do you do it without reading the full code that relates to Example struct, specially if it happens to be scattered across multiple files?
The solution proposed in multiple discussions in gonuts is to try to compile and see if it works and fix missing methods as required. Very helpful.
All of Example’s methods have to be in the same package as Example. Ideally, Example should be in its own package. Ideally, an object shouldn’t require more than 1 file to specify. Ideally, there should be some documentation.
So bad architecture/design choices aside… There’s no reason a grep can’t take care of this, but it’s usually just as fast to compile (and it gives better information.)
Besides, you don’t have to read all the code. You can easily pick up Example’s methods by scanning function declarations.
The design choice of inferring interfaces is a sound one. It allows you to add/remove/restructure interfaces without having to modify your objects. Yes, you have to remember more or get an IDE, but it makes life much easier, especially in the prototyping stages of development when interfaces aren’t yet stable.
You sound like you never did code development on enterprise level reading code developed by people all across the world.
Those advices only work if you’re developing on your own or a very small set of developers.
Exactly. These people who say that IDEs are useless have never really used them, nor worked on very large projects.
Sure, you can do most everything you can do in an IDE without an IDE. And you can write assembly instead of C, or machine language in a hex editor if you want to. You can use Perl scripts to spelunk through code and produce static reference listings. If you want to…
But I want to get work done. And I like being able to jump around my code with keyboard shortcuts that are only made possible because the editor/tool I’m using actually understands the structure of my project and the language I’m coding in (beyond basic syntax highlighting). And I like being able to step through code while looking at the project in the same tool I develop it in, instead of using esoteric commands in a command line-only tool that show you very little context at any given point in time. Sure, you can do it…but why when there are better tools? Use the right tool for the job.
Hey calm down, did I touched a nerve there?
I never mentioned IDEs except for the quote, I specifically said Without the help of a tool… already to avoid a 70’s editor vs IDE discussion.
Use whatever you like.
I really doubt Go is usable in the context of multi-site off-shoring enterprise projects, which are the bread-and-butter for any Fortune 500 company nowadays.
If it succeeds in this world, it will be because of Google’s sponsoring, nothing else.
Why do you doubt its usability? What aspects of Go are unsuitable? Do you mean that it’s has different issues from other languages, maybe issues you’re not as familiar with addressing? Please give details, as it’s hard to actually hold a conversation, let alone a debate, when participants don’t give anything to discuss.
I already did on previous posts:
– Lack of modern abstractions while compared with other mainstream languages;
– No proper way, without tools or compilation, to check what interfaces a given type supports.
I don’t see how the first is even remotely true. And the second is also a non-issue, which we’ve already discussed.
I’m pretty sure I was agreeing with you.
Sorry, I interpreted as being a sarcastic reply.
That is the problem of communicating only via text, sorry.
No one here has said IDEs are useless.
Except that people jab at IDEs all the time. They won’t go so far as to say they are useless, but they talk about how you don’t need them and you can do everything just fine in Emacs, which is patently false.
There hasn’t been any of that here, though. The closest that there’s been was my question on “Why do you think Go needs an IDE?” which was followed by my next comment in which I said “IDEs can be important”. Which I would think would make it clear that my stand point is “IDEs are useful, but try not to design a language that requires them.”
On the contrary that’s exactly what I get paid for.
I would appreciate it if you don’t try to undermine my credibility when all I’ve done is answer your questions.
Bad architecture will always exists, this is because not all developers are created equal.
Or you can just look at the top of the file for something like “implements”.
You do know how tools like rename work in IDEs don’t you?
It makes this benefit moot.
Edited 2013-02-13 16:40 UTC
Rename still isn’t as flexible.
For example, in Go if you are using someone else’s objects, you can still create interfaces that those objects implement, without needing to modify those objects (you don’t even need their source code.)
The whole point of knowing whether that something implements an interface is that it is easy to know whether it actually has certain properties and methods.
If this is all implied than I think it defeats the point of them.
Edited 2013-02-13 21:26 UTC
If you use interfaces as a primary means of tagging your objects then, yes you can’t do that in Go.
However, interfaces aren’t just a means of saying this object can do this, that, and the other. The methods of an object do that just fine; there’s no need to be redundant. Instead, Go uses interfaces as a contract. If I need a Reader then I’m going to be using a Read method. Which object this is doesn’t matter.
I commented on this earlier, but Go’s interfaces are backwards in comparison to most others. It’s not the object that implements an interface, but the interface that defines an object.
Except that contract isn’t explicitly stated. I don’t know that by looking at the code. I don’t think that is helpful when it comes to code readability. I am big on that.
What are you talking about? Of course the contract is apparent:
func Example(Reader r) { … }
The contract of this function states that it’s going to use a Read method provided by R (assuming typical Go naming conventions.)
** GROAN **
There is no way for me to know unless I check every function in an object whether it is implementing the interface.
With something like the implements keyword is makes it crystal clear.
It is less obvious while reading the code whether a type is implementing an interface in than Java or C#. It is extra mental overhead that can be used on other things.
Why are you being obtuse?
I’ve already covered that it’s not necessary to know whether a type implements some interface. The only time you need to know that is when you’re passing an object to a function and that’s a comparatively small amount of usage compared to what the function in question will actually do.
So, most of the code that you will read is going to be code that uses an interface to do something. Exactly like the function I gave. So it is always crystal clear what capabilities are at hand.
I explained it up-teenh times as my Grandfather would say.
It is about readability and I want to know before compile whether I am writing the code correctly … just an odd habit I have.
I think unless the code is crytal clear on its intent then it is not correct.
I work with a lot of developers, some are my skillset, some are better.
Some have re-skilled via courses and we obviously have juniors.
It is easier to tell them with a language when this word is put in front of a variable that is changes the accessibility of that variable … same with the interfaces.
For example.
I can tell them “If the interface has these methods defined then anything implementing them must implement them”.
It is crystal clear, there is no implied. The compiler will kick your ass straight away even if the IDE of choice doesn’t tell you before hand.
I believe you are simply missing the point on purpose at this point in the discussion.
As I’ve said “up-teenth times” it is still crystal clear.
Your example makes sense in Go. The issue that you’re missing is that the only time it matters if something does implement an interface is when you’re using an interface as a parameter. In which case your example is more literally:
“Any valid object for this parameter must have the methods defined by this interface”
And again, if it doesn’t the compiler will “kick your ass straight away”.
In my opinion, you’re focusing way too much on the definition of an object and no where near enough on actually using the object. So I’ll repeat:
An object has methods defined with it, these methods are sufficient to tell you what the object can do. Interfaces are a separate concept designed to provide a contract for parameters. Thus mixing the interface with the object is redundant.
Go as a language tries to avoid redundancy. Maybe this hurts readability in your eyes, but in practice there’s no difference and the “issue” you seem to have never comes up.
You keep on missing the point.
There is a keyword in Java that say
public MyClass implents IMyInterface.
That keyword is unambiguous. I can read the line and say to myself … If MyClass does implement the interface correctly it won’t compile.
It called readability and you keep on ignoring the fact that I keep on saying the say thing and you address it with some bullshit work around. Which I don’t think is acceptable.
And what I keep saying is that “implements” doesn’t do anything for readability.
The only thing “implements” does is force an object to have a certain signature. This is discussed in a different sub-thread in which the conclusion was:
Explicitly listing interfaces gives you compile time guarantees of what methods will exist, but if an object has the necessary signature for a different, non-listed interface then you don’t get to use the object for that interface (even though the object would work.)
Implicitly implementing interfaces has the reverse features. You lose compile time guarantees of what methods are available, but you get to use the object anywhere it might make sense to.
Yes it does because you arguments are bullshit. It says it “implements” the interface … if you think this doesn’t help readability … you are a moron.
To summarise:
* Just check the methods .. if it doesn’t compile “lol” you have done it wrong.
Sorry that isn’t good enough.
I don’t want to have to do, or want to trust other developers into doing that properly.
You keep on missing the point that code should be blatently obvious in what it does.;
Why don’t you read the clean code book. Because it is becoming quite obvious you need to read it.
Edited 2013-02-14 21:08 UTC
Yay! ad hominen attacks, because they make you sound like you know what you’re doing!
I’ve read the book. It doesn’t say anything about “implements” being a required feature for language readability.
Your issue is this: You’re unwilling to learn. You’re unwilling to adapt. Any benefit that could be gained is not worth changing your thought patterns for. If it’s different then it’s immediately not readable.
In other words, you’re xenophobic. (yay for more ad hominen, but I’m done trying to help you.)
No you are unwilling to accept that I value readability.
I have pointed out multiple time where you have could have discussed this on a case by case comparison but you declined.
I declined you explanations based on simple keywords that explain things very bluntly and clearly. Yet you never addressed these concerns directly.
I don’t mind if you say this is personal preference or what the community does. But it was “this is this way and you have to grep through methods like a numpty to see if something implements and interface”.
I then get bored of this and I am direct enough to tell you exactly what I think and that it “ad hominem”
Whatever you like to believe…
Edited 2013-02-14 21:45 UTC
lucas_maximus, I guess it is time to move on.
I see this type of discussions every day on gonuts (Go mailing list).
Then they get surprised that only script kiddies use Go in real systems.
http://commandcenter.blogspot.de/2012/06/less-is-exponentially-more…
Yeah it probably is.
satsujinka,
He’s got a valid point though, there is a difference between explicit intent and inferred intent. Which you prefer is a matter of opinion. It’s similar to the difference between loosely typed languages and strongly typed ones. Some of us might prefer loose typing with inferred conversions, others prefer explicitly strong typing. Regardless of your personal preference, can you see why others would have a different preference?
Interestingly just as go has both strong and loose typing, I wonder if it could also have both strong and loose interfacing. This way if it’s explicitly specified, the compiler will enforce the interface or error out. And if it isn’t specified it could infer a matching interface. Seems like that could be feasible to me.
Edited 2013-02-14 03:02 UTC
Um… I haven’t given any personal preferences. I’m just defending Go because someone has to in order for a debate to occur.
On the note of optional interface implementation. Is that really very different from just adding a comment? Sure the compiler does stuff (like tell you that you need method X) but you’d run into issues anyways if you tried to use an object that didn’t actually support the interface. And I’m pretty sure the error message would still make it clear what the problem is (object Y is not a Z.)
satsujinka,
“Um… I haven’t given any personal preferences. I’m just defending Go because someone has to in order for a debate to occur.”
So you are playing devil’s advocate then? I certainly didn’t get that impression, but ok.
“On the note of optional interface implementation. Is that really very different from just adding a comment?”
It’s very different. It’s like adding a comment to say the variable is a double precision float point versus an explicit declaration of a variable as double floating point which the compiler can enforce. In contract based team programing, it’s often beneficial to *explicitly* declare the intention of a class to implement something and have the compiler strictly enforce it. Comments are not meaningful in contract based programming.
“Sure the compiler does stuff (like tell you that you need method X) but you’d run into issues anyways if you tried to use an object that didn’t actually support the interface. And I’m pretty sure the error message would still make it clear what the problem is (object Y is not a Z.)”
It’s logically better to throw the error at the point where the class is defined rather than where the object of a class gets used. You might think this is nitpicking, but in contract based programming it can be significant because the interface provider and consumers might be different developers from different companies in different timezones. For the consumer to get the interface implementation error when the provider is the one that needs to fix it is not helpful.
Of course you can blame the provider for not testing it (dang it why didn’t the comment work?), but keep in mind that languages with explicit interface declarations have built in test cases for this such that the producer will get an error during compilation.
Edit: I wouldn’t go as far as to say everyone needs explicit interfaces. In small/home projects, it probably wouldn’t come up as often, but for large enterprise projects with hundreds of classes and code paths belonging to rarely used corner cases, it’s probably best for developers to be able to explicitly state their intention – especially since they come and go over the course of the project. I think adding optional support for them would be a very good idea to please people of both crowds.
Edited 2013-02-14 20:03 UTC
It’s not quite devil’s advocate. I like Go. The issues that have been brought up aren’t actually issues when you start using Go. I’ve been trying to explain why that is, but I don’t seem to be making any progress (then again Go isn’t my #1 language; so it’s a bit like me trying to explain why German capitalizes all nouns (English is my first language if that wasn’t obvious.)) It may just be one of those things you have to try to understand why, but that’s unfortunate since those I’ve been debating with are unlikely to try Go because they are hung up on a minor issue (that doesn’t really exist.)
It’s not quite the same as your floating point example. It would be more like if the declaration is guaranteed to be a double, but you declare it as one anyways.
In your second example, I could imagine that being an issue. However, the same sort of issue occurs if the provider explicitly labels the object but doesn’t include one you want (that the object does support.)
So better then optional would be “guarantee signatures.” Which would say “this object MUST implement x, y, and z; but it may implement any others that the object has the right signature for”
satsujinka,
“It’s not quite the same as your floating point example. It would be more like if the declaration is guaranteed to be a double, but you declare it as one anyways.”
I intentionally picked ‘double’ because it’s often not clear from context whether the compiler is using a ‘double’ or ‘single’ variable type. But I still get your point.
“So better then optional would be ‘guarantee signatures.’ Which would say ‘this object MUST implement x, y, and z; but it may implement any others that the object has the right signature for'”
That’s the idea.
Ever heard of adapter pattern or expression problem?
Why would you want to implement it yourself if the language gives it to you for free?
I give up.
I’d like to add something that’s not already been commented on:
Go is a dream to cross compile with. eg I can write a program on x86 Windows, test it and then compile it for a Linux ARMv6, still on the Windows PC, and just copy the ELF over. No code modifications what-so-ever.
I know this can all be done in C++ and scripting languages as well. But Go makes the process significantly easier than C++ (in regards to the more complicated programs), with significantly less code than Java and compiles unlike scripting languages.
So while Go isn’t perfect, it offers me the best balance between writing speedy code and having quick run times. Go is now my “minimum fuss” language.
Edited 2013-02-12 12:41 UTC
This is only possible if you restrict yourself to the base library and Go pure code.
This is nothing new, cross-compiling exists since the dawn of computing.
I really wish people would read before arguing…
Yet that’s exactly what the context of this thread is about. We’re not talking about some imaginary examples of Go which break convention; we’re talking about Go code written as Go code is designed. And that means using non-OS specific API calls in the base to build extended non-OS specific Go libraries.
Go is designed with portability in mind. C++ wasn’t. So while C++ can be portable, it’s much easier to write portable code in Go.
Thank you for telling me what I’d already categorically stated in my post.
My point was Go makes the process much less painful, not that it’s the only language to have ever supported cross-compiling.
These days you can do pretty much anything in pretty any language. So the choice of language boils down to productivity (time spent coding, compiling, porting, etc) vs performance (raw execution speed, memory usage, etc) and sometimes even performance is a non-issue. So my point was this: Go enhances productivity. Which is why it’s my new go-to language.
Edited 2013-02-12 14:20 UTC
“Go is designed with portability in mind. C++ wasn’t. So while C++ can be portable, it’s much easier to write portable code in Go.”
I actually agree with moondevil’s point. While the c++ ecosystem is filled with tons of incompatible libraries/frameworks across tons of platforms, the c++ language itself doesn’t impose significant portability issues, in fact it’s highly portable. I think you ought to be blaming the C++ frameworks for portability issues rather than the C++ language itself.
Now in the end this difference may be mute because we really do need the C++ frameworks in practice, but I think it’s important to recognize because without a central authority for coordination of one common framework, all languages have the potential to devolve into the situation C++ finds itself in with incompatible local frameworks. I can see it now: “microsoft foundation classes for Go”, haha.
Personal anecdote:
Even the JDK, with the most portable framework I’ve ever used, wasn’t perfect. For a university project we were using java to control serial ports connected to early bluetooth prototypes. The JDK worked perfectly from windows, but we needed to adopt a custom serial port driver for spark workstations (oh delicious irony).
I did a bit of work with OpenBabel for my dissertation (I made a very simple Java app) and was going to release it open source (probably a “do what you f–king want license”) with a few bug fixes and a general code clean-up.
The JNI interface was a PITA to link up on Linux and I didn’t even attempt it on OpenBSD. The Java interface was generated by SWIG bindings and they were totally different to the Windows versions. It might have been something to do with SWIG but I just gave up there as I was just going to spend maybe an afternoon getting a decent release.
(There was only a few thousand lines of code, and most of it was pretty decent other than some novice mistakes I made at the time).
In the end it bit-rotting in my dropbox. I think I might build a swing front end for it and stick it up on my personal site for anyone who wishes to use it on the OpenBabel google group and if they are inclined they can port it to another OS themselves. I don’t really have the time, nor the inclination.
Edited 2013-02-12 18:33 UTC
I appreciate what you’re saying, but these days frameworks are as integral part of the language as the language itself. eg what would be the point of C# if it wasn’t for .NET? Or Java if it wasn’t for JRE? Or even Python if it wasn’t for it’s modules?
I genuinely do like C++ – I’m not trying to argue that one language is a “better” language than the other. But it is fair to say that because of the core frameworks and because of the Go compiler, Go is an easier language to port.
That’s a very interesting point. We do see this problem in some other languages as well.
hehehe interesting stuff
I’m not a fan of Java personally (to be frank, it’s the language I hate the most). But that boils down to personal more than anything. “each to their own” as they say hehe
Laurence,
“I appreciate what you’re saying, but these days frameworks are as integral part of the language as the language itself. eg what would be the point of C# if it wasn’t for .NET? Or Java if it wasn’t for JRE? Or even Python if it wasn’t for it’s modules?”
True, Go is young and has a beautiful framework now, but what about in a few years? After “getting around” and putting on a few pounds, she might start to look like grandma Perl
Exaggerated a tad for comedic effect. The following link makes me laugh and cry simultaneously…
http://www.perl.com/pub/2003/03/13/datetime.html#perl%27s_built…
hehe Perl is actually one of my favourite languages.
I guess at the end of the day, no language is perfect and only as powerful as the developer. eg I used to dismiss Javascript as a a toy until one clever developer built a Linux virtual machine[1] with it – which is far more sophisticated than anything I’ve ever done in C++.
[1] http://bellard.org/jslinux/
Edited 2013-02-13 09:59 UTC
Laurence,
In this sense all languages are equal because they’re all turing complete. I find javascript is quite a good language but often times it’s used in contexts it really isn’t very well suited for because it’s the only language available. The document object model has alot of evolutionary baggage and it’s virtually impossible to optimize for native performance, but we are stuck with it in the foreseeable future.
I liked perl as well, after all it is the gold standard for regular expressions and fundamentally incorporates IO in novel ways. I prefer it infinitely over bash shell scripting (UGH). But the number of competing frameworks/libraries in CPAN (117K) is overwhelming, consequently perl code is many times more fragmented than C++. I like CPAN’s moto though “Stop reinventing wheels, start building space rockets”. I wonder if it’s meant sarcastically because the horse has already left the stable a long, long time ago.
I agree with all of that, but i particularly like this bit:
“In this sense all languages are equal because they’re all turing complete.”
it’s quite an interesting take on the “which language is better” debate. A refreshing opinion.
I really wish I could +1 you if just for that statement alone.
It seemed that fast compilation times was a goal of the language. If it was a side effect, then great, but I think they were trying to address a problem that nobody really had.
I’m upset that Google abandoned the Unladen Swallow project to make Python faster and integrate LLVM. Had their new Go language targeted LLVM I’d be less upset.
Actually I recall the Go authors stating that indeed compilation speed was an issue for them in their large C++ projects at Google which made it a focus for Go.
Ehh, why would it matter? Anyway, the Go devs looked at both GCC and LLVM as backends but found them both too large and slow and instead wrote the Go compiler from scratch.
There is GCCGo which I suppose is largely a stopgap solution to offer better optimization and support a larger range of architectures while the official toolchain matures.