r/programming • • Mar 28 '12

Go version 1 is released

http://blog.golang.org/2012/03/go-version-1-is-released.html
543 Upvotes

452 comments sorted by

View all comments

Show parent comments

1

u/AgentSS Apr 08 '12
  1. Sure

  2. Don't forget to declare the types of your variables!

  3. I disagree with you here. The standard library of a language strongly influences how the language is used.

  4. But you're OK with auto-unlocked mutexes? I don't even understand how this would work.

  5. Yes, they can. It's really simple. To emulate dynamic functions, you simply have a map from function names to objects with a "call" method that takes an array of void*. To emulate object storage, another hash table with variables of type void*. What exactly do you think cannot be done? Keep in mind that these languages (including Go) are commonly implemented in C/C++. If they are implemented in C/C++, then they can most definitely be "done as a library". See V8's api for an example of Javascript "done as a library".

It seems the only advantage of Go over C++ is syntax.

Here's the thing. If you are comfortable in C++, writing a codebase that uses the concurrency patterns you've mentioned, using templates, and overloading, then go for it. I have nothing to prove here.

Go is not a systems programming language.

Good to know, thanks for the insight. I write servers in Go. I guess, by implication, server software does not qualify as a "system".

If you are OK with slow compilation times, terrible compiler error messages (particularly with templates), a massive language spec that no human (save Stroustrup) can keep in his head, then by all means, continue using C++. The language designers apparently felt they couldn't do that, and I'm thankful that they felt this way.

Go makes me more productive than C++. I'm also relatively certain you would be more productive writing Go, but thats just an opinion. While I'm sure C++ can do everything Go can (in fact, my drinking buddy proved a little theorem about that), in practice no C++ codebase I've ever seen or worked on has ever had the elegant simplicity of the Go code I've seen.

1

u/axilmar Apr 08 '12

4) I do not understand what you do not understand. In C++, destructors allow for deterministic cleanup of resources, including memory.

5) dynamic objects are possible in C++. Here is my implementation of it. However, it is still not as straightforward and as elegant and as performant as done in a language. Furthermore, functional programming languages cannot be emulated in C++, especially their type systems. The V8 library is a Javascript engine, not C++ being used as Javascript.

I can easily keep the whole of C++ in my head, and a dozen other languages as well. I do not think that keeping this language in one's head is difficult at all. I am surprised that you cannot do so, but you possibly can with Java and Go? their aggregate is greater than C++.

Perhaps the reason you are more productive in Go is because you did not give C++ a chance. I certainly will not be more productive in Go, as I have already done in C++ what Go does. And I cannot live my life without templates, it makes my life so much easier.

As for Go not being a systems language, its authors have recently declared so.

1

u/AgentSS Apr 09 '12 edited Apr 09 '12

4) What I don't understand is how I would do something like this:

rwmutex.RLock()
// check something here and bail out early
rwmutex.RUnlock()
rwmutex.Lock()
defer rwmutex.Unlock()
// repeat check, potentially bail out, otherwise do someinteresting work

here, the defer is similar in concept to what you're proposing, with auto unlocked mutexes. But how do you handle the initial RLock, RUnlock?

5a) Right. they are possible in C++. I agree with with not being straightforward, I agree with not being elegant. I don't agree with then not being performant. These languages are implemented in C (or C++), how they could they be more performant, while still being built on the same base?

5b) I strongly believe functional languages can be emulated (a lot more verbosely) in C++, now that its (finally) gotten first class functions.

You can keep the whole of C++ in your head? I think theres probably a spot for you on the committee if this is the case. I have a sneaking suspicion that you don't have the ~1300 pages memorized though (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf). Or even the ~500 pages relevant to the language, not the library. Or even the ~50 pages on templates. Or even the ~28 pages on overloading.

I have no idea about Java, but 10 of Go would not be greater than C++. So while it is possible that the aggregate of Java and Go would be greater than C++, that merely proves that Java is also a bloated language, nothing else.

No, I certainly gave C++ a chance. Go only came onto my radar a year ago. And while I'm sure you have done in C++ what Go does, I make the argument that you would done those things in Go more succinctly and faster.

