Skip to content

Instantly share code, notes, and snippets.

@jvmsangkal
Last active December 28, 2016 09:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jvmsangkal/39ed4e91b7a294b17457 to your computer and use it in GitHub Desktop.
Save jvmsangkal/39ed4e91b7a294b17457 to your computer and use it in GitHub Desktop.
Go syntax notes

Go Notes

Running Go

$ go run <filename>.go

Or

$ go build <filename>.go
$ ./<filename>

Main Function

package main

func main() {

}

Output

import "fmt"
...
fmt.Println()

func main() {
    var i int
    var f float64
    var b bool
    var s string
    fmt.Printf("%v %v %v %q\n", i, f, b, s)
}

Using Packages

import (
    "fmt"
    "time"
    "math/rand"
)

func main() {
    fmt.Println("The time is", time.Now())
    fmt.Println("My favorite number is", rand.Intn(10))
}

exported names begin in capital letter

Functions

func add(x int, y int) int { //can ommit the type of x because it's the same as y
    return x + y
}

hypot := func(x, y float64) float64 {
    return math.Sqrt(x*x + y*y)
}

Multiple return function

func swap(x, y string) (string, string) {
    return y, x
}

Named return values

use only in short functions

func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return
}

Variables

var can be use in package and function level

var c, python, java bool

var i, j int = 1, 2

the type can be ommited when initializing variable

var c, python, java = true, false, "no!"

inside a function, := can be used instead of var

k := 3
c, python, java := true, false, "no!"

factored variable declaration

var (
    ToBe   bool       = false
    MaxInt uint64     = 1<<64 - 1
    z      complex128 = cmplx.Sqrt(-5 + 12i)
)

variables not initialized will be assigned their zero values 0 for numbers false for bool "" for string

Type Casting

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

Or, put more simply:

i := 42
f := float64(i)
u := uint(f)

Type Inference

i := 42           // int
f := 3.142        // float64
g := 0.867 + 0.5i // complex128

fmt.Printf("i is of type %T\n", i)

Constants

const Pi = 3.14

Loops

For

sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

// You can leave the pre and post statements empty
sum := 1
for ; sum < 1000; {
    sum += sum
}

While

sum := 1
for sum < 1000 {
    sum += sum
}

Forever

for {

}

Control Structures

If

if x < 0 {
    return sqrt(-x) + "i"
}

If with short statement

//the short statement is executed before the condition
if v := math.Pow(x, n); v < lim {
    return v
}

Short statement variables can only be accessed inside the if..else statement

If .. else

if v := math.Pow(x, n); v < lim {
    return v
} else {
    fmt.Printf("%g >= %g\n", v, lim)
}

Switch

// the case breaks automatically. if you want it to continue use "fallthrough"
switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
    case "linux":
        fmt.Println("Linux.")
    default:
        // freebsd, openbsd,
        // plan9, windows...
        fmt.Printf("%s.", os)
}

//switch with no condition is same as switch true
t := time.Now()
switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
}

Defer

//defer executes the function after the surrounding function returns
defer fmt.Println("world")

When there is more than one deferred function calls they are executed in stack(last-in-first-out)

Pointers

    var p *int

Example:

p := &i         // point to i
fmt.Println(*p) // read i through the pointer
*p = 21         // set i through the pointer
fmt.Println(i)  // see the new value of i

Structs

type Vertex struct {
    X int
    Y int
}// can also be factored to X, Y int

...

v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X)

Struct Pointer

v := Vertex{1, 2}
p := &v
p.X = 1e9
fmt.Println(v)

Struct Literals

var (
    v1 = Vertex{1, 2}  // has type Vertex
    v2 = Vertex{X: 1}  // Y:0 is implicit
    v3 = Vertex{}      // X:0 and Y:0
    p  = &Vertex{1, 2} // has type *Vertex
)

Arrays

var a [10]int

Slices

s := []int{2, 3, 5, 7, 11, 13}

Slicing Slices

s[1:4] == [3 5 7]
s[:3] == [2 3 5]
s[4:] == [11 13]

Making Slices

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

Nil Slices

var z []int // len=(z)=0, cap(z)=0

Appending to Slices

append(z, 0, 1, ...)

Range

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

...

for i, v := range pow {// i has index, v has the value
    fmt.Printf("2**%d = %d\n", i, v)
}

you can assign the index or value to _ to skip it you can remove ', v' to get the index only

Maps

type Vertex struct {
    Lat, Long float64
}

var m map[string]Vertex

...

m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
    40.68433, -74.39967,
}

Map Literals

var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": Vertex{
        37.42202, -122.08408,
    },
}

or simply

var m = map[string]Vertex{
    "Bell Labs": {40.68433, -74.39967},
    "Google":    {37.42202, -122.08408},
}

Mutating Maps

Insert or update an element in map m:

m[key] = elem

Retrieve an element:

elem = m[key]

Delete an element:

delete(m, key)

Test that a key is present with a two-value assignment:

elem, ok = m[key]

Function closures

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

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
}

Methods

Struct Methods

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Scale(f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

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

func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}

Type Methods

type MyFloat float64

func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

Interfaces

type Abser interface {
    Abs() float64
}

func main() {
    var a Abser
    f := MyFloat(-math.Sqrt2)
    v := Vertex{3, 4}

    a = f  // a MyFloat implements Abser
    a = &v // a *Vertex implements Abser

    // In the following line, v is a Vertex (not *Vertex)
    // and does NOT implement Abser.
    a = &v

    fmt.Println(a.Abs())
}

type MyFloat float64

func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

type Vertex struct {
    X, Y float64
}

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

Stringer

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

Errors

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}

func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
}

Readers

func main() {
    r := strings.NewReader("Hello, Reader!")

    b := make([]byte, 8)
    for {
        n, err := r.Read(b)
        fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
        fmt.Printf("b[:n] = %q\n", b[:n])
        if err == io.EOF {
            break
        }
    }
}

Web Servers

package main

import (
    "fmt"
    "log"
    "net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(
    w http.ResponseWriter,
    r *http.Request) {
    fmt.Fprint(w, "Hello!")
}

func main() {
    var h Hello
    err := http.ListenAndServe("localhost:4000", h)
    if err != nil {
        log.Fatal(err)
    }
}

Handlers

http.Handle("/string", String("I'm a frayed knot."))
http.Handle("/struct", &Struct{"Hello", ":", "Gophers!"})

Goroutines

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}

Channels

func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y)
}

Buffered Channels

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment