Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Go in Go (golang.org)
447 points by zdw on May 27, 2015 | hide | past | favorite | 146 comments


Fun fact: what's common between Rob Pike, Bjarne Stroustrup, Larry Wall, Guido van Rossum, and so many other language inventors?

They're all C programmers!


Working on UNIX operating systems means there isn't much of a choice in terms of system programming languages.

Why to you think all of them created languages to replace C on their daily work?

There are many reasons to use a specific programming languages besides "I like it".

For example I will never use C on personal projects, but will use it without any complaints if that is what my customers ask for.


Well, C is essentially "portable assembly", so it's to be expected...


I never understood this sentiment. C isn't assembly exactly because there isn't necessarily a direct correlation between the instructions the programmer writes and the resulting machine code. To me, this is as contrived as the idea that Javascript is "LISP in Java's clothing"

In what possible sense can it be described as an assembler?


It’s relatively easy to mentally compile unoptimised C, or to look at an unoptimised assembly listing and correlate it with the source, but that’s about as far as the metaphor goes. C is a high-level language.

Only when I’m writing very performance-sensitive code do I actually think “here’s a branch, there’s a load, yonder is a divide”. Most of the time it’s “eh, compiler’ll get it”.


Because C is a very low level language, it imposes very little architectural decisions on higher levels that could cause impedance mismatches.

For example, you wouldn't want to implement a garbage collector in a garbage collected language; C won't get in your way.

This is also why there are loads of C libraries out there: they can be used with bindings from essentially any other language, which is generally not true for libraries implemented in non-C languages (in particular, C++).


> Because C is a very low level language, it imposes very little architectural decisions on higher levels that could cause impedance mismatches.

Remember that it also enforces the idea of types, scopes, blocks, functions, the heap and the data stack quite strictly. It might be a very low level language compared to something like Java, but in terms of being unassuming of architectural intent, I can't say that I agree that it is even in the same ballpark as any of the assembly languages I've used.


Indeed it enforces some function calling convention, which may be an issue if you want to compile a high level language via C, particularly since C does not guarantee tail call optimization.

Also there's no fast way to check arithmetic overflow from portable C, which limits bignum performance.

Due to these limitations better portable assembly languages like C-- have been designed; these days LLVM bitcode is an option as well (which is not actually portable IIRC...).


I think these days the term "portable assembly" misses the mark. A term that better captures the flavor of C with today's CPUs is "programmable RAM".

C is one of the few languages today that still gives you very precise control over how you use memory. That can be a powerful tool, especially given how important effective cache usage is on chips.


>because there isn't necessarily a direct correlation between the instructions the programmer writes and the resulting machine code

If there was, then it wouldn't be "portable"


My point is that if you choose to ignore this characteristic of assembly languages, what exactly is an assembly language? C is a comparably high level language, which affords it things like portability and optimizing compilers. Assembly languages are used for minute and immediate control of the exact implementation.


>Assembly languages are used for minute and immediate control of the exact implementation.

I think the joke/humor/analogy is that C compilers are so good and C itself is so low level, that you don't actually gain much (if anything at all) by dropping down to ASM now (compared to 10-20 years ago).


Maybe not a direct correlation but:

"By design, C provides constructs that map efficiently to typical machine instructions"[1]

I believe this is what the op was getting at. This is why C is called a "mid level" language.

[1] http://en.wikipedia.org/wiki/C_%28programming_language%29


There is very little difference to the machine code (traditionally, before CPUs got so complex)


I'm not sure what you are saying here. Do you mean to say that it makes no difference to the machine how the code is generated, or are you saying that there is a CPU for which there is "little difference" between its machine code and C?



Reminds me of the "programming language inventor or serial killer" quiz (warning: Flash + sound): http://www.malevole.com/mv/misc/killerquiz/


Bjarne Stroustrup

Wasn't CFront written in C++?[1] (Of course, the initial version of C with classes was probably written in C.)

[1] https://en.wikipedia.org/wiki/Cfront