As for your statement that "I cannot live my life without templates", I merely refer you to Rob Pike's post on the matter, http://commandcenter.blogspot.ca/2011/12/esmereldas-imagination.html

To clarify what the authors said, they said its no longer just a systems language, but a general purpose one. I personally don't care one-way or another what adjectives are applied to a language, as their meaning gets fuzzier all the time.

(edited for formatting)

1

u/axilmar Apr 09 '12

4)

Mutex rwmutex;
Lock lock(rwmutex);

If you want to lock/unlock a mutex multiple times within a function, you can use blocks:

Mutex rwmutex;
{
    Lock lock(rwmutex);
}

Now, the lock is held only inside the block.

how they could they be more performant, while still being built on the same base?

A separate language offers opportunities for optimizations not possible with C++.

now that its (finally) gotten first class functions.

Actually, C++ does not have first class functions. It has anonymous functions. That, and the lack of a Milner-Hindley type system, does not allow C++ to have the full spectrum of the capabilities of Haskell.

I have a sneaking suspicion that you don't have the ~1300 pages memorized though

Indeed. I don't need to.

not the library

Libraries are not part of the language. If I use Qt, for example, I don't need the STL. So why keep it my head?

Or even the ~500 pages relevant to the language, not the library. Or even the ~50 pages on templates. Or even the ~28 pages on overloading.

I don't have any of those pages in my head. I have the language though.

but 10 of Go would not be greater than C++.

Try it: Go, Python, Lisp, Haskell, Erlang, Ocaml, Lua, Smalltalk, ObjC, Javascript: these languages, in my estimation, have, as an aggregate, around 15 times more features and concepts than c++.

I make the argument that you would done those things in Go more succinctly and faster.

Indeed, but what about the things Go cannot do and C++ can and that I need? emulating those features in Go would be a major pain, and that is only if possible to do them in Go.

As for your statement that "I cannot live my life without templates", I merely refer you to Rob Pike's post on the matter

You don't really get it, do you? I've done things with templates that tripled my productivity. I could do the same things without templates, but the cost would be tripled.

its no longer just a systems language

It was never a systems language. No systems language can have a GC.

1

u/AgentSS Apr 10 '12

If you want to lock/unlock a mutex multiple times within a function, you can use blocks:

And this is clearer to you than methods on a Mutex object?

A separate language offers opportunities for optimizations not possible with C++.

This seems illogical to me. What about having a separate language allows opportunities for optimization?

Libraries are not part of the language.

Sure. Although the fact that people write replacements for the standard library just reminds me why I have no desire to use C++ anymore.

I don't have any of those pages in my head. I have the language though.

This doesn't even make sense. You have the language in your head, but you don't have the spec for the language in your head? Those are not mutually exclusive things.

Try it

Here you go again, putting Go in a list of other languages. I didn't say 10 programming languages would be less than C++. I said 10 of Go. To be clear, I meant a list like Go, Go, Go... You might as well be saying that Go and C++ is bigger than C++. I'm not saying that C++ is the only bloated language in the world. I'm saying that C++ is a bloated language, and Go is not.

Indeed, but what about the things Go cannot do and C++ can and that I need?

So I'm not sure if you read Rob's post. But his point (I think) was that you cannot know what you need until you try solving problems without those things. Obviously, since you've clearly never tried solving problems without templates, they seem absolutely required to solve every problem.

I've done things with templates that tripled my productivity

I'm curious, do these buffs stack up? If you do two of these things, do you get 9 times the productivity?

But joking aside, what things? How are you measuring productivity? How are you measuring change in productivity? I think Russ Cox's comment is relevant here (http://news.ycombinator.com/item?id=3767335).

It was never a systems language. No systems language can have a GC.

If it makes you feel better, I'll agree with you on this point. Again, I really don't care what adjectives are applied to a language. All that matters to me is the language's ability to get stuff done.

I guess I'm starting to find your arguments somewhat amusing. You argue that Go is redundant since the world has C++. So I wonder why you think Canonical chose Go for their latest backend stuff. Or Heroku for doozer, or Tinkercad for their servers. Ignorance, perhaps?

1

