Hacker News new | comments | ask | show | jobs | submit login
Things I like about programming in Go (jgc.org)
181 points by jgrahamc on July 4, 2012 | hide | past | web | favorite | 110 comments

I have a hard time getting past it being mostly unusable on 32 bit Linux [1]. That just seems like a fundamental flaw in the garbage collector that moving to 64 bit simply kicks the can down the street.

And before anyone suggests "just use 64 bit", that actually a really crappy solution. In most cases it merely (almost) doubles your memory footprint for no real gain.

[1]: https://groups.google.com/group/golang-nuts/browse_thread/th...

There's a patch to make the current conservative GC a precise GC, which will totally fix this problem. It's in the process of being reviewed and integrated into the core.


FWIW, the panelists on the recent "Go in production" panel at I/O responded that garbage collection wasn't an issue for them on 64-bit systems. http://www.youtube.com/watch?v=kKQLhGZVN4A

That's awesome, kudos. How do you deal with maintaining the distinction between pointers and values on the stack and in registers? I didn't see any code to do that, skimming through that patch. Since it's a precise GC, you need to maintain the distinction.

In Rust we have a very large patchset to LLVM to allow us to do this; it involves modifying nearly every stage of the LLVM pipeline. Curious how you did that in gccgo.

Edit: I just looked at the source and it still seems conservative for the stack and registers. So it's not a precise GC yet and will not eliminate false positives. (This is of course totally fine, I just wanted to clarify for myself.)

This isn't my patch, so I can't speak to the specifics of it. Also, it isn't for gccgo, but the gc compiler.

That's too bad. Hopefully someone will improve `gccgo` as well. I actually started out experimenting with Go using the `gc` compiler, and found performance (basically manipulating large arrays sequentially) atrocious. Moving to `gccgo` improved performance four-fold, making my unoptimized Go test code in some cases faster than my unoptimized C test code.

How long ago was that? The gc compilers have seen lots of improvement recently, and more will be merged soon.

Also, if the problem is so pathological, it might be worth filling an issue.

Go 1.0.2, which is the newest stable release. I will see if I have some extra time to file a report.

