Google's New Language: Go

I've been being peppered with questions about Go, the new programming
language just released as open-source by Google. Yes, I know about it. And
yes, I've used it. And yes, I've got some strong opinions about it.

Go is an interesting language. I think that there are many
fantastic things about it. I also think that there are some really dreadful
things about it.

A warning before I go on: this post is definitely a bit of a rush job. I wanted to get
something out before my mailbox explodes :-). I'll probably try to do a couple of
more polished posts about Go later. But this should give you a first taste.

The natural question is, what does it look like? It's vaguely C-like, but
with a lot of cleanups and simplifications. Every declaration is preceded by a
keyword that identifies what it's declaring: type,
func, var, or const. Lots of parens
that are required in C have been removed. The type declarations have been
cleaned up quite a lot - they've gotten rid of the type-declaration garbage of
C.

In every declaration, the name comes first, followed by the type. So, for
example, types are declared after variable names, and all type
modifiers precede the types. So *X is a pointer to an
X; [3]X is an array of three X's. The
types are therefore really easy to read just read out the names of the type
modifiers: [] declares something called an array slice; "*"
declares a pointer; [size] declares an array. So
[]*[3]*int is an array slice of pointers to arrays of three
pointers to ints.

Functions in Go are amazing. They start off really simply, but by
providing a few simple extensions, they let you do all sorts of things.
To start off, here's a factorial function in Go.

func Factorial(x int) int {
   if x == 0 {
      return 1;
   } else {
      return x * Factorial(x - 1);
   }
}

Go extends that by adding support for named return values. You can declare the
return value as a variable in the function header; then you can assign values
to that variable. When the function returns, the last value assigned to the
return variable is the return value. So you could also write factorial
as:

func Factorial(x int) (result int) {
  if x == 0 {
    result = 1;
  } else {
    result = x * Factorial(x - 1);
  }
  return;
}

You can also write a function with multiple return values:

func fib(n) (val int, pos int) {
   if n == 0 {
      val = 1;
      pos = 0;
   } else if n == 1 {
      val = 1;
      pos = 1;
   } else {
      v1, _ := fib(n-1);
      v2,_ := fib(n-2);
      val = v1 + v2;
      pos = n;
   }
   return;
}

(The above contained boneheaded mistake 1: I just wrote that out, and didn't bother to compile it. Naturally, I screwed it up in a silly way. It's since been fixed.)

It's not object-oriented in a traditional way; it provides something like
a limited form of object-orientation using another extension to functions. You
can define new types - either type aliases, or structure types. You can
declare methods for any type at all in the module where it's defined.
A method is just a function which has a parameter preceeding the
function name.

So, for example, a basic linked list could be implemented as;

type IntList struct {
  next *IntList;
  val int;
}

func (s *IntList) SetNext(n *IntList) {
   s.next = n;
}

func (s *IntList) GetNext() *IntList {
   return s.next;
}

func (s *IntList) SetValue(v int) {
   s.val = v;
}

func (s *IntList) GetValue() int {
   return s.val;
}

(Boneheaded mistake 3: I originally put the declarations in the wrong
order above - even within a struct, it's name-first - so "next *IntList"
not "IntList* next".)

One of the dominant themes that you'll see as I continue to describe it is
minimalism. The guys who designed Go were very focused on keeping things as
small and simple as possible. When you look at it in contrast to a language
like C++, it's absolutely striking. Go is very small, and very simple. There's
no cruft. No redundancy. Everything has been pared down. But for the most
part, they give you what you need. If you want a C-like language with some
basic object-oriented features and garbage collection, Go is about as
simple as you could realistically hope to get.

To give you one example of that minimalist approach, Go allows you to
define types with methods. But there's no such thing as a class, and there's
absolutely no inheritance. Instead, there's a kind of composition. I won't go
into detail about it here.

As I said above, you can define methods on any type. The methods
are really just functions with a special parameter. There's no such thing as a
type constructor! There's an allocation operator, "new" - but it doesn't
initialize values. You can't provide Go with any automatic initializer.
Instead, things like constructors are handled by convention. You'll generally
create a new data type inside of a module. That module will have a public
function named "New", which returns an initialized value. So, for example,
there's a module named "vector" containing an implementation of a vector; to
create a vector, you import the vector module, and call
vector.New(size).

Another example of that minimalism is the way that they handle abstraction
and name hiding. There are exactly two kinds of name visibility: public, and
private. Private things can only be seen in the module that declared them;
public things can be seen in any module that imports them. The way that you
make things public is by lexical cues: public things are things that were
declared with an identifier starting with an upper case letter. "fact" is
private, "Fact" is public.

The most innovative thing about it is its type system. There are two kinds
of types in Go: concrete types, and interface types. Concrete types are
exactly what you're used to from most programming languages. Interface
types are similar to interface types in languages like Java, with one
huge exception: you don't need to declare what interface types you
implement! An interface is a specification of what methods a type must
provide to be used in some context. Anything which implements
those methods implements the interface. Even if the interface was
defined later than a type, in a different module, compiled separately,
if the object implements the methods named in the interface,
then it implements the interface.

To make that even better, methods aren't limited to objects. In fact, Go
doesn't really have objects. Any value, any type at all, can have methods. So
you can make an integer type with its own methods. For
example:

type Foo int;

func (self Foo) Emit() {
  fmt.Printf("%v", self);

}

type Emitter interface {
  Emit();
}

Foo implements Emitter. I've created the type
"Foo". Values of type "Foo" are integers. Then I've implemented a method on an
instance of "Foo".

That's brilliant. I absolutely love it. And even in the
relatively small amount of time I've spent hacking Go code, I've
seen it pay off, when I've created new interfaces, and realized that
old types already implement the interface. It's a very elegant idea,
and it works really well. It ends up giving you something with the
flavor of Python-ish duck typing, but with full type-checking
from the compiler.

For example, the first thing I wrote in Go was a parser combinator
library. I defined an interface for the input to a parser:

// ParserInput represents an input source readable by a
// parser. 
type ParserInput interface {
  // Get the character at an arbitrary position in the
  // input source.
  CharAt(i int) uint8;

  // Get the number of characters in the input source.
  Size() int;
}

Now, anything that implements CharAt(int) and
Size() can be used as an input to a parser. Then,
I defined an interface for parsers:

// ParseValue represents the type of values returned by
// successful parses.
type ParseValue interface { }

// A Parser is an object which parses input sources. The
// framework of parser combinators provides a very general,
// backtracking parser.
type Parser interface {

// Run the parser on an input source, starting with
// the character at a specified position. If the parse
// succeeds, it returns "true" as the status, the
// number of characters matched by the parser as the match_len,
// and an arbitrary parser-specified, return value as the result. 
// If the parse fails, then it returns false as the status, -1 as 
// match_len, and nil as the result.
   Parse(in ParserInput, pos int) 
       (status bool, match_len int, result ParseValue);
}

So a parser is anything which has a Parse method. A parse
method takes an input, and a position in the input; and it returns three
values: a success code (indicating whether the parse succeeded or failed); a
match length (indicating how many characters in the input were accepted by the
parser), and a return value. The return value can be anything: it's
defined as an empty interface, and everything implements the empty
interface.