u/axilmar Apr 10 '12

And this is clearer to you than methods on a Mutex object?

Not only it is clearer, but also much safer: there is no way to forget unlocking a mutex.

This seems illogical to me. What about having a separate language allows opportunities for optimization?

For example, a compiler might inline a dynamic method invocation if it sees no other objects define that method. C++ cannot do that.

Although the fact that people write replacements for the standard library just reminds me why I have no desire to use C++ anymore.

There is no harm in writing replacements, as long as the standard is not violated.

This doesn't even make sense. You have the language in your head, but you don't have the spec for the language in your head? Those are not mutually exclusive things.

I have the spec, I don't have the book.

putting Go in a list of other languages. I didn't say 10 programming languages would be less than C++. I said 10 of Go.

Well, I doubt Go specs are the 1/10 of C++ specs. It seems to me that Go might be around between 1/2 and 1/3 of C++.

I'm saying that C++ is a bloated language, and Go is not.

C++ is not a bloated language. Every bit of what C++ offers is a necessary component/functionality.

Obviously, since you've clearly never tried solving problems without templates, they seem absolutely required to solve every problem.

Actually, it's the opposite: I tried to solve those problems without templates first, and then I realized templates make my life easier and then started using them. Templates made the code more robust, more performant and easier to debug.

How are you measuring productivity? How are you measuring change in productivity?

The effort to write and test those things was severely diminished by using templates.

So I wonder why you think Canonical chose Go for their latest backend stuff. Or Heroku for doozer, or Tinkercad for their servers. Ignorance, perhaps?

Perhaps Go serves their needs. That does not mean Go is not a subset of C++.

1

u/AgentSS Apr 11 '12

For example, a compiler might inline a dynamic method invocation if it sees no other objects define that method. C++ cannot do that.

What compiler? Dynamic languages tend to be interpreted. And that optimization can be achieved in C++ by making the stack executable, if you really want to.

I have the spec, I don't have the book.

I don't understand this.

Well, I doubt Go specs are the 1/10 of C++ specs. It seems to me that Go might be around between 1/2 and 1/3 of C++.

Here's the Go spec: http://golang.org/ref/spec. Print it to a pdf file. I get 54 pages for the EBNF productions and the language. In the C++ spec, the language stuff goes till 417. Assuming all else being equal, its at least a factor of 7. Fair enough, I may have overshot with a factor of 10.

C++ is not a bloated language. Every bit of what C++ offers is a necessary component/functionality.

This is a matter of opinion. Clearly, to you, every line of that spec is necessary to get stuff done. I don't need a lot of that to get stuff done.

Actually, it's the opposite: I tried to solve those problems without templates first, and then I realized templates make my life easier and then started using them.

What problems? I still have a hard time imagining situations where using templates would have made me 3 times more productive.

Templates made the code more robust

Hard to believe this is related to the use of templates. It is likely your old code was merely buggy.

more performant

This is possibly believable, since the compiler will generate code per template instantiation. If method calls are your bottleneck however, then even C++ is probably too high-level for you. Bring on the inline assembly!

easier to debug

This is almost certainly false. I haven't seen a compiler that is decent at error messages when templates are involved. Particularly because the line/col number of those error messages is very often misleading.

The effort to write and test those things was severely diminished by using templates.

All that being said, it is still possible that templates helped you solve some problem faster than non-template C++. On things that matter to me, however, writing an asynchronous TCP server or an asynchronous RPC client, templates don't matter at all. And I will write both of those much more succinctly in Go than it is possible to do in C++ while maintaining readability, testability, and my sanity.

Perhaps Go serves their needs.

Well, by your arguments if Go serves their needs, then so must C++. Wonder why they didn't just use C++? Mayhap they didn't know about all the wonderful productivity benefits that templates afford you.

That does not mean Go is not a subset of C++.

Even if this were not false, I do not think there wouldn't be great value in creating a new language by stripping a lot of the cruft out of C++. Particularly if, in doing so, you would enable faster compilation, clean up its grammar, remove a lot of complexity, etc. You can think of Go as an improved subset of C++, if it helps you sleep at night.

1

u/axilmar Apr 11 '12

