changeValue(int* i) { *i = 12; } int array[3] = {0, 1, 2}; printf("%d", *(array + 2 * sizeof(int)); // 2 Direct access to memory locations. It's only way to pass references around instead of copies.
80s and nd a bunch of great programmers. Say, Ken Thompson, Rob Pike, people like that. Marinate them in Bell Labs for 30 years, during which time they code in C, keep developing Unix, invent Plan 9, UTF-8, and other wonderful things. Take them out, seduce them with Python, wow them with Google-scale computing. Add more amazing programmers (Brad Fitzpatrick for example), stir in Google’s near- unlimited resources. Ask them how they would do C now, if they could start from scratch. credits by Graham King (https://www.darkcoding.net/software/go-lang-after-four-months/)
oats, booleans: var n int64 = 23 var n1 int = 28 var p float64 = 9.75 var r bool = true Go provides a higher level string type: var s string = "Hello" s = s + " Devfest" // s = "Hello devfest" s = s[1:5] // ello
i < 10; i++) numbers[i] = 0; length is not a property shortcut for pointer arithmetic (non initialized, out of bound errors write in memory) Arrays in Go: var a[3]int = [3]int{1,2,3} var b[3]int = [...]int{1,2,3} a[2] // 3 len(a) // 3 Fixed lenght Passed by value
malloc(sizeof(int)) // lives in the heap, need to be freed int* f() { int b = 5; return &b; // BAD! } e cient the dev is in control of what lives in the stack and what in the heap easy to forget the lifecycle of malloc'ed objects
good: the dev is in control of what is passed by value and what by reference func f() int* { int result = 28 return &result //result stored in the heap } garbage collected pointers are references to live objects: there is no way to mess up with the memory
Pointers. A pointer value of any type can be converted to a Pointer. A Pointer can be converted to a pointer value of any type. func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) } Pointer arithmetic f := unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Offsetof(s.f))
between di erent types requires explicit conversion int n = 1400.5 / 'c'; // ????? variables are initialized with zero values MyStruct* s = (MyStruct*) malloc(sizeof(MyStruct)); memset(s, 0, sizeof(MyStruct)); no pointer arithmetic MyStruct s; int* i = (&s + 3 * sizeof(int)); // ????
around ifs Type inference, short variable declaration var s = "devfest" s1 := "devfest" // only inside a function Multiple return values (also, named return values) func f(arg int) (res int, err error) { /* ... */ }
strings) for index , _ := range(mySlice) { /* ... */ } defer() to call nalizing operations inside a function no break in switch, switch cases can be conditions
char title[50]; char author[50]; }; Book b; // a mess memset(&b, 0, sizeof(Book)); strcpy(b.title, "Golang"); Go Structs type book struct { title string author string } var b book // zero value var b1 book{title:"Golang"} // literal initializer
type Driveable interface { func Drive() int } func (c Car) Drive (km int) {/* */} func (b Bike) Drive (km int) {/* */} var c Car{wheels : 4} var d Driveable = c Can be checked c, ok := d.(Car) // true c, ok := d.(Bike) // false switch d.(type) { case Car: // }
Multiple les can belong to the same package The visibility is toggled by uppercasing / lowercasing Every le belongs to a package package mypackage var Exported int var notExported string
Condition variables Semaphores Multithreading is today's goto : - hard to read / understand - di cult to debug What we need is a better solution for concurrency, easier to understand and to handle
runtime. go myFunction() Why lighter? smaller (altough variable) stack many goroutines can be share a single os thread scheduling not invoked periodically but as a consequence of synchronization It is practical to create hundreds of thousands of goroutines in the same address space
ch := make(chan int) We can send values to a channel ch <- 23 or receive from a channel res := <- ch or just check if send has happened <- ch Channels can be bu ered or unbu ered. Sending on a full channel blocks the sender, receiving from an empty channel blocks the receiver.
:= make(chan int) incremented := make(chan int) go func() { for i := 0; i < 100; i++ { source <- i } close(source) }() go func() { for s := range source { incremented <- s + 1000 } close(incremented) }() for res := range incremented { fmt.Println(res) } } Run
# command executable pkg/ linux_amd64/ github.com/fedepaol/example/ stringutil.a # package object src/ github.com/fedepaol/example/ hello/ hello.go # command source stringutil.go golang.org/x/image/ bmp/ reader.go # package source writer.go # package source Most Go programmers keep all their Go source code and dependencies in a single workspace
and thrown away executables are compiled and left in the current dir go install package non main packages are deployed in $GOPATH/pkg executables in $GOPATH/bin go get package (as in github.com/fedepaol/example/hello) downloads the package and its dependencies installs it
libc. The go runtime is linked together with the executable. The absence of external dependencies makes the deployement a lot easier than a C executable.
Interactive Tutorial tour.golang.org (http://tour.golang.org) E ective go golang.org/doc/e ective_go.html (https://golang.org/doc/e ective_go.html) Mailing list groups.google.com/forum/#%21forum/golang-nuts (https://groups.google.com/forum/#%21forum/golang-nuts)