To build parsers, you start with a kind of parser that can process
a single input character, which is any character from some set of
characters.

// CharSetParser parses a single character from among a 
// specified set.
type CharSetParser struct {
  chars string;
}

func (self *CharSetParser) Parse(in ParserInput, pos int) 
 (status bool, match_len int, result ParseValue) {
status = false;
match_len = -1;
for c := range self.chars {
if self.chars[c] == in.CharAt(pos) {
   result = self.chars[c];
   match_len = 1;
   status = true;
}
}
return;
}

This demonstrates one sort of odd feature of Go. A structure and a pointer
to a structure are different types, and they can have different
methods
. A pointer to a

CharSetParser

is a parser;
but a

CharSetParser

is not!

The implementation above doesn't provide a way of creating a

CharSetParser

. To do that, we need a function. And to try
to make the parsers look as clean as possible, we'll name it
so that it doesn't look like a creator function, but just a parser itself:

// Create a CharSetParser which accepts any one character
// from a specified string.
func CharSet(s string) *CharSetParser {
   return &CharSetParser{ s };
}

Then you add more kinds of parsers which allow you
to combine simple parsers. For example, one combinator
is repetition, which runs a parser over and over until it succeeds:

// ManyParser is a parser that parses a repeated syntax
// element. It succeeds if the sub-parser succeeds at least
// a specified minimum number of times. Returns a list
// of the results of the sub-parses.
type ManyParser struct {
  min int;
  parser Parser;
}

// Create a ManyParser which matches min or more
// repetitions of the sequence parsed by p.
func Many(p Parser, min int) *ManyParser {
  result := &ManyParser{ min, p };
  return result;
}

func (self *ManyParser) Parse(in ParserInput, pos int) 
 (status bool, match_len int, results ParseValue) {
  status = false;
  curPos := pos;
  numMatches := 0;
  stepResults := vector.New(0);
  stepSuccess, stepLen, stepResult := self.parser.Parse(in, curPos);
  for stepSuccess {
numMatches++;
    curPos = curPos + stepLen;
    stepResults.Push(stepResult);
    stepSuccess, stepLen, stepResult = self.parser.Parse(in, curPos);
  }
  if numMatches < self.min {
     stepSuccess = false;
     match_len = -1;
     results = nil;
     return;
  }
  status = true;
  results = stepResults;
  match_len = curPos - pos;
  return;
}

With that, you just say Many(P, 0) to represent a parser
that parses 0 or more repetitions of P.

Anyway, the end result is a library where you can write lots of
very simple functions which combine parsers in very flexible ways.
The end result is something where I can write a parser that parses
lisp SExpressions into a cons-list structure with:

SexprParserRef := MakeRef();
ManySexprs := Action(Many(SexprParserRef, 1), new(VectAction));
ListParser := Second(Seq([]Parser { Lp, ManySexprs, Rp }));
Sexpr := Alt([]Parser{ ListParser, SymParser });
SexprParserRef.SetTarget(Sexpr);

Alas, not everything about it is so wonderful. Sometimes that minimalism
comes back to bite you on your ass. And worse, there's a bit of a "for me but
not for thee" attitude that pervades some aspects of the language design.

For one example of an odd minimalist tradeoff: they decided that they
didn't want to specifically add something like an enumeration type. After all,
what's an enumeration? It's really a type-safe alias for an integer, with a
set of constants defining the members of the enumeration. Go already has the
ability to define a type-safe alias for an integer! So why bother allowing the
definition of a new kind of type? Instead, just make it easy to define the
constants. So they created a pseudo-variable named iota which can
be used inside of a constant declaration block. Each time you see a semicolon
in a constant block, iota is automatically incremented. So to define a set of
colors, you could do something like:

 type Color int; const ( RED Color = iota; ORANGE = iota; YELLOW = iota;
GREEN = iota; BLUE = iota; INDIGO = iota; VIOLET = iota; ) 

That will create a color type, with "RED" as 0, "ORANGE" as 1, etc. Of course, it's kind of annoying to have to re-type the iota every time. So
if you omit the values after an iota in a const block, it automatically
just copies them. So you could rewrite the colors as:

type Color int;
const (
  RED = iota;
  ORANGE;
  YELLOW;
  GREEN;
  BLUE;
  INDIGO;
  VIOLET;
)

It seems a bit strange and obtuse, but not awful. But it can get downright
strange. Here's an example from the Go tutorial:

type ByteSize float64
const (
_ = iota;// ignore first value by assigning to blank identifier
KB ByteSize = 1<<(10*iota);
MB;
GB;
TB;
PB;
YB;
)

Iota starts at 0. By assigning it to "_", you effectively discard the zero
value. Then, "KB" is defined as 210*iota. That full expression is
then copied to the successive values. So MB gets a copy of Bytesize =
1<<(10*iota)
, which evaluates to 1<<(10*2). And so on.
Since ByteSize is an alias for a float64, the
values are automatically converted to floats.

It's powerful, but if you ask me, it's ad-hoc and ugly.

Then there's the "We're the language designers, we need stuff you don't".

The Go type system does not support generic types. They're
considering adding them at some point in the future, but for now,
they don't consider them necessary. Lowly programmers just don't
need parametrics, and it would clutter up the beautiful compiler
to implement them.

Oh, but wait... Go really needs type-safe arrays. Well, that's OK.
Everyone provides arrays as a sort of special case - what language doesn't have
typed arrays, even if it doesn't have any other parametric types? And we really
want these cool things called slices - but they really need to be strongly typed.
So we'll let them be parametric. And maps - we really need a map type,
which maps keys to values, and it really needs to be type-safe. So we'll add
a parametric map type to the language, by making it a special case built-in.