Slightly off topic (but relevant to my comment above), do you know why this:

    func TraverseInline() {
      var ints := make([]int, N)
      for i := range ints {
        sum += i
should be slower than:

    func TraverseArray(ints []int) int {
      sum := 0
      for i := range ints {
        sum += i
      return sum

    func TraverseWithFunc() {
      var ints := make([]int, N)
      sum := TraverseArray(ints)
Seeing a huge difference here. With an array of 300000000 ints, TraverseInline() takes about 750ms, whereas TraverseWithFunc() takes 394ms. With gccgo (GCC 4.7.1), the different is much slighter, but there's still a difference: 196ms compared to 172ms. (These are best-case figures, I'm doing lots of loops.) Go is compiled, not JIT, so I don't see why a function should offer better performance.

I don't have any immediate insight for the difference in performance you're seeing (my hunch is that it's to do with where and how memory is being allocated), but I would suggest you ask about it on the Go-Nuts mailing list: https://groups.google.com/forum/?fromgroups#!forum/golang-nu...

The Go authors should be very receptive and informative on such an issue.

Unrelated to your question, but your code doesn't traverse array. All it does is:

      for i := 0; i < len(ints); i++ {
        sum += i

Sorry, that was a typo. The actual test program I use is correct. It was obviously supposed to be:

    sum += ints[i]

Not relevant to the performance test but you can do this

for index, value := range mySlice { }

and you get the index and the value, or you can do

for _, value := range mySlice { }

If you only need the value.

Not sure why the difference in performance between function and non-function, particularly considering this looks inline-able.

2 theories on why gcc is doing better. Maybe its unrolling the loop, and avoids a bunch of jumps. Alternatively, it could be using SSE, but this theory is a much less likely, because I would expect it to be 4 times faster not twice as fast. gc doesn't use SSE instructions yet.

I'm not seeing any difference between the two functions using the 1.0.2 x64 gc compiler. Here's the code I used (slightly modified to compile): http://play.golang.org/p/gcf0BOGncQ

For more complex functions, you could try profiling using the runtime/pprof package. More info here: http://blog.golang.org/2011/06/profiling-go-programs.html

If you want to dig deeper and are not averse to assembly, you can pass -gcflags -S to 'go build' and see the compiler output. Here's what I got for the above code:

  --- prog list "TraverseInline" ---
  0000 (/tmp/tmp.rkM3kSJ6Hd/trav.go:10) TEXT    TraverseInline+0(SB),$40-8
  0001 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) MOVQ    $type.[]int+0(SB),(SP)
  0002 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) MOVQ    $300000000,8(SP)
  0003 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) MOVQ    $300000000,16(SP)
  0004 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) CALL    ,runtime.makeslice+0(SB)
  0005 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) MOVQ    24(SP),BX
  0006 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) MOVL    32(SP),SI
  0007 (/tmp/tmp.rkM3kSJ6Hd/trav.go:11) MOVL    36(SP),BX
  0008 (/tmp/tmp.rkM3kSJ6Hd/trav.go:12) MOVL    $0,DX
  0009 (/tmp/tmp.rkM3kSJ6Hd/trav.go:13) MOVL    $0,AX
  0010 (/tmp/tmp.rkM3kSJ6Hd/trav.go:13) JMP     ,12
  0011 (/tmp/tmp.rkM3kSJ6Hd/trav.go:13) INCL    ,AX
  0012 (/tmp/tmp.rkM3kSJ6Hd/trav.go:13) CMPL    AX,SI
  0013 (/tmp/tmp.rkM3kSJ6Hd/trav.go:13) JGE     ,16
  0014 (/tmp/tmp.rkM3kSJ6Hd/trav.go:14) ADDL    AX,DX
  0015 (/tmp/tmp.rkM3kSJ6Hd/trav.go:13) JMP     ,11
  0016 (/tmp/tmp.rkM3kSJ6Hd/trav.go:16) MOVL    DX,.noname+0(FP)
  0017 (/tmp/tmp.rkM3kSJ6Hd/trav.go:16) RET     ,

  --- prog list "TraverseArray" ---
  0018 (/tmp/tmp.rkM3kSJ6Hd/trav.go:19) TEXT    TraverseArray+0(SB),$0-24
  0019 (/tmp/tmp.rkM3kSJ6Hd/trav.go:20) MOVL    $0,DX
  0020 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) MOVL    $0,AX
  0021 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) MOVL    ints+8(FP),SI
  0022 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) JMP     ,24
  0023 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) INCL    ,AX
  0024 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) CMPL    AX,SI
  0025 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) JGE     ,28
  0026 (/tmp/tmp.rkM3kSJ6Hd/trav.go:22) ADDL    AX,DX
  0027 (/tmp/tmp.rkM3kSJ6Hd/trav.go:21) JMP     ,23
  0028 (/tmp/tmp.rkM3kSJ6Hd/trav.go:24) MOVL    DX,.noname+16(FP)
  0029 (/tmp/tmp.rkM3kSJ6Hd/trav.go:24) RET     ,

  --- prog list "TraverseWithFunc" ---
  0030 (/tmp/tmp.rkM3kSJ6Hd/trav.go:27) TEXT    TraverseWithFunc+0(SB),$40-8
  0031 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) MOVQ    $type.[]int+0(SB),(SP)
  0032 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) MOVQ    $300000000,8(SP)
  0033 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) MOVQ    $300000000,16(SP)
  0034 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) CALL    ,runtime.makeslice+0(SB)
  0035 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) MOVQ    24(SP),DX
  0036 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) MOVL    32(SP),CX
  0037 (/tmp/tmp.rkM3kSJ6Hd/trav.go:28) MOVL    36(SP),AX
  0038 (/tmp/tmp.rkM3kSJ6Hd/trav.go:29) LEAQ    (SP),BX
  0039 (/tmp/tmp.rkM3kSJ6Hd/trav.go:29) MOVQ    DX,(BX)
  0040 (/tmp/tmp.rkM3kSJ6Hd/trav.go:29) MOVL    CX,8(BX)
  0041 (/tmp/tmp.rkM3kSJ6Hd/trav.go:29) MOVL    AX,12(BX)
  0042 (/tmp/tmp.rkM3kSJ6Hd/trav.go:29) CALL    ,TraverseArray+0(SB)
  0043 (/tmp/tmp.rkM3kSJ6Hd/trav.go:29) MOVL    16(SP),AX
  0044 (/tmp/tmp.rkM3kSJ6Hd/trav.go:30) MOVL    AX,.noname+0(FP)
  0045 (/tmp/tmp.rkM3kSJ6Hd/trav.go:30) RET     ,

Here is my test, with test output for gc and gccgo:


The numbers are from Go 1.0 as that's what is available on Ubuntu Precise, my test box. (Getting similar numbers with 1.0.2 on a different box where I don't have gccgo.)

I realized that the first loop was using "i < len(ints)" as a loop test, which turns out to be more expensive than I thought, and the compiler doesn't optimize it into a constant (which would be expecting too much, I guess). After rewriting the test, the function call case is only slightly faster, although it is still significantly faster with gccgo.

Is this patch going to be part of LLVM? Is one out of luck if they want to implement a precise collector in LLVM today?

I've talked with Chris Lattner about upstreaming it and the LLVM developers seem open to it when it's ready. In the meantime you can find the most recent work here:


