Currently sitting in the Go language keynote in JAOO.
Go was created to handle Google needs:
- Compilation speed
- Efficient
- Fit for the current set of challenges we face
Go is meant to be Simple, Orthogonal, Succinct. Use C syntax, but leave a lot of complexity behind.
This make sense, because C/C++ is horrible for a lot of reasons, because of complexity added to it over the years. Actually, the major problem is that C/C++ mindset are literally designed for a different era. Take into account how long it can take to build a C++ application (I have seen no too big apps that had half an hour build times!), and you can figure out why Google wanted to have a better model.
Nice quotes:
- Programming shouldn’t be a game of Simon’s Says
- Difference between seat belts & training wheels – I am going to use that a lot.
I find Go’s types annoying:
- [variable name] [variable type] vs. [variable type] [variable name]
- And []int vs. int[]
I like the fact that is uses garage collection in native code, especially since if you reference a variable (including local) it will live as long as it has a reference to. Which is a common mistake in C.
It also have the notion of deferring code. This is similar to how you can use RAII in C++, but much more explicit, which is good, because RAII is always tricky. It very cleanly deals with the need to dispose things.
All methods looks like extension methods. Data is held in structures, not in classes. There is support for embedding structures inside one another, but Go isn’t an OO language.
Interfaces work for all types, and interfaces are satisfied implicitly! Much easier to work, think about this like super dynamic interfaces, but strong typed. Implies that we can retrofit things afterward.
Error handling is important, and one of the major reasons that I moved from C++ to .NET. Go have two modes, the first is error codes, which they use for most errors. This is especially nice since Go have multiple return values, so it is very simple to use. But it also have the notion of panics, which are similar to exceptions. Let us take a look at the following test code:
package main
func test() {
panic("ayende")
}
func main() {
test()
}
Which generate the following panic:
panic: ayende panic PC=0x2ab34dd47040 runtime.panic+0xb2 /sandbox/go/src/pkg/runtime/proc.c:1020 runtime.panic(0x2ab300000000, 0x2ab34dd470a0) main.test+0x47 /tmp/gosandbox-a9aaff6c_68e6b411_26fb5255_aa397bb1_6299a954/prog.go:5 main.test() main.main+0x18 /tmp/gosandbox-a9aaff6c_68e6b411_26fb5255_aa397bb1_6299a954/prog.go:8 main.main() mainstart+0xf /sandbox/go/src/pkg/runtime/amd64/asm.s:78 mainstart() goexit /sandbox/go/src/pkg/runtime/proc.c:145 goexit()
I got my stack trace, so everything is good. Error handling is more tricky. There isn’t a notion of try/catch, because panics aren’t really exceptions, but you can recover from panics:
package main import ( "fmt" ) func badCall() { panic("ayende") } func test() { defer func() { if e := recover(); e != nil { fmt.Printf("Panicing %s\r\n", e); } }() badCall() fmt.Printf("After bad call\r\n"); } func main() { fmt.Printf("Calling test\r\n"); test() fmt.Printf("Test completed\r\n"); }
Which will result in the following output:
Calling test Panicing ayende Test completed
All in all, if I need to write native code, I’ll probably go with Go instead of C now. Especially since the ideas that it have about multi threading are so compelling. I just wish that the windows port would be completed soon.