So: you can't write parametric types - but they can. And that
creates a very weird asymmetry to the language. Everything in Go is passed by
value - except for the built-in slice and map types, which are passed
by reference. Everything is allocated by "new" - except for the
built-in slice and map types, which are allocated by "make". It's
by far the biggest blemish in Go, and it's absolutely infuriating.

  • There's a similar issue around error handling. The language doesn't
    have exceptions. I can accept that - exception handling in most languages
    is absolutely hideous, and you can make a strong argument that
    it's so damned broken that you should find a way to do without. Particularly
    in a language like Go, where you can return multiple values from functions,
    you can do things like return both a result and a status code, and handle
    errors via status codes.

    So the Go guys left out exceptions. They say that you don't need them. But
    for their own code, they added workarounds that become something like
    exception handling for their own code. For example, if you want to do a cast
    from an interface type X to an interface type Y, you'd write something
    interface type to another, you'd write "y = x.(Y)". But if the
    value x didn't implement interface Y, it would be an error, and
    the program would crash. So if you're not sure that x implements
    Y, you can write "y, ok := x.(Y)". That never fails;
    if x implements Y, then y gets the casted value, and ok is true.
    If x doesn't implement Y, then y get assigned nil, and ok is set
    to false. Once again, having a way of catching an error is OK for the language
    designers, but not for anyone else.

    Anyway, with the complaints out of the way: one other major piece of
    goodness is compilation speed. One of the fundamental goals of Go was to be
    able to compile things really quickly. Lots of things about the
    language were designed to make it possible to build a really fast compiler,
    and to be able to do full separate compilation without every needing to
    re-process anything. (The motivation for this is that at Google, we have a
    very large code-base with tons and tons of code re-use. This is a very good
    thing. But because most of that code is C++, builds can be incredibly slow.
    The way that C++ header files work with a standard compiler, you can wind up
    re-parsing the same file hundreds or thousands of times. So even with a really
    fast compiler, you can easily wind up with some extremely slow compile times.
    Tricks like pre-compiling headers can help, but they've got their own
    problems.)

    Go programs compile really astonishingly quickly. When I first tried it, I
    thought that I had made a mistake building the compiler. It was just too
    damned fast. I'd never seen anything quite like it. I'd taken a parser
    combinator library that I'd written in Java, and re-implemented it in Go - the
    full version of the code that I excerpted above. The code was slightly more
    than 30% shorter in Go, and also cleaner and prettier than the Java. A full, clean
    build of the combinator library in Java took just over 3 seconds in Eclipse. It took
    0.6 seconds on the command-line compiled with Jikes. With the 6g go compiler,
    it took 0.06 seconds!

    Before using Go, Jikes was the fastest compiler I'd ever
    used. But Go managed to do better by a factor of 10! And
    Jikes was generating Java bytecode; 6g is generating
    reasonably well-optimized native code! Part of that is
    the genius of Ken Thompson, the guy who implemented 6g; but part of
    it is also the very careful design of the language.

    (Boneheaded mistake 2: for some reason, I always confuse Ken Thompson and Dennis Ritchie. It's Ken who wrote 6g, not Dennis, as I originally wrote.)

    So... At the end of the day, what do I think? I like Go, but I don't love
    it. If it had generics, it would definitely be my favorite of the
    C/C++/C#/Java family. It's got a very elegant simplicity to it which I really
    like. The interface type system is wonderful. The overall structure of
    programs and modules is excellent. But it's got some ugliness. Some of the
    ugliness is fixable, and some of it isn't. On balance, I think it's a really
    good language, but it could have been a lot better. It's not going to wipe C++
    off the face of the earth. But I think it will establish itself as a solid
    alternative. And hopefully, over time, they'll fix some of the worst parts
    of the ugliness, without sacrificing the beauty or simplicity of the language.

    To preemptively answer a question I'm sure people will ask: am I using
    Go for my daily work? Not yet. My project has a lot of existing code, and at the moment, I'm constrained by that. I'll be starting work on a prototype of a major new component very soon, and once I've had time to look at the foreign function interface for Go, I'll make a decision about whether or not to use it. Basically, if the FFI is good enough to allow me to link to the Google infrastructure that I need to be able to use, then I will use Go for my prototype, and hopefully for the full component.

  • More like this

    Is this new language tied to the Android platform, both smartphone and pc versions, and the chrome browser?

    I get this feeling they picked the name so that when they put out the next version of the language, they can call it Go2 and make Dijkstra jokes.

    By James H G Redekop (not verified) on 11 Nov 2009 #permalink

    Neat concept. I agree with your criticisms. Especially on exception handling. That is exception handling, but only a) for special cases, and b) without (yet) the ability to interpret the nature of a failure. Exception handling may be ugly. But real programs can't just roll over and die.

    @1;

    No. Go has absolutely nothing to do with Android or Chrome.

    Hopefully, you'll be able to write plugins for Chrome using the native client, but I don't know.

    The goal of Go is to be a systems programming language. It's for things like infrastructure, backends and servers - the kinds of things that we mostly write in C++ today.

    I've looked at Go after hearing about it today, and it looks like it has promise. I definitely like the "less is better" approach. However, I'm also missing generics, and operator overloading. What I'm really missing though (and maybe I just haven't looked carefully enough) is the ability to create Domain Specific Languages in Go. It's one of the reasons I'm sticking to C++ for now, instead of moving to C# for example - even though writing DSL's in C++ often seems to require using arcane magic. I'm really waiting for a language that is fast, type-safe, and makes defining and using DSLs easy. Given the stated goals of Go, though, I don't think Go will be that language anytime soon.

    That interface system somewhat reminds me of Haskell's typeclass system, except that in Haskell you need to explicitly explain how a data type belongs into a typeclass - but it can still be done outside the declaration, which I think is really nice. Doesn't Objective-C have something like that as well?

    But, alas, I'm a sucker for type-safety with generics... I might have to wait for that until I give this language a serious try.

    The way that you make things public is by lexical cues: public things are things that were declared with an identifier starting with an upper case letter. "fact" is private, "Fact" is public.

    Maybe this is a naive question, but isn't that setting up for a lot of subtle and hard-to-detect bugs just by mistyping a capital or lower case letter?

    I'm glad to hear that Google has rediscovered Modula-3.

    There's hope for the world yet.

    @7:

    No, it's not. The language is case significant. So "Foo" and "foo" are different - the fact that the initial capital is also used as a cue for what's exported from the module shouldn't cause any more name-confusion grief than any other case-significant language.

    Can you elaborate on multiple return values? In your example code for fib(n), how do you interpret the line

    val = fib(n-1)+fib(n-2)

    if each invocation of fib(_) returns two ints? Does it default to the first one?

    @10;

    That would be an error. That's what I get for not actually running my code. D'oh. I'll go fix it.

    The ability to add methods to types sounds a lot like Ruby, and is one of my favourite features. In Ruby you can add methods to existing types; I gather that is not possible in Go, though?

    @15:

    That is name before type.

    The declaration starts with a keyword, identifying what kind of entity it declares. Since it's a type declaration, that's "type".

    Next comes the name that's being declared: "IntList".

    After the name comes the type, which is a struct containing two fields.

    @17:

    Oops, my apologies. For some stupid reason, I've always confused Ken Thompson and Dennis Ritchie.

    @14:

    That's actually a slightly tricky question.

    You can only add methods to a type in the module in which it was declared. But you can always declare a type alias, which then gives you the ability to add your own methods, at some cost in verbosity. It's not as convenient as being able to just add methods to types,
    but it gives the author of the original module some ability to enforce an abstraction. In practice, I've found that it's a very reasonable tradeoff - you keep strong typing,
    fast separate compilation without any inter-module analysis, and extensibility - but you have to sometimes do some explicit type conversions in order to make all of that work.

    I think #15's question was about the structure itself. It looks like you are still thinking in C land with the structure definition.

    Should it be:

    type IntList struct {
    next *IntList;
    val int;
    }

    By Anonymous (not verified) on 11 Nov 2009 #permalink

    @21:

    D'oh. Yup, you're right. I *really* should have test-compiled all of the code in the post, but I was in a hurry to get the post out, since so many people were bugging me!

    Typo:
    if you want to do a cast from an interface type X to an interface type Y, you'd write something interface type to another, you'd write ...

    By Colin Curtin (not verified) on 11 Nov 2009 #permalink

    I remember the "iota" operator from APL... when you put "iota n" in your APL, that meant the numbers from 1 to n. Is that where they got the name from, or is there a common ancestry of which I am ignorant?

    By Paul Clapham (not verified) on 11 Nov 2009 #permalink

    @24 Most likely they both originated from the colloquial use of "iota" to mean "a little bit". So, each increment adds an "iota" to the previous step.

    By Avi Steiner (not verified) on 11 Nov 2009 #permalink

    You know, all this hoopla over "Go" and how wonderful it is and yadda yadda yadda was being pushed by the ETH Oberon group and all Oberon users back in the late 90s. With few exceptions, certainly none large enough to fundamentally change the language for, Go does _NOTHING_ different than Oberon-2.

    Why can't people just use Oberon and move on with life? I'll tell you why -- because it was designed by Niklaus Wirth. People HATE Wirth. He's the anti-Christ. He's an abomination. Nobody loves him, and neither should you. He's communist, fascist, and a capitalist pig all at the same time. And, get this folks!, he writes his languages using all-caps keywords! OH NOES!!

    Except, of course, the folks who want to cash in on Wirth's ideas while retaining C/C++'s basic, ugly, highly error-prone, and utterly retarded syntax. I have no respect what-so-ever for Pike and Thompson here -- they're just plagiarizers and have actually made the language WORSE. And, unbelievably hard to read and maintain in comparison.

    They should be ashamed of themselves.

    I am so sick and tired of this uber-opportunist and politicized bull$#!+ in the comp-sci/comp-eng fields. If it's one thing that pisses me off more than any other is when awesome technology comes out, gets trash-talked fifteen ways 'til Monday, then some jackass who lists "Bell Labs" on his resume comes out with the EXACT SAME LANGUAGE but with a different syntax and a handful of bells and whistles (which EASILY could have been retrofitted into Oberon-2 had anyone game a damn about it), and he somehow gets all cuddly kudos and awesome street-cred for it.

    BULL$#!+.

    Well... sorry but I won't try Go for several reasons :
    1- Pointers ?? Looks like Java managed to get rid of those like 10 years ago.
    2- Interfaces ? Yes, really neat idea. Sorry, but Java uses them since the beginning.
    3- Struct ? Where is my (cow) class ? No, this is a struct, thus can't be OO. I just couldn't live outside the OO-paradigm.
    At least one great idea : having multiple returns for one function.
    Maybe I am all wrong here, but I don't see any great advance here.

    I'm sure you are aware of it by now, but there is a name clash between googles 'go' and 'go!', a programming language that had 30 man years in it when you decided to release your product.

    Do the right thing and push your management for a name change in stead of making it worse by putting our more and more content drowning out the original.

    With great power comes great responsibility, and if you own the worlds largest and arguably the best search engine there is no excuse for 'not knowing' about this.

    Make the move, sooner is better.

    @8 and @26: that's what i thought: wirth's revenge (though it's true that pike didn't mind to admit before that he got inspired by wirth's work.)

    Presumably the name "Go" was chosen so they can release a debugger for it called "ogle"...

    (Joke stolen from a commentor on theregister.co.uk)

    Sam, you have issues.

    From http://golang.org/doc/go_lang_faq.html: "Go is mostly in the C family (basic syntax), with significant input from the Pascal/Modula/Oberon family (declarations, packages), plus some ideas from languages inspired by Tony Hoare's CSP, such as Newsqueak and Limbo (concurrency)."

    By Noah Evans (not verified) on 12 Nov 2009 #permalink

    Can somebody explain what's good about multiple return values? In C I can do this:

    val_t func()
    {
    return (val_t){ .ok = true };
    }

    val_t val = func();
    if(! val.ok) {
    // handle error
    }

    So it's basically just a little syntatic sugar.

    @30 Nice joke about Ogle debugger :)

    But speaking seriously it's necessary to try it before starting critic. Go! is not a merely object-oriented language, it declares to become the basic technology in the software system development. It's too complicated area that can prove its effectiveness in huge projects, not in small code listings' considerations.

    'A pointer to a

    CharSetParser
    is a parser; but a
    CharSetParser
    is not!'

    looks very ugly.

    By Sergey Miryanov (not verified) on 12 Nov 2009 #permalink

    How did you do a piece on google's new distributed computing friendly language and leave out any mention of channels or goroutines?

    You basically just cover the syntactic niceness of the language syntax here and none of the power.

    @26:

    Get over the paranoia!

    I looked at Oberon back in the day. And yeah, you're right - as the Go team freely admits, it was clearly an influence on Go.

    But the thing about Oberon is that it wasn't just a language. It was a complete operating system, with its own GUI and windowing system, and its own execution model within that operating system. It was an interesting system - but to use it, you pretty much had to cram yourself into its universe.

    It's pretty much the same problem as Smalltalk: wonderful programming language, but severely constrained by the fact that it lives in its own, separate universe.

    Personally, I haven't had the good fortune to work on a project where I could choose to isolate myself into a custom universe. I've always needed to be able to interface to lots of existing code that just doesn't fit in to the universe of Oberon or Smalltalk. And in both cases, there's no powerful, portable, well-supported standard compiler that allows me to compile Oberon or Smalltalk outside of their universe. In both cases, people did hack together standalone compilers - but they never had the credibility or level of support that a real developer would need to propose using a new language for a real product.

    Rob Pike and the Go team have been greatly influenced by Wirth and Oberon - both in the language design area, and in others. If you look at the work Rob did on windowing systems and programmers editors back at Bell Labs, Acme (which I still think is utterly brilliant) was also strongly influenced by Oberon - it's basically what you get when you try to merge the Plan9 approach to "everything is a file" with the Oberon approach to tools.

    There are two reasons that I think Go has a chance to succeed where Oberon failed:

    (1) It's being supported by Google. Like it or not, having the support of a big company
    provides a language with a lot of credibility. You know that Google isn't going to
    disappear.

    (2) It's got a standalone compiler that runs code using standard calling conventions, with a foreign function interface to allow you to connect it to existing code/libraries without a huge amount of pain.

    What is the measurable benefit of writing code in GO?

    Why another language except for the fact we can make a new language and Google will fund it?

    Can you enumerate quantitative not qualitative and ideological facts that would justify creating GO and anyone bothering to learn GO?

    @39:

    First - I am not a member of the Go team. I don't work on it. And I don't represent Google in any way, shape or form - I'm just a lowly engineer. So take what I say with a grain of salt.

    Why another programming language? Very simple: because someone thinks that the languages we're currently using leave significant room for improvement. That's a sentiment that I agree with wholeheartedly.

    The Go team's arguments for why they designed Go are set out very clearly on their website in the FAQ at golang.org. You can see the reasoning directly from the guys who decided to do it.

    Quantitative facts about programming languages are damned hard to come by. I've yet to see a quantitative study of anything about programming languages that I thought was meaningful. There's so much variation caused by how familiar programmers are, how skilled they are, the specific application that's being used for the test, and a dozen other factors - I don't think that anyone has figured out a way of setting up a realistic quantitative way of evaluating the relative strengths of different languages. Frankly, it
    seems to me to be something rather like asking for a quantitative measure of the quality of literature written in different human languages. Which is quantitatively better for writing great poetry: German or Russian? Can you really, meaningfully answer that question?

    apart from all the criticisms, this language has a couple of very strong points going for it.

    1. It is designed to exploit multi-core Processors, not only by exploiting the available cores but also by threading easily across them and in a very high-performance style. That alone can make it succeed, try doing that with ruby or python. I am not sure about c++ but I doubt it.

    2. Its emphasis is on speed, utter raw uncompromising speed. People buy speed. Its a major selling point.

    3. If you think the compiler is fast now, wait till they re- implement it in GO exploiting concurrent compilation with goroutines.

    4. The Guy who wrote Unix and C is working on it. He's got something of a track record. If he re implements the Unix Kernel in GO and Google open sources it... then anything is possible.

    5. I really like some of the Key Concepts they were thinking about in Plan9. Especially the one that anything can be piped into anything. I think they had it on their minds in the design of GO.

    By anonymous (not verified) on 12 Nov 2009 #permalink

    @13 This code is sounding petulant. Does it own us, or do we own it? Not an insignificant question IMHO.

    C is the programming language. For any software programmer, It is necessary to learn C language. Without it no one can become software programmer. It is the initial step of the programming.

    Adding parametric polymorphism to the language would likely entail A) a more complicated syntax, and B) longer compile times for more extensive type checking. You ask me, I tell you those things would be prices worth paying. Still, this first draft is interesting without them.

    But it's got some ugliness. Some of the ugliness is fixable, and some of it isn't

    Surely it can all be fixed if the designers are willing to break backwards compatibility?

    This could be really cool. On the other hand, TCL was really cool at one time.

    I kind of thought the definition of a systems programming language was manual memory management and pointer arithmetic, but what do I know? Guess they'll still need C or C++ to write the garbage collector runtime.

    No do-while? Considered error-prone in the hands of mere mortals no doubt.

    I really like my parametric polymorphism. I really expect language support for runtime exceptions (in reality, they happen whether or not the language design takes them into account).

    At first glance, this language is looking like yet another dumbed-down garbage-collected extended subset of C++. Not that that hasn't been popular, but it usually goes along with a lot of marketing.

    Look out Google, getting into the language business has been the beginning of the end for many a noble contender.

    BTW the Ogle joke is in the FAQ.

    @45:

    I think that some things, you can't change without dramatically altering the language in a way that conflicts with the language designers goals. Some of the things that I don't like about Go fit into that category. Not many, but a few. (For example, I'm a big type-inference fan. I'd like to have a programming language with full generics, where I don't need to type all of the declarations. That's never going to happen in Go.)

    @Deen #38:

    For-loops are syntactic sugar too.

    <pedant>

    Unless you have a break statement, a continue statement, and an iteration expression in the for loop. Your "replace the for loop with an equivalent while" won't work, then.

    Now, it's probably a bad idea to have all three of those in a single for loop, but that's an argument for a different day.

    :-)

    </pedant>

    By Shawn Smith (not verified) on 12 Nov 2009 #permalink

    I never really used Oberon-2 (only viewed some code samples and overview) nor have I started really looking at Go, so this may be simply answered by reading the docs, but I do have a question regarding the similarities between the two. Is there a feature that Go has that isn't in Oberon-2 or can't be implemented in a somewhat trivial way in that language? and if that is not the case, wouldn't it have been just easier to create an Oberon-2 compiler instead of creating an entire new language?

    @49:

    for and while are *both* syntactic sugar for a set of about 3 carefully constructed

    if (condition) goto label;

    statements. I'm not sure why you grant while special status. It's equally sugary.

    (since you decided to bust out the pedantry. ;-) )

    By Steve Sandvik (not verified) on 12 Nov 2009 #permalink

    Your "replace the for loop with an equivalent while" won't work, then.

    I accept you pedantry and raise you some. I'm not suggesting replacing for loops with while loops at all - while loops are syntactic sugar as well. Your compiler will translate all of them into conditional jumps - goto statements, basically.

    @Steve Sandvik #51 and @Deen #52.

    True, both. Heck, let's just all start writing in machine language again, like real programmers. If numbers are good enough for the computer, they're good enough for humans. No need for that pansy-ass assembly. And where the hell is my front panel, goddammit?!

    :-) :-)

    By Shawn Smith (not verified) on 12 Nov 2009 #permalink

    I have two questions:

    1. How strong is the typing? Haskell strong, C weak or somewhere in between?

    2. How does the concurrency model deal with the fact that Go is a very imperative language where variables will be mutated all over the place?

    Vincent.

    The way map and slice are somewhat special is at least in part reasonable - I'd actually prefer that it was more like Python and had special syntax for map, not just for slice. That said, the way that those two are call by reference while everything else is call by value is a real Yeccch. Hopefully the language doesn't devolve into having the reference/pointer combo disaster that C++ does today.

    For me, the big selling point of Go is that it has queues and threads built into the language (and yes, queues have weird special status too). Python, for example, still is lacking a decent networking library to this day, and that has caused me no end of headaches.

    It still isn't anywhere near mature enough for me to be tempted to play around with it though. Maybe after it gets exceptions and generics.

    Any language that doesn't emanate from Microsoft is all right by me! They only thing they produce with consistency is bad language...!

    Mark,

    Oberon-2 is a language that can (and does) stand on its own independent of any runtime environment. Oberon System is the operating system coded in Oberon-2. They are quite different.

    Consider Modula-2 -- another language which started out implementing its own runtime environment, and eventually running free-standing in a multitude of embedded applications.

    Oberon is no more tied to its host environment than C is to Unix.

    As far as paranoia goes, that it is not. What I expressed is pure anger. Wirth put a lot of work and effort into his languages over the years, and virtually nobody uses them, with the odd occasional use of Modula-2 in embedded environments. Pike comes along and wraps the same basic language in a horrible worse-than-Java syntax, and gets accolades from everybody. What the hell gives? Simply saying it's "inspired by Oberon" isn't enough to give credit where it's really due. (C# and the CLR are also inspired by Oberon, especially since one of the core engineers on the Oberon System moved to Microsoft to work on the CLR and influenced the design of C#) You ask anyone if they'd consider programming in Modula-2 or Oberon today, and the first thing they'll spew forth is, "I would not be caught dead coding in a Wirth-y language."

    Channels and pointers are kind of generic types as well, in addition to maps and arrays. So that's four generic warts.

    I wonder how it can all be folded back into a general generic types system in Go. Might make it in Go 2. Or is it Goto? :)

    By Ori Folger (not verified) on 13 Nov 2009 #permalink

    Sam,

    Would you explain what you mean by saying Go is "EXACT SAME LANGUAGE but with a different syntax" as Oberon-2? From what I have read, the extensible structs and method (procedure) association are the only (although very significant) notable similarity. What else?

    (1) It's being supported by Google. Like it or not, having the support of a big company provides a language with a lot of credibility. You know that Google isn't going to
    disappear.

    Seen much PL/I lately? IBM dominated the computer industry in those days (late 60's) to an extent that Google and Microsoft can only dream of. Heck, they named their operating system "Operating System" and their programming language "Programming Language."

    For that matter, Ada was touted in part because the DoD was going to be around forever. That didn't work out, either.

    By Bob Munck (not verified) on 13 Nov 2009 #permalink

    @62, Boyko. He means it's turing complete, I guess?

    @63:

    Having support isn't sufficient, but it is necessary.

    As for PL/1: by any realistic measure, PL/1 was an immensely successful language. I would guess that there were billions of lines of PL/1 code written. There are still people programming in PL/1 today! It never managed to translate the success in the mainframe world to success in PC development - but that's a very different thing from saying that it wasn't a vastly successful programming language.

    Ada I actually think was seriously harmed by its DOD heritage. Back in college, I did an independent study on programming languages. My advisor forced me to read the Ada language definition and do some programming in it. I was absolutely *shocked*. Like everyone else, I had images of a bureaucratic nightmare of a language. But it's actually a beautiful, well-defined programming language. People used to make fun of the language specification for being so long - but to me, I always wind up contrasting it with C++ - when I was at IBM, I worked on a C++ compiler, and needed to read large parts of the C++ standards document. The difference between the two was striking. The C++ was vastly, vastly longer. The Ada reference was about 500 pages long; the C++ standard was about 700 pages long. I consider them to be roughly equivalent in length. But the striking difference was that in 500 pages, the Ada standard managed to be absolutely precise about the meaning of every construct - including concurrency. Whereas the C++ standard was hopelessly vague - we spent so many hours puzzling over and arguing over the meaning of various parts of it.

    Ada got a bad rap - mainly because the people promoting were a bunch of bureaucratic twits who managed to give it a bad reputation through a combination of petty rules, foolish behavior, and just plain stupidity.

    One last story about Ada: I went to the history of programming languages conference during the 90s. At a panel, the guy who was there to speak about Ada said something along the lines of "All this college and computer science stuff is rubbish; in the military, we take a bright recruit, throw him in a classroom for two weeks, and get an Ada programmer. That's all you need." *That* is why Ada has such a lousy reputation: the people who promoted it had attitudes like that.

    I would guess that there were billions of lines of PL/1 code written.

    Many of them by me, including a WYSIWYG editor for Time-Life magazines that used CICS to store the text. What were we thinking? My BRUIN language was meant to be Dartmouth BASIC with PL/I syntax; we had both an interactive interpreter and a machine-code (/360) compiler for it. I tried to sell it to Bill Gates at a Homebrew Computer Club meeting at SLAC in 1976 or 1977, but he wasn't interested. Jobs and Woz were, but it didn't work out.

    But it's actually a beautiful, well-defined programming language.

    A large number of very bright people put many years of effort into it. Were you aware of the Ada Compiler Validation Capability (ACVC)? It was a large suite of tests of a compiler's conformity to the language standard. Getting your compiler validated was a very big deal. My colleague at SofTech, John Goodenough, managed that development; it was on the order of 50 person-years of effort.

    "we take a bright recruit, throw him in a classroom for two weeks, and get an Ada programmer."

    Argh. Sounds like Col. Whitaker. We told them repeatedly that the way to get an Ada programmer was to take a good software engineer and give him a manual and a compiler. The trouble is that competent software engineers are in short supply and C++ programmers are relatively plentiful. The set of C++ programmers who aren't software engineers command much lower hourly rates than those who are, and that was Ada's downfall. Defense contractors couldn't find enough Ada programmers or people they could train for low enough salaries, so they started demanding waivers from Ada.

    the Ada standard managed to be absolutely precise about the meaning of every construct - including concurrency.

    Thanks. I wrote the first draft of the ARM concurrency section.

    By Bob Munck (not verified) on 14 Nov 2009 #permalink

    Given what you said above about Ada, I'd like to mention what I see as a possible failing in Go. This was triggered by your comment that Go had little or no redundancy.

    In the Ada development, a lot of effort was put into making the code readable. There were a lot of write-only languages at the time, like APL, and we thought that was bad. This has been born out since then; code reading and review may be the nearest thing to a silver bullet that we have.

    Go appears to be a language written by programmers for programmers; the criteria applied to its design were mostly from the point of view of the person writing code, not the people who would later read it and modify it. From some things you've said or hinted, it may be worse; Go may be a language designed by compiler programmers for programming compilers. PARC's MESA was a fairly good language, but suffered from that syndrome.

    To produce readable, easy-to-modify, maybe mission- or life-critical programs, the code has to be easy to read and understand. That is, in my opinion, much more important than it being easy or fast to write.

    COBOL had the right idea, especially considering how long ago it was defined. You have to consider the entire life of a program, not merely its gestation and birth. Likewise you have to consider the corporate environment in which that program will live, grow, change, and die. That means you have to worry about the understandability of the code.

    By Bob Munck (not verified) on 14 Nov 2009 #permalink

    @56 Except Go doesn't really offer support for writing kernel code. Unix redux would still be C and ASM instead of Go and ASM.

    I would prefer a language with haskell's strong typing, type system, and type classes but with opt-in control over the low level structure of types (essential for kernels). Design the language to be highly GC friendly and you'll have a language that you could scale from kernel development to application software.

    My initial response was that the syntax looks weird. It seems a lot of thought went into the technical side of things but not necessarily into usability/human factors which is a shame. In particular it seems that you'd use () in some cases where C/C++ would use {} which I think a lot of programmers are going to find confusing. There's also := and a bunch of other syntax that looks weird to me. It seems like this weird C/Pascal/Python mixture which can't quite do what C or Python can. Maybe it is something that grows on you but it looks like the emphasis was on something a compiler can read rather than a human.

    Fast compile times are very important but if the code is hard to read and write (which it seems to be) that would be the bottleneck. You really want a human friendly expressive language with all the safety features and a fast compiler. Maybe this will create the motivation for someone like Microsoft to address some performance issues in their tools.

    There are definitely some cool features though. I like the interface concept and even the separation of methods from the data may have something going for it (though I guess it means there's no construction and destruction which are useful concepts). I would prefer a mechanism more like C++ classes but with a "Python" twist where if two classes implement the same method they can be polymorphic with respect to this method. In C++ you can accomplish the same deal with multiple inheritance (and with templates in compile time) but it's ugly and has issues so it really hasn't scaled well.

    Would be interesting to see how this fans out.

    Your argument, and the arguments of every other person so far about exceptions are not valid. Go does not have exceptions, which means it does not perform stack unrolling for any error operations. Stack unrolling is bad. (Yes, that was a period.)

    You seem to think that exception handling is done inside the language compiler, but it isn't. They don't unroll the stack to make the "ok" variable (as you named in your code above).

    Other people seem to think that exceptions occur whether the language defines them or not. No, that is NOT the case. Hardware exceptions and language exceptions are 2 VERY DIFFERENT things! Hardware exceptions merely map to a function call from a table of pointers (the Interrupt Vector Table, for those who used X86 parlance). They do NOT involve unrolling of the stack unless your compiler hooks them, and makes them do that sort of horrible thing!

    Also, templates, generics, whatever you want to call them, are not necessary. The reason that they are necessary in C++ is that sometimes you have to know how big an object is in order to make a class that uses it as a member somewhere. For example, in a stack class, which I'm assuming everybody here understands, one would have to know how many bytes the object that would be on this stack takes up in order to have an array of them that is sequential in memory. However, one could also argue that a stack of pointers is sufficient for any type, but not type safe. Perhaps all that we need is interfaces as first class values, and not generics or templates after all. Generics and templates are pre-processor concepts anyway; it seems that Go is trying to avoid that sort of thing. Because they are pre-processor concepts, they make a new copy of the functions, or types when they are given concrete values; therefore, generics/templates bloat your binary at the benefit of type safety.

    By Anonymous (not verified) on 16 Nov 2009 #permalink

    Other people seem to think that exceptions occur whether the language defines them or not.

    they do. you're talking about the technical means used to recognize and deal with exceptions, and those can indeed vary quite a lot. but exceptional conditions in program execution due to errors or odd runtime causes such that program flow has to be diverted into some sort of unusual --- indeed, exceptional --- error-handling path will happen regardless of what method you use for the diverting.

    Also, templates, generics, whatever you want to call them, are not necessary.

    nothing is necessary apart from machine code. metaprogramming --- which is what templates, generics, and good macro systems get used for --- is a really nice concept to have around once you get far enough away from the bare metal, though. after all, you don't need higher-order functions either, but they're damn fine things to have on tap.

    By Nomen Nescio (not verified) on 16 Nov 2009 #permalink

    Dammit! now it's going to be even harder for people doing a search for my favorite game.

    Also while you can't overload operators they have overloaded the + operator for string concatenation. Yes its become fairly commmon practice to do this these days but it is still operator overloading. And if you do it for strings then why not for other arrays?

    Yes personally I'd prever not to have it at all. Have cat as a predefined function that takes any number of arguments instead.

    The problem I have with the "we'll fix it later" approach to parametric types is that this almost always results in a system that's harder to understand, harder to get right and, most importantly, LOOKS like an afterthought.

    The temptation will always be there to implement something that doesn't break too much existing infrastructure rather than something that is actually useful.

    By Pseudonym (not verified) on 17 Nov 2009 #permalink

    Syntactic sugar sometimes make the whole difference. It seems Go would leave the possibility open to catch up only the first return value, explicitly by doing a, _ = two(1,2) and imagine two being a really interesting function of which sometimes only the first value is important. Perhaps also an implicit a = two(1,2) could be allowed to compile, but with giving a warning at some point.

    Thanks for the review.. it sounds like an interesting language.

    Out of idle curiosity, can "go" simplify multi-core programming? I've seen a lot of interest in minimizing side-effects, as is done in the functional languages, and would appreciate your opinion.

    Mark, you misunderstand the reference type/make thing, as do most people. It's the Go folks' fault for describing it so badly.

    Think of a slice astype Slice struct { ptr *T; begin, end int }And think of "make([]int, 20)" as a call to a function "slice.Make(20)" that returns a Slice. With regard to memory, the so-called "reference types" can be described in the language, and there is no call-by-reference, only call-by-value. What the designers have given themselves with these types is genericity and some syntactic sugar (and pointer arithmetic in the case of slices), but nothing special from a memory or calling-convention viewpoint.

    By Jonathan Amsterdam (not verified) on 30 Nov 2009 #permalink

    Okay, late to the game, I know...

    Over on Greg Laden's article on this, I pointed out that the problem with Go is not a technical one but a marketing issue. Go, for better or for worse, has a lot in common with Alef, Bell Labs' original systems programming language for Plan 9 (and given Pike and Thompson's involvement, that isn't exactly surprising). Alef wasn't even successful within the Plan 9 environment (although the language Limbo, a derivative used in the Inferno operating system, still gets some use), even though it was demonstrably superior to C in many ways. Apple's Dylan, though a Lisp derivative, suffered a similar fate, only in its case never even really getting off the ground.

    It's the Esperanto problem -- just how many languages can you fit into a specific market niche, and will significant architectural or semantic improvements really make any difference in uptake? It seems pretty safe to say that Objective-C only hangs in there because of Apple's iron-fisted insistence on developers porting to Cocoa, Ada is a marginalized and dying language (even if it isn't as awful as its reputation)... long story short, there's a lot more of these languages that are legacies than are used in actual development.

    I'm not saying Go will be a failure, but it's going to have to make quite the splash to create any demand.

    Sam:

    Pascal was a fiasco that so far has outlived its usefulness by well over 20 years; if you've never read Brian Kernighan's screed about Pascal, it still applies today, especially the standardization issues. (Everything else about the language can be dealt with except for that; Pascal has some serious fragmentation problems.) Modula-2 is often too strict and marginal at best; Modula-3 is a nonentity; the problems with Oberon have already been covered. Your screed about Wirth somehow being disrespected is not only borderline-insane, but fails to acknowledge that he did receive credit as an influence, and shows that you have absolutely no idea how software design (or, for that matter, science) works.

    Wait a minute. So if I happen to have a type that implements methods foo() and bar() and then someone adds an interface based on foo() and bar(), suddenly my type implements the interface? That's not right.

    By Paul C. Anagno… (not verified) on 06 Dec 2009 #permalink

    why would that be wrong, Paul? presumably your API documentation would state which interface(s) you had meant to implement, thus preventing confusion; does there really need to be a statement of that intent in a compiler-readable format as well?

    if so, how far should we take matters --- should interfaces be version-numbered, too, with our code specifying which version(s) of the interfaces they are intended to implement, and interfaces specifying which versions are meant to be backwards/forwards compatible with each other?

    at some point, duck typing becomes the better idea by simply letting humans make decisions best fit for human judgment to handle. seems like Go's interfaces could be considered a thin veneer of specification on top of duck typing, which doesn't look obviously wrong to me.

    By Nomen Nescio (not verified) on 07 Dec 2009 #permalink

    Yes, there really needs to be a statement of intent in the program, too. Otherwise I might have an old type that just happens to include methods foo() and bar(), and then suddenly someone decides those are the two functions for an interface. Now a third person thinks my type implements the interface, when in fact foo() and bar() have nothing to do with it.

    Surely you're not suggesting that an existing interface should be updated in an incompatible manner?! That would be DLL Hell all over again.

    By Paul C. Anagno… (not verified) on 08 Dec 2009 #permalink

    but, Paul, all the mistakes you are worried might be committed here are ones committed by people. if a note in the human-readable API documentation is not enough of a clue to prevent them from making such a mistake, why should a note in the machine-readable specs do the job any better? aren't you just asking people to ask the machine to do their job for them?

    conversely, aren't you expecting a machine to do a human's job (that of knowing what an "interface" specification should mean) to a considerable extent here, and arguably to an extent great enough that human intelligence might be the best tool to use instead?

    if this path really led to DLL hell, i'd expect Python's duck typing to be most of the way there by now, but it doesn't seem to be. (don't get me started on monkey-patching, though. that's over the line even by MY standards.)

    By Nomen Nescio (not verified) on 09 Dec 2009 #permalink

    Which mistake are you talking about? The one where someone creates an interface without checking to be sure that no types anywhere in the world implement it yet, or the one where everyone forgets to check some documentation and thus notice that the old type wasn't implementing the new interface? You can shoot yourself in the foot two different ways here.

    I'm a Lisp guy, so I guess I shouldn't object to this. But when you include a formal interface mechanism in a statically-typed language, it seems to me that the compiler should catch this.

    By Paul C. Anagno… (not verified) on 13 Dec 2009 #permalink

    A2 (nee' Bluebottle, formerly AOS) is an operating system written in Active Oberon: http://www.bluebottle.ethz.ch/ . There is an embedded version which runs on Windows. I wrote a realtime voxel raytracer in it. I still miss the Native Oberon desktop -- A2 has a new UI, which doesn't use the mouse chording that NO users loved. Google should have ported AO and used it as the basis for Chrome. Now that would have been slick.

    http://www.youtube.com/user/xenopusRTRT

    By Soren Renner (not verified) on 20 Dec 2009 #permalink

    Interesting overview. Sounds a lot like CLU.

    By Uncompetative (not verified) on 03 Jan 2010 #permalink

    Another hype type of language similar to ruby.

    I see some things I really like about Go, especially in the area of concurrency, but some things I don't like at all. One thing that I see as really shortsighted is making visibility a lexical dependency. When designing code I tend to start out making methods private, and only when it becomes apparent that they need to be visible do I change them to public. This way I only expose the minimum methods on an as-needed basis. However, with the lexical dependency, I'll need to change every reference in the module instead of a single keyword. To make this dependency part of the language just to eliminate a single keyword seems to be a unecessary tradeoff. Once good tooling support is available with robust refactoring maybe this won't be such an issue.

    By Dean Horak (not verified) on 28 Feb 2010 #permalink

    This could be really nice.

    Generally this language is looking like yet another dumbed-down garbage-collected extended subset of C++.

    Hopefully the language doesn't devolve into having the reference/pointer combo disaster that C++ does today.

    But it's important to try it before starting critic as Go! is declared to become the basic technology in the software system development.

    My dislikes:

    1. Syntax: Either make it "C"ish or "Pascal"ish, but not
    both.
    2. Readability: Restricted to the author of the code
    3. Export: Capitals as export marks don't stick out.
    See point 2.
    4. Structural interface/record concordance: Danger of sudden
    feature acquisition (cf message 79)
    5. No clear distinction between value and reference types.
    Yet another hell for the occasional reader of a program.

    I think program readability is an important point.

    By dirk muysers (not verified) on 16 Mar 2010 #permalink

    i think a good language for system analysts ,not for everyone as it works good formaking big s/w.

    Which mistake are you talking about? The one where someone creates an interface without checking to be sure that no types anywhere in the world implement it yet, or the one where everyone forgets to check some documentation and thus notice that the old type wasn't implementing the new interface? You can shoot yourself in the foot two different ways here.

    I'm a Lisp guy, so I guess I shouldn't object to this. But when you include a formal interface mechanism in a statically-typed language, it seems to me that the compiler should catch this.

    Okay, late to the game, I know...

    Over on Greg Laden's article on this, I pointed out that the problem with Go is not a technical one but a marketing issue. Go, for better or for worse, has a lot in common with Alef, Bell Labs' original systems programming language for Plan 9 (and given Pike and Thompson's involvement, that isn't exactly surprising). Alef wasn't even successful within the Plan 9 environment (although the language Limbo, a derivative used in the Inferno operating system, still gets some use), even though it was demonstrably superior to C in many ways. Apple's Dylan, though a Lisp derivative, suffered a similar fate, only in its case never even really getting off the ground.

    It's the Esperanto problem -- just how many languages can you fit into a specific market niche, and will significant architectural or semantic improvements really make any difference in uptake? It seems pretty safe to say that Objective-C only hangs in there because of Apple's iron-fisted insistence on developers porting to Cocoa, Ada is a marginalized and dying language (even if it isn't as awful as its reputation)... long story short, there's a lot more of these languages that are legacies than are used in actual development.

    I'm not saying Go will be a failure, but it's going to have to make quite the splash to create any demand.

    Sam:

    Pascal was a fiasco that so far has outlived its usefulness by well over 20 years; if you've never read Brian Kernighan's screed about Pascal, it still applies today, especially the standardization issues. (Everything else about the language can be dealt with except for that; Pascal has some serious fragmentation problems.) Modula-2 is often too strict and marginal at best; Modula-3 is a nonentity; the problems with Oberon have already been covered. Your screed about Wirth somehow being disrespected is not only borderline-insane, but fails to acknowledge that he did receive credit as an influence, and shows that you have absolutely no idea how software design (or, for that matter, science) works.

    @27: either you're joking, or it was tl;dr.

    1- Go pointers != C pointers. Go is as memory-safe as Java; it's impossible to access an invalid memory address, or do pointer arithmetic, or write to a pointer like it's an int. Maybe "reference" would've been a better name for this language construct.

    2- Go interfaces != Java interfaces. In Java you must explicitly say class A implements interface B. In Go, a class A automatically implements the interface B if the set of A's methods is a superset of B's methods. The flexibility of duck typing with the type safety of Java.

    3- Go struct == C struct, but being able to define methods for any type means there is no need for a separate "class" keyword. Sorry but your idea of what constitutes OO is completely wrong.

    Naysayers can say "Java already has X", "Modula already has Y" or "Oberon already has Z" but the fact is there's not really a language combining X, Y and Z before now. Sounds like http://en.wikipedia.org/wiki/Simpsons_Did_It to me. Which is not to say that Go has everything, far from it; no language could ever be a "one size fits all" killer language; a programmer covering several problem areas will always need a multiplicity of languages, but IMO Go is one of the better ones (this coming from a coder with a C/C++/Java/Perl/Ruby background). With "IMO" being the operative term, because a major part of choosing a language does boil down to simple sylistic preference.

    And if Go borrows ideas from a language of which you are fond, that should improve your opinion of Go, not diminish it. See also http://c2.com/cgi/wiki?HaveThisPattern

    For the record I do dislike the initial-capital-means-public and the asymmetry of ad hoc genericity of arrays and maps.

    And its OO model does have the propensity for producing write-only code, limiting the domain of problems for which Go is suitable; that one is forgivable, however, as long as you don't try to apply Go to a problem for which it's not suited. It means that Go is applicable to a whole other family of problems to which many of its competitors are not.

    @93:

    Your point one isn't entirely correct. Go *does* allow you to do things like cast pointers to integers - but in order to do so, you need to explicitly import the "unsafe" module. So when you really need to get to low-level bit-twiddling, you can do it. But it's the kind of thing that you should almost never need to do - and so you need to go out of your way to make it possible.

    @94 Thanks for the correction, that's useful to know.

    Another botheration that I forgot to mention: Go does automatic semi-colon insertion at the end of each line if the line could form a syntactically valid complete statement. Therefore this:

    if foo
    {
      bar;
    }

    Is equivalent to this:

    if foo;
    {
      bar;
    }

    i.e. "evaluate foo and ignore it, then do bar unconditionally."

    Forcing you to put the '{' on the same line as the 'if'. Ugh.

    Is "varName type" a common thing in programming languages that have static typing (such as C/++ (int myVar = 3), not like PHP ($myVar = 3))? It doesn't seem that way (from the quick check I did on Wikipedia), so why would they do something contrary to what nearly everyone is used to? That's just going to make it harder for anyone who has done any programming (in, ie: C/++, C#, Java, etc) before to learn ("damn I did 'int x' again!") it seems. Granted, I haven't done extensive research on this, but from my initial check, this seems to be the most common version of statically typed languages.