What to expect from an AT&T employee?

Which languages do you think guys at Microsoft, Apple and Google get to choose?

Those developed by their employers or others?


Probably the only C++ program he ever wrote.


Bjarne has written numerous C++ programs, has he not?


Out of curiosity to the downvoters, has he NOT written C++ programs? Was his paper in IEEE the other year calling for more static code (let the compiler do its work) and abandonment of the dynamic_cast "let's check at runtime!" development model something he pulled from thin air? Or has he actually written code?


They have a beard?



Matz (Yukihiro Matsumoto) too!


Unless I missed it, it is surprising the lack of benchmarks or mentioning how compile speed compares with the previous iteration.

I'm not saying it would be necessary slower than a compiler written in C, if they wrote the more critical parts in assembler, but you would think compiling speed would be one of the outstanding discussion points, after a major rewrite.


There were a few slides with numbers and detailed performance graphs in Andrew's preceding talk. See http://talks.golang.org/2015/state-of-go-may.slide#10 and nearby slides.


If I'm not mistaken, these graphs refer to the speed of the code generated with the compiler, not of the compiler itself.


This slide mentions that initial go-version dropped down to 1/10th of the C in performance:

http://talks.golang.org/2015/gogo.slide#15

While the next mentions that the got it back up -- but not by how much.

It wasn't exactly crystal clear from the docs/website, but apparently[1] "master" is go1.5 -- so with go1.4 on windows, one can:

    # from a git bash, already have go1.4 installed
    git clone https://github.com/golang/go.git go.git
    cd go.git/src
    git checkout master
    export GOROOT_BOOTSTRAP=$GOROOT
    time cmd "/c all.bat"

    real    0m29.078s
    user    0m0.015s
    sys     0m0.030s

    # with our fresh go1.5 (see more below):
   
    real    0m33.034s
    user    0m0.000s
    sys     0m0.000s
So, apparently doing the same job (compiling go1.5 "master") with go1.5 and go1.5 -- there's a small hit (I ran a couple of runs with each, the numbers are consistent to ~1sec, so call it 29 for 1.4 and 33 for 1.5).

Note that if you want to do this, in particular the second part, it gets a bit hairy, as "go.exe" needs to be in your path, and you need to change your gopath (easy).

On my system, I had everything in $HOME/opt (%HOME%\opt), so all i did was move opt\go to opt\go1.4, and copy go.git to \opt\go. One can confirm the right version is being run with 'go version' (and 'cmd "/c go version"' from bash).

[1] After a few useless hits, I found: https://godoc.org/golang.org/x/mobile/cmd/gomobile -- which mentions what's needed to actually test go 1.5. If they want testers, they should probably add something under "install from source" on golang.org about "And if you want to live on the edge, or say, test go in go, use "master")


(I'd be more confident in this test if someone could point me at a past commit where go1.5 works, builds with go1.4 and itself, but is (much 10x) slower...).


Distinctions like that makes googling for speed of the compiler itself annoying.. :-)


There was some discussion about it on golang-dev:

https://groups.google.com/forum/#!msg/golang-dev/6obxRcm-rqc...


Does the speed it takes to compile the compiler really matter?

Edit: Of course, faster speeds would be interesting to hear about, so great question.


"We believe it's worth trying again with a new language, a concurrent, garbage-collected language with fast compilation."

Fast compilation is an explicit goal of Go, so they certainly think it matters.


I am most excited for the new SSA backend in go. I have been following commits to it here:

https://github.com/golang/go/tree/dev.ssa

No idea how long it will take to mature, but I hope there are some decent performance improvements once it is fully functional.


Just for those who are wondering what SSA is: https://en.wikipedia.org/wiki/Static_single_assignment_form


I was exited by this:

> Generate machine descriptions from PDFs (or maybe XML).

> Will have a purely machine-generated instruction definition:

> "Read in PDF, write out an assembler configuration".

> Already deployed for the disassemblers.

(my emphasis)