Currently, you are mostly out of luck if you try to use mainline, unless you're okay with the llvm.gcroot intrinsics, which pin things to the stack so they can never live in registers (causing a corresponding performance loss). Probably your best bet is to do what Go will do once the patch enneff was referring to is merged: scan conservatively on the stack and precisely on the heap. You can still get false positives and leaks, and you can't do moving GC that way, but it's better than fully conservative GC.

By far, the hardest part of GC is precisely marking the stack and registers. Yet you have to be able to do it if you want to prevent leaks. Our goal is to put in the hard work so that new languages will be able to have proper GC without having to roll a custom code generator or target the JVM or CLR.

> Our goal is to put in the hard work so that new languages will be able to have proper GC without having to roll a custom code generator or target the JVM or CLR.

As someone who has ambitions of writing a fun little language this is exactly what I want out of LLVM. Can't wait for your patches to hopefully get to mainline.

32bit memleak is by far the main reason I stopped looking at go. Many people still have plenty of 32 bit hosts.

When will this be in the official release??

It'll be in Go 1.1, around the end of the year.

In practice very few people have issues on 32bit systems, and for those that do there are workarounds.

Also, Go works much better on 64bit systems for many other reasons, if nothing else because that is what most of the core team uses. 64bit certainly does not double your memory footprint, and it increases performance dramatically (in part because the extra registers, etc., and in part because the Go 64bit compilers are much better).

And as Andrew mentioned, there is a patch already to fully solve things for the few people stuck on 32bits that have any issues.

Finally, all this is an implementation detail, and has very little to do with the qualities of the language. which is what the article is really about.

> In practice very few people have issues on 32bit systems,

I'm not sure what the proportion of people who experience issues is (whether it's "some", "most", or "very few"), but in my anecdotal experience running several long-lived Go processes on a 32-bit VPS it hasn't been a problem.

I think it just comes down to the allocation patterns in your program. Some programs trigger the pathological behavior and others don't.

Regardless of the numbers of affected programs, I'll be glad when the issue is behind us for good.

> 64bit certainly does not double your memory footprint

Not quite, but it does use a lot of extra memory:


I'm sure Ruby's memory usage characteristics are different than Go's, but still, it's worth paying attention to.

To be fair, it's kicking the can 60 years down the street, to when we're fully populating a 64 bit address space with 16 exabytes of ram. Considering the change will be backwards compatible, 64 bit is for all intents and purposes a permanent solution.

You do have a point about 32 bit, though (I use 32 bit Redis for instance, for the same reason).

Yep, they fucked up a bit. It happens. Fix coming in Go 1.1.

It's not really a fuck up, it's a "we didn't have time to do that yet because instead we were focusing on make an awesome language and standard library".

Lots of issues with the runtime had to wait because they can wait because it doesn't matter if you wait 5 years to fix the GC because you won't break any code when you do it.

I've been a Python developer for a decade. Go is the first language to successfully pull me away from Python. I've been developing in it for almost a year now and for every reason this blog post points out, I'm in love with it.

How has the library situation been? As a fellow Python developer, I'm very spoiled on libraries and every time I've looked at go, it doesn't seem to be gaining traction in that area.

The page full of go libraries the OP points to is laughably small -- even Haskell does better.

The core language though seems quite nice. Although it looks to not support OpenMP, which is a shame.

EDIT: I understand that Go is young and thus can't match up directly with Python/Java/Perl/C in sheer number of libraries. I'm more concerned with the rate of change of language adoption and new library creation, which doesn't seem to be large. But, the enthusiasm in this thread is quite encouraging.

Go is a new language (while it was developed in public, release 1 was just months ago) so of course the library situation is less well defined than in older languages.

On the positive side, the standard libraries are very consistent, the good 3rd party libraries tend to follow the conventions of the standard libraries (lots of decisions made in the language and tooling make it easier to do things the Go way than to treat it like it is another language) and if you really need some large chunk of functionality that Go doesn't provide and you don't have the time or willingness to make a pure Go version, you can easily pull C libraries in via cgo.

Ten years ago I was saying the same thing about Python with respect to Perl. Sure, it had some nice language features, but the libraries were a little spares. Now look at the Python libraries today.

Go's libraries are, IMHO, very thin right now. Just of the things I've recently looked for, there's no TLS v1.2, no XML parsing of any sensible variety, and the SMTP library is a sad joke. But I'm still using Go daily.

And guess what? It's also fun to get to write the libraries.

What does Go's encoding/xml package (http://golang.org/pkg/encoding/xml/) not do for you?

Being a new language it can't compete on the number of libraries. However, it does cover the ones I need the most for writing network servers. JSON, Websockets, Databases, SMTP, etc..

If I need to integrate features into a server that are more easily done in Python, I'll just launch a Python process from Go and communicate with it over pipes to get the functionality I need.

Can you be more specific regarding what libraries you need/miss?

Actually, yes! I picked up Go this week, and I'm actually really enjoying it. I did, however, hit a slight stumbling block because I needed to cryptographically sign some files to the PKCS#7 standard.

