Go(lang)

From Adam Colton
Jump to navigation Jump to search

I should contribute Go samples here: https://www.algorithm-archive.org/chapters/introduction/how_to_contribute.html

http://go-search.org/tops

https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/

http://eefret.me/making-sublime-your-golang-ide/

http://godashboard.appspot.com/project

https://github.com/chsc/GoGL

Here is the whole spec. This is actually a really good quick refresher.

https://github.com/eawsy/aws-lambda-go

http://libs.club/golang/

http://www.meetup.com/Ann-Arbor-Gophers/?scroll=true

https://github.com/gobwas/ws - Another websocket library.

https://github.com/dmulholland/clio/blob/master/go/example/main.go command line tool. I may like this better than the one I've been using.

Maybe this instead of gothic.

To-do / learn

  • Go modules
  • Create Android app

Libraries

Meta

Web Frameworks

In the past I looked at Negroni, Goji, Gin and Beego. Did not like these. Want to look at

I should be able to get Gothic to play nice with them.

Other

Basics

  • Uses func main (similar to C), a program also starts in package main

That thing you always forget

http://play.golang.org/p/rbuFUCsIY0

 type foo []string
 
 func (f *foo) Add(s string) {
   *f = append(*f, s)
 }

unsafe conversion

 *(*int32)(unsafe.Pointer(&a))

coverage report

 go test -coverprofile=coverage.out 
 go tool cover -html=coverage.out -o=coverage.html

or

 go test -coverprofile=coverage.out && go tool cover -html=coverage.out -o=coverage.html && rm coverage.out

https://golang.org/pkg/plugin/

Import

 import (
   "packageA"
   "packageB"
 )
  • Unused imports throw an error

Functions

Basic

 func add(x int, y int) int {
   return x + y
 }

Multi-return

 func swap(a, b int) (int, int) {
   return b, a
 }

Named results

 func sumProd(x, y int) (sum, prod) {
   sum = x + y
   prod = x * y
   return
 }

Function are values too and can be assigned, referenced and passed around.

Closure

 func adder() func(int) int {
   sum := 0
   return func(x int) int {
     sum += x
     return sum
   }
 }

Variables

Go is strongly typed, but uses inference as much as possible. So this is possible

 var x int
 x = 5

But better is

 x := 5

Types

  • bool
  • string
  • int{8,16,32,64}
  • uint{8,16,32,64}, uintptr
  • byte (same as uint8)
  • rune (same as uint32, represents unicode point)
  • float{32,64}
  • complex{64,128}

Pointers

Go has pointers, but no pointer arithmetic.

 v := Vertex{1,2}
 p := &v
 p.X = 5

Structs