That coupled with a whole tool chain in a friendly language like go, makes be exited for how this might be used by other language designers. While "compile to go" might not be as attractive as "compile to c" -- it's not half-bad. More importantly it kind of smells like part of this tool chain should make it quite easy to generate machine code quite easily.

Nothing against llvm, rpython/pypy, graal etc - but the more the merrier!


SSA?


Internal graph representation the compiler uses for programs. llvm uses SSA form of programs as its main low level representation. The benefits of SSA is that it enables some analysis and optimization techniques.


It is basically a simplification that makes optimizations easier by eliminating re-assignment of local variables (where possible, for loops and conditions, merging phi values might be necessary). It has been awhile since I played with this, but it made CSE (common sub-expression elimination) really easy.


And writing programa in that style makes programs less bug-prone. :-)


Oh, I was hoping for some go (aka baduk or weiqi) playing program written in go. These are a bit tricky to google ;)


Finally, my moment! I submit my own library, which is really meant for two players and scoring...and like much of what I do, was purely pun-driven. Maybe one day I'll add AI:

https://github.com/acityinohio/baduk


Have a look at the Go Text Protocol [1] and SGF [2]. If you add these then the strongest existing AIs can already play on your board.

All that said you can of course write your own bots, but Copmputer Go isn't as easy as one might think. In fact it's still considered a much harder problem than Computer Chess.

[1] http://www.lysator.liu.se/~gunnar/gtp/

[2] http://en.wikipedia.org/wiki/Smart_Game_Format


Ah awesome! Thanks for sharing. Definitely going to add this on my to-do list; would love to add some already-made AI to it. :D


Cool! Thanks for sharing.


I wrote one a long time ago. (It does not play well; it's just a port of a Java benchmark.)

https://github.com/skybrian/Gongo


Me too. It is messing up with golang as well:

> [14:54:36] Topic is Go, the game (not the silly language) ! (the language see #go-nuts


> Getting rid of C was a huge advance for the project.

> Code is cleaner, testable, profilable, easier to work on.

This is just great!


Looking at the title, my first thought was that somebody is making fun of all those posts "[something] in Go" ;)


There is no slide about writing the GC in Go.

How do you write a GC in a GC'd language?


The usual way to do it is to define a restricted subset of the language that has explicit memory management and is statically typed, and implement GC with that.

For example, Pre-Scheme and RPython.

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.3.40...

https://en.wikipedia.org/wiki/PyPy#RPython


Slide #9 mentions they use the unsafe package in the GC to deal with pointers as raw bits.


But does the GC run on the GC's own runtime data?

Can the GC be interrupted by itself if it takes too long or uses too much memory?

It seems like there are several things about the GC that would need to be special-cased, since the GC is implicitly invoked by the runtime.


I would assume not. GCs are typically invoked by requesting allocation. Since the GC (presumably) uses lower-level OS facilities to allocate memory, it wouldn't need to recursively invoke itself.


Can we trust the go compiler?

edit: This is the link I meant - https://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thomp...


i.e. can a bug that existed early in the toolchain history propagate in the binaries but not the sources?

c_i is the i'th version of the compiler.

    c1 c2 // c1 compiles c2

    c2 c3 // c2 compiles c3
Source code of c1 has bug, source code of c2 and c3 is fixed. Bug in c1 causes binary of c2 to have bug. Binary bug in c2 causes binary bug in c3.


You can still, if you really want to, build the Go 1.4 from its C source, then compile the go compiler with that result.


I really like the slide software. Does anyone know where I can find it?



Wow, they run an entire web server just for slides?


They're not just slides. Some of the slides have code that you can click to run: http://talks.golang.org/2012/concurrency.slide


My lack of knowledge resulted in downvotes. Thanks for the reply.


Wow. You have to use a whole web browser just to view slides ?


The web is almost perfect for a presentation.


When you are Google and your slides generate traffic why not right?


If you don't care about executing the code, you can save the slides to a PDF. I did this in Chrome many times and it works well.


This script is included at the top of the page source: http://talks.golang.org/static/slides.js


It is unreadable on an iPhone.


Doesn't work on iPhone which is annoying.


It works fine on an iPhone. Tap the left or right side of the slide to go back or forward, respectively.


I have to hold the screen in landscape to not get the sides of the slides cropped off, and then I still get the address bar covering the headline after each new slide load, unless I tilt the phone to portrait and back for each slide.

Horrible.


Just use your two fingers to slightly zoom out one slide, and you won't have the address bar covering the headline after that.


Doesn't work. And now the slides aren't centered on the screen anymore, but halfway outside it. sigh


The Go project philosophy emphasizes simplicity of development over end-user usability.

Much like HackerNews website implementation, actually.


HN is super-usable. Just a simple website. Minimal JS and styling.

That slide-script is just broken.


HN is pretty dreadful on mobile.


OK, doesn't work when you swipe. Not sure why I would think to tap the edges.


I'd recommend present.js instead.


Live stream recording here: https://youtu.be/Fx304EfqtMo?t=2468


Not anymore :)