The 'usual suspects' have library support for this (Ruby, PHP, etc etc): Go does not (so I invoke openssl from within Go instead).

Putting that aside, it is a great language and one I'm really enjoying using. I primarily work in Objective-C, so it makes a nice change!

I suspect the 'usual suspects' just wrap OpenSSL, you can use Go bindings for OpenSSL too, but I'm also sure Adam Langley, who is responsible for the Go crypto lib and the main crypto guru for Chrome will be happy to help get any bits that you are currently missing into the go.crypto repo.

Hell, Go even has an official ssh library, I don't think any of the 'sual suspects' has that ;)


To be fair, I didn't actually expect Go to have it covered. I was porting over some Ruby code, and it just meant a little diversion via the OS/Exec package.

I'm currently working on a set of OpenSSL bindings for go. https://github.com/shanemhansen/go-ssl/

Honestly the project is only a few days old and really sucks, but I found wrapping OpenSSL's SHA and AES features trivial. cgo is the most awesome FFI I've ever used. SHA hashing is actually faster using the OpenSSL version.

Please feel free to fork and add your features, in the meantime I'm working on adding support for a TLS listener/connection like crypto/tls.{listener,Conn}. http://golang.org/src/pkg/crypto/tls/

I was very excited when I learned Go had standard library support for ASN.1 as I want to write a Go implementation of my companies ASN.1 protocol, but then I realized it was DER and not BER. I need a library that has good support for BER. That said there is a 3rd party BER 'asn1-ber' library that exists on Github, but I have not had time to explore it enough, and the description for the project says it is very basic; just enough for the LDAP protocol.

Machine learning, natural language processing, linear algebra. Extra points for bioinformatics-related stuff.

These are things that, obviously, aren't going to be on the top of a core dev team's priority list. They will come with time. But I can't do without them.

There are already libraries to do some of those things. There are for example several linear algebra libraries like gomatrix: http://code.google.com/p/gomatrix/

I don't know so much about bioinformatics, but I know some folks are using Go in that field without too much problem. Of course, the more specialized your needs, the greater the chances you might have to roll your own.

But given that Go 1 has hardly a few months old, this is not very surprising.

I'm working on a Restricted Boltzmann Machine learner for Go. (https://github.com/taliesinb/gorbm).

It is very early days (0.083 days to be exact) but I intend to support Hinton-style "deep learning" within the next few days.

I have a feeling that Go's concurrency features will make it a good fit for various ML workloads. And it's a rare combination of expressive and metal-close, which is good fit for prototyping crunchy algorithms.

I'm basically in the same situation though I've been programming with Go for under 6 months now.

A few features that have really begun to draw me away from Python:

* A step away from object-oriented programming while still providing a way to associate functions with types via methods. I've been tending towards a more functional style in Python lately with functions and simple types instead of heavy OO code. * Static instead of dynamic typing. I find that I rarely actually benefit much from the dynamic typing features in Python and they can often be a source of bugs.

A couple of things I still find myself missing regularly:

* A full-featured unit testing library like Python's unittest * A simple interface for defining rich command-line argument parsers like Python's argparse

> * A full-featured unit testing library like Python's unittest * A simple interface for defining rich command-line argument parsers like Python's argparse

Most people find that the libraries for both unit testng and arg parsing in the Go stdlib are more than enough (IMHO specially the arg parsing lib does way more than I would ever want in a command line program).

But some people have written more "rich" alternatives, see the Unit Testing and Command Line UI sections here:


Some of the libs there are outdated, but that is mostly because in practice almost everyone find using what the standard Go distribution provides works very well. (If there is some functionality you are really missing you could fill an issue, but you would have to make a convincing case as to why it is needed.)

In the workplace we've written a pretty extensive suite of command-line programs in Python using the argparse module. It has some nice features to easily define subcommands as well as mandatory positional arguments, different argument multiplicities, etc. While most simple command line apps don't need this kind of functionality, the kinds of apps we are writing at my employer often do.

Anyway, neither of those cases are by any means a major downer, just two things that have been niggling me from time to time.

Somebody mentioned recently that the code that is part of the `go` tool that handles sub-commands maybe should be factored out and added to the stdlib, it should be relatively straightforward. If you are also interested in that I would recommend filling an issue in the tracker and if a few more people find it useful it probably will happen sooner rather than latter.

if you're talking about someone mentioning it in #go-nuts, that might have been me. I have a reference project to do that here: https://github.com/jordanorelli/multicommand

haven't taken time to turn it into a proper library.

Have you looked into using the built-in testing[1] library for unit tests; it seems very full-featured to me. In Go the flag[2] package contains the command-line argument parsing functionality.

Is it that you didn't know about these libraries, or that they don't meet your requirements? If the latter, what do you require from each of them that they do not already deliver?

