Skip to content

Instantly share code, notes, and snippets.

@sachinsmc
Created June 24, 2019 11:33

Revisions

  1. sachinsmc created this gist Jun 24, 2019.
    324 changes: 324 additions & 0 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,324 @@
    package main

    import(
    "fmt"
    m "math"
    "os"
    "io/ioutil"
    "net/http"
    "strconv"
    )

    func main() {
    fmt.Println("start where you left off other day.")
    beyondHello()
    }
    // Functions have parameters in parentheses.
    // If there are no parameters, empty parentheses are still required.
    func beyondHello() {
    var x int // Variable declaration. Variables must be declared before use.
    x = 3 // Variable assignment.
    // "Short" declarations use := to infer the type, declare, and assign.
    y := 4
    sum, prod := learnMultiple(x, y) // Function returns two values.
    fmt.Println("sum:", sum, "prod:", prod) // Simple output.
    learnTypes() // < y minutes, learn more!
    }

    /* <- multiline comment
    Functions can have parameters and (multiple!) return values.
    Here `x`, `y` are the arguments and `sum`, `prod` is the signature (what's returned).
    Note that `x` and `sum` receive the type `int`.
    */
    func learnMultiple(x, y int) (sum, prod int) {
    return x + y, x * y // Return two values.
    }

    // Some built-in types and literals.
    func learnTypes() {
    // Short declaration usually gives you what you want.
    str := "Learn Go!" // string type.

    s2 := `A "raw" string literal
    can include line breaks.` // Same string type.

    // Non-ASCII literal. Go source is UTF-8.
    g := 'Σ' // rune type, an alias for int32, holds a unicode code point.

    f := 3.14195 // float64, an IEEE-754 64-bit floating point number.
    c := 3 + 4i // complex128, represented internally with two float64's.

    // var syntax with initializers.
    var u uint = 7 // Unsigned, but implementation dependent size as with int.
    var pi float32 = 22. / 7

    // Conversion syntax with a short declaration.
    n := byte('\n') // byte is an alias for uint8.

    // Arrays have size fixed at compile time.
    var a4 [4]int // An array of 4 ints, initialized to all 0.
    a5 := [...]int{3, 1, 5, 10, 100} // An array initialized with a fixed size of five
    // elements, with values 3, 1, 5, 10, and 100.

    // Slices have dynamic size. Arrays and slices each have advantages
    // but use cases for slices are much more common.
    s3 := []int{4, 5, 9} // Compare to a5. No ellipsis here.
    s4 := make([]int, 4) // Allocates slice of 4 ints, initialized to all 0.
    var d2 [][]float64 // Declaration only, nothing allocated here.
    bs := []byte("a slice") // Type conversion syntax.

    // Because they are dynamic, slices can be appended to on-demand.
    // To append elements to a slice, the built-in append() function is used.
    // First argument is a slice to which we are appending. Commonly,
    // the array variable is updated in place, as in example below.
    s := []int{1, 2, 3} // Result is a slice of length 3.
    s = append(s, 4, 5, 6) // Added 3 elements. Slice now has length of 6.
    fmt.Println(s) // Updated slice is now [1 2 3 4 5 6]

    // To append another slice, instead of list of atomic elements we can
    // pass a reference to a slice or a slice literal like this, with a
    // trailing ellipsis, meaning take a slice and unpack its elements,
    // appending them to slice s.
    s = append(s, []int{7, 8, 9}...) // Second argument is a slice literal.
    fmt.Println(s) // Updated slice is now [1 2 3 4 5 6 7 8 9]

    p, q := learnMemory() // Declares p, q to be type pointer to int.
    fmt.Println(*p, *q) // * follows a pointer. This prints two ints.

    // Maps are a dynamically growable associative array type, like the
    // hash or dictionary types of some other languages.
    m := map[string]int{"three": 3, "four": 4}
    m["one"] = 1

    // Unused variables are an error in Go.
    // The underscore lets you "use" a variable but discard its value.
    _, _, _, _, _, _, _, _, _, _ = str, s2, g, f, u, pi, n, a5, s4, bs
    // Usually you use it to ignore one of the return values of a function
    // For example, in a quick and dirty script you might ignore the
    // error value returned from os.Create, and expect that the file
    // will always be created.
    file, _ := os.Create("output.txt")
    fmt.Fprint(file, "This is how you write to a file, by the way")
    file.Close()

    // Output of course counts as using a variable.
    fmt.Println(s, c, a4, s3, d2, m)

    learnFlowControl() // Back in the flow.
    }

    // Go is fully garbage collected. It has pointers but no pointer arithmetic.
    // You can make a mistake with a nil pointer, but not by incrementing a pointer.
    func learnMemory() (p, q *int) {
    // Named return values p and q have type pointer to int.
    p = new(int) // Built-in function new allocates memory.
    // The allocated int is initialized to 0, p is no longer nil.
    s := make([]int, 20) // Allocate 20 ints as a single block of memory.
    s[3] = 7 // Assign one of them.
    r := -2 // Declare another local variable.
    return &s[3], &r // & takes the address of an object.
    }


    func learnFlowControl() {
    if true {
    fmt.Println("no parentheses required in if condition")
    }

    if false {

    } else {

    }

    x := 42.0
    switch x {
    case 1:
    case 42:
    // cases don't fall through without fallthrough
    case 43:
    // Unreachable
    default:
    // Dafault case is optional
    }

    // like if, for doesn't require parenthesis
    for i := 0; i < 3; i++ {
    fmt.Println("Iteration : ", x)
    }

    // GO doesn't have while do or any other loops
    // for { // Infinite loop
    // continue
    // break
    // }

    // using range to iterate over an array, a slice, a string, a map or a channel
    // range returns one value(channel) or two vlaues (array, slice, sting and map)
    for key, value := range map[string]int{"one":1, "two":2, "three":3} {
    fmt.Printf("key=%s , value=%d]\n", key, value)
    }

    for _, name := range []string{"Bob", "Bill", "Joe"} {
    fmt.Printf("Hello, %s\n", name)
    }

    if y:= expensiveComputation(); y>x{
    x=y
    }

    // function literals are clousures
    xBig := func () bool {
    return x>10000
    }
    x = 99999
    fmt.Println("xBig : ", xBig())
    x = 1.3e3
    fmt.Println("xBig : ", xBig(), x)

    fmt.Println("Add + double two numbers : ",
    func(a, b int) int {
    return (a+b) * 2
    }(10, 2))

    goto love

    love:
    learnFunctionFactory() // funct returning func
    learnDefer()
    learnInterfaces()
    }

    func expensiveComputation() float64 {
    return m.Exp(10)
    }

    func learnFunctionFactory() {
    fmt.Println(sentenceFactory("summer")("A bueatiful", "day"))
    }


    func sentenceFactory(mystring string) func (before, after string) string {
    return func (before, after string) string{
    return fmt.Sprintf("%s %s %s", before, mystring,after)
    }
    }

    // defer statement put off the statement for later time, until surrounding function returns
    func learnDefer() (ok bool) {
    // A defer statement pushes a function call onto a list. The list of saved
    // calls is executed AFTER surrrounding function returns
    defer fmt.Println("deferred statements execute in reverse (LIFO) order.")
    defer fmt.Println("\n This line is being printed first because")
    // defer is commonly used to dicsonnect db/close a file, so the function closing
    // files stays close to the function opening the file
    return true
    }

    // Define Stringer as interface type with one method, String
    type Stringer interface {
    String() string
    }

    // Define pair as struct with two fields, ints names x and y.
    type pair struct {
    x, y int
    }

    // Define a method on pair, Pair now implements Stringer becaue Pair has defined all the methods in the interface.
    func (p pair) String() string { // p is called the receiver
    // Spintf is another public funcitonin package fmt
    // Dot syntax references fileds of p.
    return fmt.Sprintf("(%d, %d)", p.x, p.y)
    }

    func learnInterfaces() {
    // intialize p to this struct
    p := pair{3, 4}
    fmt.Println(p.String())
    var i Stringer
    i = p
    fmt.Println(i.String())
    fmt.Println(p)
    fmt.Println(i)
    learnVariadicParams("great","learning", "here")
    }

    func learnVariadicParams(myStrings...interface{}) {
    for _, param := range myStrings {
    fmt.Println("param:", param)
    }
    fmt.Println("params:", fmt.Sprintln(myStrings...))

    learnErrorHandling()
    }

    func learnErrorHandling() {
    // ", ok" idioms used to tell if something worked or not
    m := map[int]string{3: "three", 4: "four"}
    if x, ok := m[1]; !ok {
    fmt.Println("no one there")
    } else {
    fmt.Print(x)
    }

    if _, err := strconv.Atoi("non-int"); err != nil {
    fmt.Println(err)
    }
    learnConcurrency()
    }

    func inc(i int, c chan int) {
    c <- i+1 // <- is a send operator when a channel appears on the left
    }

    // we'll use inc to increment some numbers concurrently
    func learnConcurrency() {
    // make allocates and intializes slices, maps and channel.
    c := make(chan int)
    // Start three concurrenyt goroutines. Numbers will be incremented concurrently
    go inc(0, c) // go statement starts a goroutine.
    go inc(10, c)
    go inc(-805, c)

    fmt.Println(<-c, <-c, <-c)

    cs := make(chan string)
    ccs := make(chan chan string)
    go func () { c<-84 }()
    go func () { cs<-"wordy"}()

    select {
    case i := <-c: // received value can be assigned to a variable
    fmt.Printf("it's a %T", i)
    case <-cs:// or the value received can be discarded.
    fmt.Println("it's a string")
    case <- ccs: // empty chnnedl not ready for communication
    fmt.Println("didn't happen.")
    }

    learnWebProgramming()
    }

    func learnWebProgramming() {
    // First parameter of ListerAndServe is TCP address to listen to
    // second param is an interface, specifically http.handler
    go func () {
    err := http.ListenAndServe(":8080", pair{})
    fmt.Println(err)
    }()

    requestServer()
    }

    func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("You learned GO in Y minutes!"))
    }

    func requestServer() {
    resp, err := http.Get("http://localhost:8080")
    fmt.Println(err)
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Printf("\nWebserver said : `%s`", string(body))
    }