Can some one answer this question. It says that Go1.4 will be needed to compile Go1.5. Does this mean that Go1.4 will always be needed, even for Go1.6 and beyond? So are they essentially locking things to the Go1.4 "C" code, then updating on top of that?


No, any newer version works. You can build 1.5 with 1.5, you will be able to build 1.6 with 1.5 and 1.6.


Right, but if someone surreptitiously deleted all Go compiler binaries from the world, then we'd have to go back to compiling the C source of 1.4...

Of course, that's the nature of bootstrapping! If someone managed to erase all the software from all the computers in the world, we'd have to go back and find an "Old world" Mac and use the on-die Forth compiler to write a C compiler so we could start compiling things again.


Provided people didn't forget. Recreating from memory will take a fraction of the time. I would go for a lisp interpreter in assembly then implement a c compiler in that.


Yes, and thanks to version control that would take, what, maybe a few minutes?


Not if all the binaries for the version control systems also go missing :)


Yes. It means that anytime you want to add a new supported architecture, you'll need to bootstrap through Go 1.4.

Otherwise, I'm guessing that for Go 1.6, they'll rely on you having a binary distribution of 1.5 (probably from your distribution, or their website), etc.


>It means that anytime you want to add a new supported architecture, you'll need to bootstrap through Go 1.4.

That's not true at all, (1) you write the backend for the target machine, (2) you recompile the compiler with the new backend included on a supported host, (3) then use the new compiler to compile itself for the target using the new backend, (4) you now have a compiler that runs on the target.

Same process is used to port C compilers (or any self-hosting compiler, really).


I think it would be much more likely that new architectures would be added as cross-compilation targets than to work back through a v1.4 bootstrap.


Sorry for the noob question, but could someone help me understand how this is (conceptual) possible?

I get that you can write a program which compiles language X to machine code, e.g. how python interpreting Go to write the assembly necessary would be technically possible.

My question is, how is the compiler generated? If it's written in c, gcc -o compiler, but what is the piece I'm missing when it comes to Go compiles a Go compiler -- or is this still done as "here's the machine code, now compile the Go runtime"?

I suppose my question is a similie to "the chicken or the egg?".


On a related note, while Go at least has Go 1.4 available to allow bootstrapping from a C compiler for the near future (see [1] for more detail), many languages have no easy way to do so. For example, Rust's compiler was originally written in OCaml, and Nim's in Object Pascal, but both compilers were migrated to be written in the respective languages themselves, and AFAIK both languages have since evolved alongside their compilers for long enough that bootstrapping all the way from before said migrations to the present would require a massive chain of newer and newer compiler versions - not an undertaking anyone really wants to carry out.