[1] http://golang.org/pkg/testing/ [2] http://golang.org/pkg/flag/

I have used (and continue to use) both of these libraries. The testing library works fine but it doesn't include much other than the bare minimum. A more batteries-included library could include some assertion methods to test for value equality/inequality and provide some pre-canned error messages.

As for the flag package, it's fine for simple command-line flags but doesn't have anything to deal with specifying positional arguments. Sure you can get them from the Args() method but you have to basically write another layer of argument handling to deal with them. I like Python's argparse module's approach and flexibility there.

> A more batteries-included library could include some assertion methods to test for value equality/inequality and provide some pre-canned error messages.

For value equality, just use reflect.DeepEqual[1]. The wiki also has a page on table driven tests, which is worth a read[2].

[1]: http://golang.org/pkg/reflect/#DeepEqual [2]: http://code.google.com/p/go-wiki/wiki/TableDrivenTests

Just the other day I stumbled upon that wiki page, it looks like a pretty reasonable technique and I've started adopting it.

Thanks for the pointer to the reflect package, I shall check it out.

What evidence is there, if any, that Go is significantly more performant than Python? I'm not disputing it (it seems to me as though it ought to be). I'm just asking if there is any evidence that it actually is (or will be). If no real evidence yet, I'd still be interested in opinions (with explanations.)

I'm particularly wondering about code other than Web apps with hundreds of simultaneous users, such as single-user statistical AI/machine learning or other performance-demanding apps where Python has to delegate to libraries written in C.

Optimized C/C++ will usually beat out Go code, while Go will usually far outstrip the cpython interpreter[1]. Go itself doesn't really have any optimization for vector processing using SIMD that would make it a "fast" language for doing things like machine learning, machine vision, etc.; hand-coded C/C++ is always going to beat out any other language here. If you're talking python vs. go though, Go will win hands down.

To be honest my personal viewpoint is that we're better off reducing our dependence on SIMD CPU instructions and using GPUs for this sort of highly-parallel processing instead. Most Processors sold these days come with a GPU built-in, so why not make use of these SIMD units, rather than duplicating them on the CPU? This is just my opinion though, and is sort of irrelevant to the question.

Go has an excellent interface to C (cgo) built in, and SWIG can also be used to wrap C/C++ libraries so they are usable in Go. If your aim is core-for-core speed, then your best option is probably to take some highly optimised C/C++ library and create a wrapper that allows you to access it from Go. This route would be at least as performant as any python implementation using the same technique, if not much faster. If your goal is having a highly-concurrent and safe implementation, it is better to implement such libraries from scratch in Go; this is the method most Go libraries use.

Just as with benchmarks, I don't think anyone can give you a non-subjective answer on whether Go will be faster (so take mine with a grain of salt).

[1] http://shootout.alioth.debian.org/u64q/benchmark.php?test=al...

I/O bandwidth between the GPU and main memory is a significant limiting factor, giving SIMD instructions on the CPU an advantage.

For big data sets or complex SIMD algorithms the I/O bandwidth overhead is tiny compared to the speedup achieved by moving the calculation to the GPU.

For the calculations that don't work well on the GPU due to small data sets, simple calculations, or bandwidth constraints we could just run the code in parallel across multiple cores/multiple goroutines.

I think eventually (and this seems to be the direction companies like AMD are headed in) we'll have a couple (maybe up to 4) big cores right next to a bunch of smaller whimpy GPU-like cores which handle SIMD, making SIMD on big cores all but redundant. We're not there yet but AMD and Intel are both working on trying to get their on-chip GPUs to share memory with the processor directly. At the moment the focus for this is mainly gaming performance, so textures, etc. don't have to be copied from main memory to the GPU; the same functionality will greatly benefit GPGPU though. Once we have this heterogeneous architecture and newer faster memory technologies, the problems with using the GPU for SIMD will disappear.

But for the moment, with the real-world technology constraints we have, you're absolutely right on the limitations of GPGPU.

Running code in parallel across multiple cores is going to lose to SIMD. I don't think SIMD is going away anytime soon.

Go's http package is competitive with nginx, so that should give you an idea of the playing field that Go competes in.

Do you have a pointer to some data? I am especially interested in the minimal latency even when serving from memory a response under light usage (100 concurrent users).

This would be at first to provide "backend" services to currently running applications, so the latency overhead is important.

> What evidence is there, if any, that Go is significantly more performant than Python?

You do realize that Go compiles to machine code and Python is a dynamically interpreted language?

