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
}

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
}

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 weredeclared 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 Color = iota
  YELLOW  Color = iota
  GREEN Color = iota
  BLUE Color = iota
  INDIGO Color = iota
  VIOLET Color = 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 Color = 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. (Addendum 2011: I’ve used Go a whole lot since I wrote this… and at this point, I absolutely love Go. It’s become one of my favorite languages. It’s just so much fun to program in. Yeah, it’s got its blemishes – but it’s a delight to work with.)

    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.

  • 97 thoughts on “Google's New Language: Go

    1. Peter

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

      Reply
    2. James H G Redekop

      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.

      Reply
    3. Russell

      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.

      Reply
    4. Mark C. Chu-Carroll

      @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.

      Reply
    5. Deen

      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.

      Reply
    6. Rodrigo Monteiro

      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.

      Reply
    7. Comrade PhysioProf

      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?

      Reply
    8. Mark C. Chu-Carroll

      @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.

      Reply
    9. John Armstrong

      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?

      Reply
    10. Mark C. Chu-Carroll

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

      Reply
    11. Janne

      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?

      Reply
    12. Mark C. Chu-Carroll

      @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.

      Reply
    13. Mark C. Chu-Carroll

      @17:
      Oops, my apologies. For some stupid reason, I’ve always confused Ken Thompson and Dennis Ritchie.

      Reply
    14. Mark C. Chu-Carroll

      @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.

      Reply
    15. Anonymous

      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;
      }

      Reply
    16. Mark C. Chu-Carroll

      @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!

      Reply
    17. Colin Curtin

      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 …

      Reply
    18. Paul Clapham

      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?

      Reply
    19. Avi Steiner

      @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.

      Reply
    20. Sam

      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$#!+.

      Reply
    21. Olivier

      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.

      Reply
    22. Jacques Mattheij

      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.

      Reply
    23. Jochen

      @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.)

      Reply
    24. MarkW

      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)

      Reply
    25. Noah Evans

      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).”

      Reply
    26. Devin

      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.

      Reply
    27. Itransition developer boy

      @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.

      Reply
    28. Tim

      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.

      Reply
    29. Mark C. Chu-Carroll

      @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.

      Reply
    30. Jawahar

      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?

      Reply
    31. Mark C. Chu-Carroll

      @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?

      Reply
    32. anonymous

      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.

      Reply
    33. green tea

      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.

      Reply
    34. j h woodyatt

      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.

      Reply
    35. amk

      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?

      Reply
    36. Marsh Ray

      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.

      Reply
    37. Mark C. Chu-Carroll

      @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.)

      Reply
    38. Shawn Smith

      @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>

      Reply
    39. Ram

      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?

      Reply
    40. Steve Sandvik

      @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. 😉 )

      Reply
    41. Deen

      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.

      Reply
    42. Shawn Smith

      @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?!
      🙂 🙂

      Reply
    43. Vincent Foley

      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.

      Reply
    44. Bram Cohen

      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.

      Reply
    45. IanW

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

      Reply
    46. Sam

      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.

      Reply
    47. Sam

      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.”

      Reply
    48. Ori Folger

      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? 🙂

      Reply
    49. Boyko

      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?

      Reply
    50. Bob Munck

      (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.

      Reply
    51. Mark C. Chu-Carroll

      @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.

      Reply
    52. Bob Munck

      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.

      Reply
    53. Bob Munck

      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.

      Reply
    54. Jesse

      @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.

      Reply
    55. Guy

      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.

      Reply
    56. Anonymous

      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.

      Reply
    57. Nomen Nescio

      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.

      Reply
    58. Konrad

      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.

      Reply
    59. Pseudonym

      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.

      Reply
    60. Simon B.

      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.

      Reply
    61. dja

      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.

      Reply
    62. Jonathan Amsterdam

      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.

      Reply
    63. Brian X

      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.

      Reply
    64. Paul C. Anagnostopoulos

      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.

      Reply
    65. Nomen Nescio

      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.

      Reply
    66. Paul C. Anagnostopoulos

      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.

      Reply
    67. Nomen Nescio

      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.)

      Reply
    68. Paul C. Anagnostopoulos

      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.

      Reply
    69. Soren Renner

      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

      Reply
    70. Dean Horak

      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.

      Reply
    71. Tenax software developer

      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.

      Reply
    72. dirk muysers

      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.

      Reply
    73. ajit

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

      Reply
    74. sasa

      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.

      Reply
    75. sasa

      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.

      Reply
    76. Oktalist

      @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.

      Reply
    77. Mark C. Chu-Carroll

      @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.

      Reply
    78. Oktalist

      @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.

      Reply
    79. NightKev

      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.

      Reply

    Leave a Reply to dirk muysers Cancel reply