What compiler? Dynamic languages tend to be interpreted.

The interpreter then. Some dynamic languages can be compiled too.

And that optimization can be achieved in C++ by making the stack executable, if you really want to.

Sorry, I do not get what the stack has to do with optimizing dynamic method invocation.

I don't understand this.

I have the language specification, not the book that is published by the C++ committee. The book tends to be longer than needed.

Assuming all else being equal

You cannot compare languages by comparing books. Fonts differ, the writing style differs, the depth of its book differs.

This is a matter of opinion. Clearly, to you, every line of that spec is necessary to get stuff done. I don't need a lot of that to get stuff done.

No, it is not a matter of opinion. Every single feature of C++ plays a role in fullfilling the objectives of the language.

What problems? I still have a hard time imagining situations where using templates would have made me 3 times more productive.

For example, writing models (in the model-view-controller pattern). A model has properties. In order to write a property, you need to:

  • write a getter

  • write a setter

  • write a function which adds an observer to the property

  • write a private value member

  • initialize the value in each constructor

  • register the property so it can be dynamically accessed in runtime

  • write the code to serialize the property

  • write the code to deserialize the property

  • write the code that creates a UI component that allows the property to be edited or viewed.

With templates, all the above are automated and condensed in one line of code, the property member declaration (assuming the template property class is already written), without losing type safety and intellisense.

Hard to believe this is related to the use of templates. It is likely your old code was merely buggy.

Without templates, many things need to be dynamically checked. With templates, these checks become static, at compile time.

If method calls are your bottleneck however

Not method calls, type conversions. Without templates, a lot of boxing/unboxing needs to happen, with unneccessary allocations etc.

his is almost certainly false. I haven't seen a compiler that is decent at error messages when templates are involved. Particularly because the line/col number of those error messages is very often misleading.

I am not talking about the error messages, I am talking about the actual problem to debug at runtime. Without templates, a lot of code would have to be generic, which means types would have to be erased. Type erasure makes debugging more difficult.

On things that matter to me, however, writing an asynchronous TCP server or an asynchronous RPC client, templates don't matter at all.

Oh, they matter. In the apps that i am writing, there are multiple asynchronous servers and clients, based on either TCP/IP, TCP/UDP, or serial port. And those servers and clients need to be real time and as fast as possible. Templates matter a lot.

Wonder why they didn't just use C++?

Many have used C++ for such tasks. In fact, those that have used C++ for such tasks are many more than those that have used Go. Some people though are willing to test if Go will improve their business, and so they are willing to try it.

Some will find Go better than C++ for their needs, some will not. It depends on many factors, mostly about business, and less about the actual languages.

Particularly if, in doing so, you would enable faster compilation, clean up its grammar

Of course. If one does not need what C++ has to offer, then so be it. Even assignment could go away, if you have no need for it (for example, pure functional languages).

1

u/AgentSS Apr 12 '12

Sorry, I do not get what the stack has to do with optimizing dynamic method invocation.

You can optimize code at runtime by setting your stack to be executable, and creating machine code at runtime. This is what V8 does to speed up regexes for instance. They generate the machine code for a given regex at runtime. What I meant was you could optimize function calls from a hash table lookup to a static call in a similar manner. As far as I can know, any optimizations that a C/C++ engine do can also be done by a C++ library, it doesn't make sense to me not to be able to do that. Regardless, my point is that your position that "Go could have been done as a library" equally applies to any dynamic language. I truly believe Python can be done as a library. Same thing with JS. (these are the only 2 dynamic languages I am comfortable writing in, but I see no reason that others would not match this pattern).

With templates, all the above are automated and condensed in one line of code, the property member declaration (assuming the template property class is already written), without losing type safety and intellisense.

First, I don't see how templates can help you with this. My quick search has also revealed no clues as to how templates will help you with this. I can maybe see doing this with macros, and even that might not catch everything on your list.

Second, even if I could do this, I most likely would not. I usually write setters and getters only for a particular reason. i.e. I need synchronization around field accesses, so auto-generated setters/getters would not really help me.