Instead, any Linux distribution etc. that wants to integrate the language into its build system has to start by importing a binary from somewhere else. In general this isn't a problem, because that binary is used only to compile the compiler from source (and then that compiler recompiles itself, usually), so any bugs in it are unlikely to affect the final product. However, the topic tends to come up of Ken Thompson's famous paper [2] describing a hypothetical scenario where a compiler binary is intentionally backdoored to insert a vulnerability when it's compiling some security-critical program, plus a copy of the same backdoor whenever it detects it's compiling itself. In that case, the backdoor could theoretically infect the final result of a bootstrap, despite it being compiled from pristine source; no attack of that nature has ever been detected in the wild, though.

[1] https://docs.google.com/document/d/1OaatvGhEAq7VseQ9kkavxKNA...

[2] https://www.ece.cmu.edu/~ganger/712.fall02/papers/p761-thomp...


What also intrigues me is how one would port to a new architecture.

You've got no go1.4 there to boostrap you (new architecture), and you can't get the binary because you're trying to build the first one.


Easy, you cross compile from Go on a different architecture. Go apparently has a good cross compilation story, though I don't have experience with it; honestly IMO the whole perception that cross compiling is an unusual or difficult thing comes from poorly designed Unix build systems. Though I suppose this would make a fully automated bootstrapping system a bit messier. (Do the first build in an emulator?)


Thanks for you answer. I hadn't though about cross compilation, and I guess that's the sanest approach, when possible.


Simple, you need a working version of go1.4 to compile go1.5.

The bootstrapping process can therefore take advantage of the fact that go1.4 will continue to build as it does today, and use that to get a working go installation to build go1.5+.


Ah, great. Thanks for the explanation :)


I understand that the standard build/release procedure for compilers which are the primary compiler for the language they are written in is to:

Build the new version of the compiler with the previous version of the compiler

Rebuild the new version of the compiler with the new compiler from the previous step, that was built with the old compiler

Rebuild the new compiler with the new compiler from the previous step, that was also built with the new compiler, and that's your official binary

The initial creation of the language requires somebody to write a compiler for it in assembly or in some other language that already has one, but once you get that first one built, all the rest could be in their own language.


a curiosity question. is "all but impossible" correct? shouldnt it be "all but possible" or "all but easy"? whenever i see the "X is all but Y" phrase, it makes sense to me that X is not Y. its everything else but/except Y. am i thinking correctly or is the use in the slides correct?


It's correct, but so is your line of thinking. These things are not impossible, they are all but impossible. And all in this context includes things like requires an expert, is highly hard to do, and/or would take many years. It is all of those things, but not impossible, hence all but impossible.


The idiom "X is all but Y" means "X is very nearly, but not quite, Y." I think of it as "X is in all ways like Y except one last little bit."


> is "all but impossible" correct?

Yes.

> whenever i see the "X is all but Y" phrase, it makes sense to me that X is not Y.

It's not "X is not Y", it's "X is all but Y", that is, X is very nearly not Y. "All but impossible" means it's possible, but only barely.


And to make it extra confusing there's "X is anything but Y" idiom which basically means what pvinis says.


aaah thats why i get confused. i thought its always one phrase, but its "all but" and "anything but". now i get it. lets just say this whole confusion is anything but unclear now. it used to be all but impossible to understand what people meant.


Oh, I didn't realise that either. Now I understand.


All but impossible means nearly all the way to being impossible.



It's an exaggeration where the upper bound isn't met.

All but impossible, it's everything up to, but not including impossible.


Does that mean cgo is away too ?


I don't know why I've been downvoted. Maybe my question wasn't clear. Since there is no need anymore for a C compiler in the Go toolset, how will the magic import "C" package work ?


If you want to use cgo you still need a C compiler for that. But it's the system C compiler (clang or gcc), not the one we deleted.


OK, thanks for the information.



Just out of curiosity, is this the first time a language is written using itself?


Nope. Many languages are written in themselves. C, C++, and many Lisp implementations come to mind :)

See http://en.wikipedia.org/wiki/Self-hosting


No, this is actually pretty standard.http://en.m.wikipedia.org/wiki/Self-hosting


There's quite a few languages that bootstrap: https://en.wikipedia.org/wiki/Bootstrapping_%28compilers%29#...