A Struct (this can be set in package space, I don't know if it can be declared in a function)

 type Vertex struct {
   X int
   Y int
 }
 v := Vertex{1,2}
 fmt.Println(v.X)

A struct literal.

 var (
   name := "Adam"
   i := 1
 )

Structs are the closes thing to classes in Go

Methods

Methods take a struct before the method name, this is the struct they are a method on

 func(v *Vertex) Abs() float64 {
   return math.Sqrt( v.X*v.X + v.Y*v.Y )
 }

You can define a method for any type in your package, but not for a struct from another package.

Interfaces

Interfaces define a set of attribute. A struct satisfies an interface when it has all the attributes the interface defines. Golang.org reference

For

The only looping structure is for.

Traditional

 for i := 0 ; i<10 ; i++ {
   fmt.Println(i)
 }

As While

 i: = 5
 for i<100 {
   i += 3
 }

Infinite Loop

 for {
   fmt.Println("There is no escape")
 }

Range

 a := []int{3,1,4,1,5,9,2,6,5}
 for i,v := range a {
   fmt.Println(i, v)
 }

Range without index. This can be important because unused variables throw errors.

 a := []int{3,1,4,1,5,9,2,6,5}
 for _,v := range a {
   fmt.Println(v)
 }

If

Basic

 func abs(x float64) float64 {
   if x<0 {
     return -x
   }
   return x
 }

Much like for, there is a space for a statement scoped to the if block before the conditional

 func pow(x, n, lim float64) float64 {
   if v := math.Pow(x,n) ; v < lim {
     return v
   }
   return lim
 }

Else. Not shown here, but the pre-statement is scoped to the else block as well

 if foo {
   fmt.Println("Foo is true")
 } else {
   fmt.println("Foo is not true")
 }

New

New allocates something and returns a pointer.

 v := new(Vertex)
 x.X = 5

Maps

Like a dictionary, must be created with make

 m = make(map[string]int)
 m["Adam"] = 28
 m["Lauren"] = 26

Map literal

 var m = map[string]int{
   "Adam": 28,
   "Lauren": 26,
 }
 var n = map[string]Vertex{
   "Home": {10,20}
   "Work": {25,40}
 }

Delete (using previous examples)

 delete(m, "Adam")

Slice

A slice points to a slice of an array. It does this with a pointer and a length

 s: = []int{3,1,4,1,5,9,2,6}

Switch

 switch pre := something; condition{
   case "A":
     // handle A
   case "B":
     //do B stuff
     fallthrough
   case "C":
     //do stuff for C and B
   default:
     //default stuff
 }

A switch with no condition evaluates each case, can act like a large if-else chain

 switch{
   case a > 10:
     //do something
   case a > 5:
     //do something else
     //this is actually 10 >= a > 5
   default:
     //all others, final else
 }

Go Routines

I love these!

Prefix a function/method call with go and it's run in something like a thread, but with less overhead. Communication is done over channels

  • ch := make{chan int}
  • ch := make{chan int, 3} //make a channel with a buffer of length 3
  • ch <- v //Send v to channel
  • v := <-ch //Receive from channel and assign to v\
  • close(c)
 func sum(a []int, c chan int) {
   sum := 0
   for _, v := range a {
     sum += v
    }
    c <- sum  // send sum to c
 }
 ...
 c := make{chan int, 2}
 go sum( []int{1,2,3,4,5}, c)
 go sum( []int{6,7,8,9,10}, c)
 x, y := <-c, <- c

A channel can be used a for range and the for will last as long as the channel is open Good Example. Closing isn't necessary, it will get garbage collected if appropriate, even when open.

Select

Select is like a switch but with channels for cases. It blocks until one of the cases is met (channel can read or write), then executes that block Documentation. Default works as expected, good for sleep is you don't want a select in a loop to consume too many resources.

Generics (and stuff)

Go doesn't have generics, or templates or convenient type casting. Instead, it does this.

Server Stuff

Install Golang

https://golang.org/doc/install

Gopath

 export GOPATH=gopath (something like $HOME/go)

http://golang.org/doc/code.html#GOPATH

Exec

main.go

 package main
 
 import (
   "bufio"
   "fmt"
   "os/exec"
 )
 
 func main() {
   cmd := exec.Command("go", "run", "callme.go")
   out, err := cmd.StdoutPipe()
   if err != nil {
     panic(err)
   }
   rd := bufio.NewReader(out)
   cmd.Start()
   s, _, _ := rd.ReadLine()
   fmt.Println(string(s))
 }

callme.go

 package main
 
 import (
   "fmt"
 )
 
 func main() {
   fmt.Println("Hello")
 }

ScrewTypeSafety

 func ScrewTypeSafety(i interface{}, o uintptr) {
   p0 := unsafe.Pointer((uintptr)(unsafe.Pointer(&i)) + uintptr(8))
   p1 := (*(*uintptr)(p0)) + o
   *(*int)(unsafe.Pointer(p1)) = 70
 }

Passing Slice Pointers

 package main
 
 import (
   "fmt"
 )
 
 func main() {
   var b []byte
   mod(&b)
   fmt.Println(b)
 }
 
 func mod(b *[]byte) {
   f := []byte{12, 34}
   *b = f
   fmt.Println(f)
 }

footer