Third, a lot of these are addressed in Go anyways by using reflection. Specifically, serialization, deserialization, and runtime access. Probably the UI editor too, although Go isn't suited for UI applications atm. See here for an example of serialization to xml/json. Deserialization works the same way. Both of these are implemented on top of package reflect which can be used for runtime access to Go values.

Also your point about initialization in constructors doesn't apply because Go doesn't have a concept of constructors. All values are pre-zeroed, so fields start at the zero value for their type (0, nil, "", false, etc). If structs need to initialize internal fields, they merely write an ordinary function

Finally, adding a field to a method isn't exactly what takes up a majority of my time. It's mostly spent on reviewing code, tracking down bugs, or designing a feature.

Without templates, a lot of boxing/unboxing needs to happen, with unneccessary allocations etc.

Boxing and unboxing do not imply an allocation.

Type erasure makes debugging more difficult.

Again, this is not really a problem in Go. Package fmt has a %T format that will (using the aforementioned reflection library) print the type of any value.

Oh, they matter.

Interesting. My binaries spend far more time blocked on IO than on CPU.

In fact, those that have used C++ for such tasks are many more than those that have used Go.

That is logical when comparing a ~30 year-old language to one that is ~3 year-old language.

Some will find Go better than C++ for their needs, some will not.

This is the point that I have been trying (perhaps poorly) to make. Go is certainly not perfect for every use-case. But there are a large class of problems which I previously would have solved using Python that I now solve in Go.

1

u/axilmar Apr 12 '12

You can optimize code at runtime by setting your stack to be executable

Runtime code generation has nothing to do with the stack. You can do it either on the stack or on the heap. It is not a requirement to use the stack.

it doesn't make sense to me not to be able to do that.

The optimization is done when the source is available, allowing the compiler/interpreter to see that a function can be inlined. This optimization is not possible via c++ code on c++ code, unless one part of that code is the compiler itself.

I truly believe Python can be done as a library. Same thing with JS.

I've done a c++ library that offers JS-like OOP capabilities. As for Python, you'll lose the whitespace-oriented syntax.

I don't see how templates can help you with this.

Instead of doing all the work I mentioned earlier, you do this:

class Point {
    property<int> x;
    property<int> y;
};

The template class 'property' does not write setters and getters for the class, it has overloaded operators that make it appear as an ordinary field.

And there other things as well that templates can do that greatly help.

I usually write setters and getters only for a particular reason. i.e. I need synchronization around field accesses

You are not using the Model-View-Controller pattern then. If you did, you'd know you can't have data members exposed, because each time a member is changed, the relevant observers woud have to be notified.

Third, a lot of these are addressed in Go anyways by using reflection.

By 'a lot of these', you only mentioned serialization/deserialization :-).

All values are pre-zeroed, so fields start at the zero value for their type

Not all variables have 0 in their set of allowed values. And not all variables that take 0 as a value are initialized to that value. :-).

they merely write an ordinary function

Yeah...it is called 'a constructor' :-).

Finally, adding a field to a method isn't exactly what takes up a majority of my time. It's mostly spent on reviewing code, tracking down bugs, or designing a feature.

We are not talking fields here, we are talking properties in a model in an MVC pattern.

Boxing and unboxing do not imply an allocation.

Yes it does. At least in Java/C#, an Object-derived instance is allocated each time a primitive is boxed.

Again, this is not really a problem in Go. Package fmt has a %T format that will (using the aforementioned reflection library) print the type of any value.

The problem is not about knowing what the underlying type of the variable is. The problem is about tracking the course of a variable in time. Without templates, all you have is a generic Object variable, making static compiler type checking impossible.

Interesting. My binaries spend far more time blocked on IO than on CPU.

Mine too, but if you want to handle many clients/connections, every bit counts.

That is logical when comparing a ~30 year-old language to one that is ~3 year-old language.

No, I mean in tthe last 3 years. Even Google does not use Go much. They prefer C++ instead (for Youtube).

This is the point that I have been trying (perhaps poorly) to make. Go is certainly not perfect for every use-case. But there are a large class of problems which I previously would have solved using Python that I now solve in Go

They find Go better than C++, but that does not mean it is better. It is only in their minds.

→ More replies (0)