So if you follow it all the way down, what does all these self-hosting code become? Machine code?


A common pattern used to be as follows:

Start by implementing in Assembly as little as possible for the programming language as an interpreter.

Meaning just one form of conditionals, just one looping construct, very few basic types, basic IO.

Then use the bare bones interpreter for the second stage, writing a real compiler that is able to process the same basic language and additional constructs.

Another alternative is to add some bytecode format that can then be used equally for interpretation or as input to native code generation.

Niklaus Wirth originally designed P-Code with the intent to make Pascal compilers easier to port. He wasn't thinking to use it as full OS VM, like the guys at UCSD did with they Pascal dialect.

Another trick is to design the bytecode in such a way that it can directly be translated to native code via a macro assembler. It won't generate fast code, but it will provide an easy path for a compiler instead.

Nowadays the Assembly step tends to be replaced by another language that can be found in most platforms, so many tend to choose C.

Not always because it is the best language to write compilers in, but rather because it is ubiquitous or there is some library the authors want to use, thus perpetuating the myth that all languages require C for those not so well versed in compiler design.


They usually need a previous version of the compiler to compile themselves. Turtles all the way down if you will.


It's a sign of maturity to show that a language can bootstrap itself, prolog has been written in prolog, erlang was written with prolog first, then later rewritten in erlang, as other's have pointed out, it's pretty common for C/C++, Lisp, Assembly. This of course applies more to compiled languages.


You know that Erlang is not entirely written in Erlang, right?


Hell, brainfuck can interprete itself


No, bootstrapping is fairly common. Rust is another common example of a bootstrapped language and has been for some time.


Congrats on this milestone!


It would be nice to see benchmarking stats to gauge the significance of the performance problems mentioned in the slides. For users, I'd imagine the ease of developing the Go language is less important than its performance.


Is there anyway to navigate that presentation using only the mouse? If not, why not?


From the instructions on the page:

> Use the left and right arrow keys _or click the left and right edges of the page_ to navigate between slides.


Is the video out yet?



"How to sell a rewrite of your compiler that made it slower"


This is a fair criticism presented in a poor way. Hopefully the performance will improve with the new dev.ssa branch eventually.

I will note that go programs still seem to build orders of magnitude faster than C++ programs, even after this change.


Can you please explain what dev.ssa branch is implementing and how is it going to change the performance of the compiler?


It is a program representation that a few modern compiler optimization techniques rely on. It just mean there is potential for the compiler to emit better assembly code.

Because the compiler is now written in Go, compiler optimization will affect how fast programs compile.

The compiler may speed up or slow down because it is doing more advanced code analysis, but is generating better assembly. I do not know if this will cancel itself out or not.



He means in compilation speed - not in resulting binary speed.


It's not a hard sell. Self-hosting improves the language simply by having the core developers use it for a complex project like a full toolchain.


whee exciting new stuff AND a foundation for even more stuff in the future. great thx!


These new Go presentations (this one and http://talks.golang.org/2015/state-of-go-may.slide#1) are great. Very insightful and well explained.


We'll have vids of both up on https://www.hakkalabs.co/meetups/gosf within a few days or so.


Could someone explain why 4 of the top 5 stories right now are about Go?



I won't be surprised if there having been a Golang SF Meetup tonight with community headliners hurts ;-) http://www.meetup.com/golangsf/events/220935959/

  •  Talk 1: Andrew Gerrand on Go 
  •  Talk 2: Rob Pike on Go 
  •  Talk 3: Aaron Schlesinger, Concurrency Conventions in Go   
  •  Talk 4: Steve Francia, Common Mistakes in Go and When to Avoid Them


Google IO is 1 day away. My guess is they just finished polishing presentations which got published.


Randomness


I've created my own programming language and they always tell me that the best languages are always self-hosted, so I wrote the compiler in my new language too.

I'm having trouble running the compiler.

     bpgcomp bpgcomp.bpg -o bpgcomp
But I keep getting a "bpgcomp not found" error.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: