Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Overview

Installation

brew install go


Add it to your Path

Add the following to your .bashrc  or zshrc file

Code Block
export PATH="$PATH:$(go env GOPATH)/bin"


Configuration

Setup default workspace

...

go build

Install it

go install

Creating a Module

Create a go.mod file

Code Block
titlego.mod
module mymodule
go 1.18


Add Libraries

go get github.com/qopher/go-torrentapi


Commands

CommandDescription
go run <src.go>Run some code
go buildCompile the code. Outputs to local folder. Executable has folder as name.
go installCompiles and places the output in workspace/bin
go env GOPATHOutputs the default workspace folder

...

Code Block
package main

import (
  "fmt"
  "error"
  "math"
)

func main() {
  result, err := sqrt(16)
  
  if err != nil {
    fmt.Println(err)
  } else {
    fmt.Println(result)
  }
}

func sqrt(x float64) (float64, error ) {
  if x < 0 {
    return 0, errors.New("Undefined for negative numbers")
  }
  return math.Sqrt(x), nil
} 


Method Set

Code Block
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    ...
}

func (s *GracefulServer) BlockingClose() bool {
    ...
}

This is called the 'receiver'. In the first case (h handler) it is a value type, in the second (s *GracefulServer) it is a pointer. The way this works in Go may vary a bit from some other languages. The receiving type however, works more or less like a class in most object-oriented programming. It is the thing you call the method from, much like if I put some method A in side some class Person then I would need an instance of type Person in order to call A (assuming it's an instance method and not static!).

One gotcha here is that the receiver gets pushed onto the call stack like other arguments so if the receiver is a value type, like in the case of handler then you will be working on a copy of the thing you called the method from meaning something like h.Name = "Evan" would not persist after you return to the calling scope. For this reason anything that expects to change the state of the receiver, needs to use a pointer or return the modified value (gives more of an immutable type paradigm if you're looking for that).

Here's the relevant section from the spec; https://golang.org/ref/spec#Method_sets


Structs/Types

Example of Person Type

...

Code Block
package main
  
import (
  "fmt"
)

func main(){

  //run in background
  go count("sheep")

  go count("fish")

  //wait for keyboard press before exiting
  fmt.Scanln()

}

func count(thing string) {
  for i:=0; true; i++ {
    fmt.Println(i, thing)
    time.Sleep(time.Millisecond * 500)
  }
}


Using Channels

Channels are blocking

Code Block
package main

import (
  "fmt"
  "time"
)

func main(){

  //make channel of type string
  c := make(chan,string)	

  //run in background
  go count("sheep", c)

  //block until message is pushed to the channel
  msg:= <- c

  fmt.Println(msg)
}

func count(thing string, c chan string) {
  for i:=0; i <= 5; i++ {
    //send message on channel
    c <- thing
    time.Sleep(time.Millisecond * 500)
  }
} 

In the above code, the program exits once the count routine returns a message on the channel.


Code Block
package main

import (
  "fmt"
  "time"
)

func main(){

  //make channel of type string
  c := make(chan,string)	

  //run in background
  go count("sheep", c)

  //loop until count function closes the channel
  for {
    msg, open := <- c
    if !open {
      //channel closed, break out of for loop
      break
    }
  }

  fmt.Println(msg)
}

func count(thing string, c chan string) {
  for i:=0; i <= 5; i++ {
    //send message on channel
    c <- thing
    time.Sleep(time.Millisecond * 500)
  }

  //close channel
  close(c)
} 

Organizing your Code

Image Added

References