The obvious answer is that the Go standard library packages (http://golang.org/pkg/) are written in Go, including crypto code (e.g., http://golang.org/src/pkg/crypto/sha1/sha1block.go), but many of the Python standard libraries are written in C for performance reasons.

For file I/O and network bound applications (e.g., Django) Python is a great choice, but if your app involves any serious computation Go is much, much faster than Python (or Ruby, Perl, PHP etc.).

Python does have excellent 3rd libraries for computation like Numpy but the actual number crunching code is written in C or Fortran.

>You do realize that Go compiles to machine code and Python is a dynamically interpreted language?

Which doesn't matter much if Go's machine code/runtime is inefficient or if Python libs are written in C in the first place whereas Go's are written in Go.

And the sad thing is that have the same syntax obscurity derived of C. Is still not readable (like python or pascal), lack the fast-coding/reading and a lot of things that make python the most fun/readable language ever (IMHO!!).

However, I wish that python have some of the cool things of GO (like gorutines) and other stuff like in cobra-language.com and:

1- Removal of null (using maybe as haskell) 2- Decimal instead of float as default

Still, the new languages refuse to fix #1. #1 Must be declared a goal like have garbage collection right now.

You can't really use Maybe like in Haskell without a static type system.

After all, in Python, there is no actual Null-pointer exceptions; instead, you have TypeErrors that just happen to trigger on None. Even if you had some sort of option type, you would still get runtime errors because there is not enough information to deal with them at compile time.

Now, you could add some sort of abstractions to make checking for None in your code easier. But when your "benevolent" dictator hates folds, you're not getting any advanced features like monads any time soon!

Yep, the sad thing is that you can't get all in a single package.

The type system in Haskell look very good. But the cobra language have a implementation very close and in line with the spirit of python...

>Is still not readable

Wha...? Have you spent any time with it at all?

Will go really multiplex goroutines which are blocking on system calls as well as those blocking on go-level entities (e.g. channels)?

The underlying OS threads will do that, but if goroutines aren't 1-1 with OS threads (which I don't believe they are), how is this achieved? Are all current syscalls intercepted?

What about calls out to external C libs which in turn call blocking syscalls?

(I could test, but if go happens to be running all my goroutines in their own OS threads, I could get a false positive "pass")

According to http://code.google.com/p/try-catch-finally/wiki/GoInternals it does.

The magic trick is that it runs the scheduler just before the blocking call, and if need be it will spawn a new thread to make the blocking call in. That way the thread that thinks it made the blocking call is free to continue running other goroutines.

The Go runtime manages a pool of OS threads with which to make blocking syscalls, while only a few OS threads run Go code.

Calls to external C libs are treated the same as syscalls.

You can read the well commented scheduler code here: http://golang.org/src/pkg/runtime/proc.c

A fast read suggests both syscalls and call to C code (cgocall) are used to switch goroutines.

I don't know if/how Go does this, but what I would do is something like the following: I'd have a thread pool of worker threads which execute the goroutines, so that if a system call blocks the goroutine, the thread will block. The threads would also use work-stealing so that if a thread runs out of tasks (goroutines), they can steal them from another threads task queue. As long as system calls are reasonably rare, this will work with if threads 1-1 with processor cores/hardware threads, but if system calls are common, this this could cause livelock (all threads blocked by system calls, but runnable goroutines cannot run). I imagine that often this would solve itself as system calls unblock the threads when they complete, but to protect against this, I would also have a low priority maintenance thread (or some other mechanism to run this check every so often - perhaps a wrapper around system calls) which checks how many runnable threads are in the thread pool and if there are less than a certain amount (eg number of available hardware threads), then it would spawn additional threads (or, again, perhaps a pool of these backup threads is kept around for cheaper spawning/despawning). Then later as the system calls unblock, the threads can be retired again.

Thats just off the top of my head how I'd handle it. I imagine with some more thought you can come up with a better mechanism.

I tried, and was exited about it, but the lack of easy IDE integration and the lack of a proper debugger were a turn off for me. For now at least.

Two questions to people that use Go:

1. Does Go have a good debugger that is easy to use? i.e. I shouldn't have to mess with the command line, but preferably use it directly from something like eclipse. It should work even in Windows.

2. Is goclipse working properly? Last time I used id, while it would show the syntax fine, the build and run was not working. I had to use the command line.

I think a language should be developed together with its tools. Right now Go is lacking in this department.

Go has gdb support, so any program that uses it as a backend (like ddd) can debug Go code. http://golang.org/doc/gdb

Not as easy to use as a lot of debuggers, but it's widely known.

I don't know about Goclipse; I do all my development on the command line.

> I think a language should be developed together with its tools.

A lot of people will probably not like this answer, but Go's "tools" are the Acme editor and the shell. If you're running on Windows, Acme-SAC (https://code.google.com/p/acme-sac/, or just running Acme under "vanilla" Inferno) is a viable option, and is written in Limbo, a precursor to Go. (It still has some features Go lacks, but is roughly comparable.)

I wouldn't hold my breath on getting former Bell Labs guys to work on a graphical debugger or Eclipse support, so the language is somewhat unlikely to be developed together with those tools.

> I wouldn't hold my breath on getting former Bell Labs guys to work on a graphical debugger or Eclipse support, so the language is somewhat unlikely to be developed together with those tools.

I wouldn't expect them to, and I also really can't understand the appeal of something as complex as an IDE to write code in a language as simple as Go, but Goclipse has been around for a while, and there is support for other IDEs:

http://code.google.com/p/goclipse/ http://go-lang.cat-v.org/text-editors/

I program Go on both emacs and sublime text 2, very good support for both editors.

If you're using Windows, Zeus IDE has pretty decent debugger integration. It's basically just a front end for gdb, but it does let you trace into both Go and C functions in a nice way. Variable display is a little funky, just a console output, but it gets the job done.


No idea about debugging -- but for other "IDE conveniences", combine Sublime Text (syntax highlighting and general text-editing win) with "GoSublime" (auto-completion & more, https://github.com/DisposaBoy/GoSublime )

I know you say you don't want to mess with the command line debuggers, but Go works with gdb [1]. While gdb looks daunting and antiquated at first, once you learn your way around, you'll feel something is missing from IDE based tools.

[1] http://golang.org/doc/gdb

This is probably very obvious, but just a note for anyone interested in using gdb.. if you downloaded 64-bit go, you need to use the 64bit gdb to debug it

If you attempt to use the 32 bit gdb, you'll get errors about the executable you're attempting to debug is in an invalid format

Try Golangide. It has debugging support although It is a front end for gdb . I works also in Windows.

I also suggest you to try gdb from the command line.

> the build and run was not working. I had to use the command line.

The latest Zeus beta includes support for the Go Build, Clean and Run commands via the Zeus workspace.

Here is a video that shows how it works: http://youtu.be/9MeyFdRe6xM

NOTE: Zeus is shareware, runs natively on the Windows and can run on Linux using Wine.

Jussi Jumppanen

Author: Zeus Editor

I feel very bad for someone who has to have an IDE to write Golang. I'm quite sure that there is no functionality provided by Goclipse that is not provided by GoSublime, and even then it's really not necessary. I like it mostly for auto gofmt.

With so many blogs writing praises about Go, I keep wondering how much people learn about programming languages in the universities nowadays.

As a compiled language, Go gets usually compared to the experiences people have with C and C++.

The reality is that 90% of Go features are available in the Pascal family branch of programming languages since the early 80's.

So most features that people enjoy in Go are all features that would already be mainstream, if the Pascal branch had won over C to become mainstream.

Even the ability to use a language like Go for systems programming has been proven in the Native Oberon OS and its descendents (A2) at ETHZ.

What's about CSP (channels/goroutines), static duck typing (Go interfaces) and a very practical standard library?

I had taken a look at Oberon back in 1999 and found it so much worse than Delphi for writing real programs. (which was a precursor of C#/Windows Forms, not Go).

> What's about CSP (channels/goroutines), static duck typing (Go interfaces) and a very practical standard library?

CSP and static duck typing belong to the missing 10% I noted.

Still there are available in other languages that also support native code generation with modules.

> I had taken a look at Oberon back in 1999 and found it so much worse than Delphi for writing real programs. (which was a precursor of C#/Windows Forms, not Go).

Go method definitions are taken from Component Pascal, an extension to Oberon.

Actually I find Delphi much more powerful than Go for large scale development in the enterprise world.

How much code have you written in Go?

You mean besides doing a few contributions to the core Go libraries?

Do you want to have the ticket numbers and Mercurial branches information?

Paulo, I'm very sorry if my question looks a bit rude. The only goal I had is to understand if your opinion is theoretical or based on the real experience.

I don't share your opinion on Go syntax, although, I like Pascal family much more than C and had been using Pascal/Delphi almost exclusively for all my projects until 2003. After that, Delphi became too outdated and I had to switch to other languages.

Also, as I have said before, my knowledge about Oberon and Component Pascal is theoretical, so it might be that you're actually right. Given that these languages are effectively dead (by github criteria: it does not recognize Oberon or Component Pascal, but supports DCPU16 assembly), I don't have a chance to improve this situation (any program written on dead language is theoretical, because it would not be used in prod)

No problem.

I did contribute the initial version of the os.user package for Windows, which was then picked up by the core team. Also started to add Windows to the exp.gui/draw packages, but gave up on them when they were dropped from Go 1.

I find github criteria a bad one, as many people I know don't even care about it.

Oberon is still pretty much alive for ETHZ students as Active Oberon, just check the list of possible assignments, http://www.nativesystems.inf.ethz.ch/WebHomeProjects.

You can see the original method syntax for Component Pascal here, http://www.oberon.ch/pdf/CP-Lang.pdf, section 10.2.

I still lurk in the Go mailing list as a language geek, but lost interest, as the language feels too minimalist to my taste, given my experience with other languages.

In a way I belong to the group Rob recently described as C++ programmers. Given my experience in language design, using Go makes me feel I am back in high school with Turbo Pascal 6.0.

But Google's weight might nevertheless help Go become mainstream, who knows.

Something that's said a lot about Go is that it's not that it brings a lot of new things to the table but that it it brings together many great features in to a clean and well thought out language.

The batteries-included toolchain including gofmt and the go command are another pleasure while developing.

As far as languages I've dabbled with in the last few years Go was definitely the easiest to get started with in terms of the development toolchain.

Maybe I'm not understanding it correctly, but on the point about "it's ok to block", does that mean Go will continue to serve other requests normally, but at the point of the blocking code, it automatically has a "callback" to the next command? (effectively saving the programmer the pain of having to write code in callback fashion)

Having no prior experience with Go, I found the rest of the article informative!

Yeah, Go has a concept called Goroutines which are like lightweight threads. The system multiplexes Goroutines onto system threads. This means if one Goroutine blocks while waiting on IO, the Go scheduler will automatically select another Goroutine to run while the first Goroutine waits on IO.

Writing your code in blocking style is just easier to follow than the callbacks used in Node and other asynchronous event servers.

My point was that you make a goroutine and within that goroutine you do stuff sequentially and you block if you need to.

Let's not forget excellent documentation that links directly to the source code.

CSP is an interesting take on concurrency but lends a degree of opacity to the scheduling of tasks. So far (working in Go) in minor (or well understood patterns) it is a non-issue, but I wonder what would happen at large scale. It is also worth noting that in Go 1 runtime, switching from 1 "processor" to N can certainly alter the behavior of your program e.g. the same precise [1] binary may lead to CSP/Go's version of "deadlock" e.g. "all goroutines are sleep" or not depending on simply 1 bit of difference in the binary. The current runtime also gives rise to some interesting (and very unintuitive) performance differences when hacking with the CSP mechanism e.g. peppering GO sources with unnecessary sleeps, etc. to hack the scheduler.

[1]: well nearly the same. Somewhere in the binary, a call to set maxprocs is present. Same exact program differing only in the param to this call (i.e. 1 vs 2).

We (tinkercad) have actually ended up running once process per core and limiting the number of concurrent OS threads. This gives significantly faster task switching times and is more performant from a GC perspective. Given our system is highly distributed anyway shared memory would mostly be an optimization and not a primary facility.

Go is interesting in that doesn't yet support Generics... but might some day.

The reason that interest me is that I like Generics aka parametric polymorphism but I feel like Scala, Haskell and OCaml take it almost to the extreme particularly since those languages also have type inference. So it can be overwhelming for a new user.

That being said if Rust was more mature I would prefer it over Golang (here is another hacker news comment on this: http://news.ycombinator.com/item?id=1951467).

> And the fact that it's missing exceptions seems like a win because I much prefer dealing with errors when they occur.

This person doesn't seem to have much experience with error handling.

You shouldn't deal with errors the way you prefer it, you should deal with them the right way. Sometimes, it's where they occur, but very often, it's somewhere up the stack.

We learned this lesson in the 90's.

It seems odd to assume he has that opinion because of lack of experience, considering we're discussing a language developed by people like Rob Pike, who share his opinion on error handling and can hardly be described as unexperienced.

And people like Ken Thompson.

Accusing the author of this article of being "inexperienced" is also very amusing: http://en.wikipedia.org/wiki/John_Graham-Cumming

And even Java and C++ luminaries like Bruce Eckel have come out in support of Go's error handling and against exceptions.

Not sure that I deserve to be mentioned in the same breath as Ken Thompson.

And Go lets you do that. You just return the error.

Try writing a few things in Go. I very much doubt you'll respond like this afterwards.

So I assume it has multiple returns? Some smart built in error class I could actually see that removing the need for exceptions, yes.

One new way I've found interesting in obj c is giving functions (an) error handling block argument(s). It nicely does what java unhandled exceptions warnings do: make the user aware of his actions.

Yes, it can return a tuple, in Python-speak, and has a pre-declared error type. http://golang.org/ref/spec#Errors

I think a lot of people would disagree with your view that non-local exits, of which exceptions are a type, is the right way to go.

Here is a good detailed analysis why exceptions might be a worse choice: http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/35294...

I think the author addresses this quite effectively in the article starting with:

"I'm sure some people reading this are going to say "But language FrobBub has had NoduleFoos for years cretin!"."

Priceless :-).

does Go have package management? How do you guys find 3rd party libraries?

You can use 'go get' to download and install packages direct from repository links, and there is a reasonable definitive list of open sourced libraries available here:


There's also the Go project dashboard: http://godashboard.appspot.com/project

Also gopkgdoc maintains a list of Go packages:


The go command will install third party packages from source code repositories if you know about them. There is a dashboard of packages on the go web site but I believe further work is needed for discovery on the command line.

Applications are open for YC Summer 2019

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