Skip to content

Instantly share code, notes, and snippets.

@anantjain-xyz
Last active August 29, 2015 14:18
Show Gist options
  • Save anantjain-xyz/d2c089f3e8cb6192f42a to your computer and use it in GitHub Desktop.
Save anantjain-xyz/d2c089f3e8cb6192f42a to your computer and use it in GitHub Desktop.
Small snippets/notes collected while going through essential-go course at https://www.kajabinext.com/courses/1-essential-go

Go Notes

"Go is for the essentialist"

  • Language
  • Libraries
  • Tooling

First program

Go programs can be of two types - commands and packages. Commands usually have a main function where execution starts.

  • go build - builds the executable in the same directory
  • go install - builds the executable and puts it in the $GOtripleATH/bin
  • go run - runs the program

Go Tools

  • go fmt is the standard way to format your code.
  • godoc -http=:8080 is how you can serve up a local copy of docs
  • godoc.org for all the documentation

Variables

var greeting string = "Hello world"

You can drop the string here since greeting is being initialized - go can infer that it is of type string. So

var greeting = "Hello world"

var d, e, f = 1, 2.0, "hello"

Drop var and use :=

course := "Essential Go"
x, y, z := 1, 3, 2

In go, any identifier that starts with an uppercase is public and available for use by other packages. Example: fmt.Println

In this example, Version and author are global variables

package main
var Version = "0.0.1"
var author = "@anant90"
func main() {
	...
}

You can also group variables or constants together:

var (
	author = "@anant90"
	Version = "0.0.1"
)

const (
	CCVisa = "Visa"
)

Control Structures

if true == true {
	fmt.Println("true is true")
} else {
	fmt.Println("true is false")
}

for i := 0; i < 20; i++ {
	fmt.Println("Go!")
}

for {
	fmt.Println("Infinite Loops")
	break
}

j := true
for j {
	fmt.Println("This should happen only once")
	j = false
}

Functions

func double(n int) int {
	return n + n
}

func function_name(argument type) return_type {}

func parseName (name string) (first, last string) {
	parsed := string.Split(name, " ")
	return parsed[0], parsed[1]
}

use _ in function calls to discard a result.

first, _ := parseName("Anant Jain")

Anonymous function:

greet := func(name string) {
	fmt.Println("Hello", name)
}

greet("Anant")

Pointers

func triple( n*int) {
	*n = *n * 3
}

num := 5
triple(&num)
fmt.Println(num)

HTTP File Server

package main

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

var port int

func main() {
	// We will get the port through a cli flag
	flag.IntVar(&port, "port", 3000, "The port to run the file server on")
	flag.Parse()

	fmt.Printf("Serving files on localhost:%v\n", port)
	err := ServeStatic(port)
	if err != nil {
		log.Fatalln(err)
	}
}

func ServeStatic(port int) error {
	host := fmt.Sprintf("localhost:%v", port)
	return http.ListenAndServe(host, http.FileServer(http.Dir(".")))
}

Arrays and slices

var nums [5]int
fmt.Println("empty:", nums)
nums[4] = 100

Slices are abstractions on top of arrays

ints := []int{1,2,3,4,5}
ints = append(ints, 6)
ints[:2]
ints[4:]
ints [2:4]

for i, val := range ints {
	fmt.Println(i, val)
}

Maps

Maps can be initialized with the make builtin

age := male(map[string]int)

age["jeremy"] = 24
age["jordie"] = 21
age["josh"] = 27
fmt.Println(age)

delete(age, "jeremy")
m := map[string] int {
	"jeremy": 24,
	"jordie": 21,
}

for n, a := range m {
	fmt.Prinf("%v is %v years old", n ,a)
}

JSON Parser

Specify interface as type when you do not know the return type - it may act like the void type

panic is another way to tell go to stop executing. Discouraged for use in libraries. It is like throwing an exception.

Check out how to define a type as well

c["name"].(string) explicitly tries to convert c["name"] to string type

// To make use of some of our collections knowledge, we will parse some JSON
// configuration into our application.
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
)

// we will create a function called LoadConfig that will load up our JSON
// configuration file
func LoadConfig(path string) (map[string]interface{}, error) {
	var m map[string]interface{}
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return m, err
	}

	err = json.Unmarshal(data, &m)
	return m, err
}

func main() {
	config, err := LoadConfig("config.json")
	if err != nil {
		panic(err)
	}

	fmt.Println(config)
}

Types and Structs

type point struct {
	x, y int
}

p := point{20, 40}

p.x
p.y

type rect struct {
	pos point
	width int
	height int
}

##Constructor:

func newPoint(x, y int) point {
	return point{x, y}
}

r := rect {
	pos: NewPoint(20,40),
	width: 100
	height: 200
}

##Method on a struct:

func (r rect) area() int {
	return r.width * r.height
}

fmt.Println(r.area())

Interfaces

Animal is an interface. Any type which implements the Pet and Name function can be considered an Animal.

package main

import "fmt"

type Animal interface {
	Pet()
	Name() string
}

type Cat struct {
	name string
}

func (c Cat) Pet() {
	fmt.Println("prrrrrr")
}

func (c Cat) Name() string {
	return c.name
}

type Dog struct {
	name string
}

func (d Dog) Pet() {
	fmt.Println("woof woof")
}

func (d Dog) Name() string {
	return d.name
}

func Compliment(a Animal) {
	fmt.Println("Great Job", a.Name())
	a.Pet()
}

func main() {
	c := Cat{"johnny larry"}
	Compliment(c)

	d := Dog{"trixie belle"}
	Compliment(d)
}

Example: Static Site Generator

os.Args[0] is always the path of the binary being run.

https://github.com/codegangsta/essential-go/tree/master/pub

Key things:

  • Generating markdown
  • Package Building
  • Go Templates

Concurrency

  • Concurrency != Parallelism
  • Go by default runs on one core
  • The scheduler is really smart

Primitives: Goroutines, Channels, Select statement

Goroutines

say is a function which prints a string, then sleeps for 100 ms

go say("go")
go say("for it")

Channels

c := make(chan string, 4)
c <- "Hello"
c <- "world"

v := <-c
fmt.Println(v)

Select
======

Multiplex channel results (Events from Goroutines)

func main() {
	done := make(chan bool)

	go func() {
		fmt.Println("Running...")
		time.Sleep(250 * time.Millisecond)
		done <- true
	}()

	<- done
}

func waiton(done chan bool) {
	select {
		case <-done:
			fmt.Println("Finished")
		case <- time.After(500 * time.Millisecond):
			fmt.Println("Timeout")
	}
}

Example: Job Queue

https://www.kajabinext.com/courses/1-essential-go/lessons/16273-example-job-queue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment