Python | Go |
---|---|
dynamically typed | statically typed |
interpreted | compiled |
whitespace | curly braces with strict layout |
Objects with inheritance | Structs with embedding and interfaces |
pure | pragmatic |
package main
import "fmt"
func main {
fmt.Println("Hello NZPUG")
}
package main
// No such thing as "from foo import bar"
import (
"bufio"
"fmt"
"io"
"os"
)
// Note how the type comes after arg name in argument list
func countWords(source io.Reader) (map[string]int, error) {
counts := make(map[string]int) // What's this?
scanner := bufio.NewScanner(bufio.NewReader(source))
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
counts[scanner.Text()]++ // has ++ but it's not crazy like C
}
// returning errors is a common pattern
return counts, scanner.Err()
}
func main() {
counts, err := countWords(os.Stdin) // type inference!
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
for word, count := range counts { // "for" does all types of loops
if count > 1 {
// print anything, just like Python
fmt.Println(word, count)
}
}
}
if err != nil ...
Structs!
(with methods)
type Rectangle struct {
length, width int
}
func (r *Rectangle) Area() int {
return r.length * r.width
}
No: composition and delegation!
(Embedding with syntactic sugar)
package main
import "fmt"
type Person struct {
FirstName string
LastName string
}
func (p *Person) FullName() string {
return p.FirstName + " " + p.LastName
}
func (p *Person) Intro() string {
return p.FullName()
}
type Man struct {
Person
}
func (m *Man) Intro() string {
return "Mr " + m.LastName
}
func main() {
p := Person{"Some", "Human"}
fmt.Println(p.FullName(), ":", p.Intro())
m := Man{Person{"John", "Smith"}}
fmt.Println(m.FullName(), ":", m.Intro())
}
Output:
Some Human : Some Human John Smith : Mr Smith
Juju easily has 1000's of concurrent Goroutines per host
package main
import "fmt"
func produce(c chan int) {
for i := 0; i < 10; i++ {
c <- i
}
close(c)
}
func consume(c chan int, done chan bool) {
for i := range c {
fmt.Println(i)
}
close(done)
}
func main() {
c := make(chan int)
done := make(chan bool)
go produce(c)
go consume(c, done)
<- done
}
# Installing a program or external package
go get github.com/foo/bar
# Make some changes...
cd $GOPATH/src/github.com/foo/bar
# edit, edit, edit
# Run all the tests
go test ./..
# Build and install again
go install ./..
A build gives you a statically linked binary (almost).
$ ldd wordcount not a dynamic executable $ ldd juju linux-vdso.so.1 => (0x00007ffff9755000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f14096d5000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f140930f000) /lib64/ld-linux-x86-64.so.2 (0x00007f1409915000)
Just copy the file and you're done.