Golang Coding - hqzhang/cloudtestbed GitHub Wiki

More example Go tour example

Send& Receive routine

package main

import (
    "fmt"
    "time"
    "sync"
)

func main() {
    ch1 := make(chan string)
    //ch2 := make(chan string)
    var wg sync.WaitGroup
    wg.Add(2)
    go func() {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            time.Sleep(2 * time.Second)
            ch1 <- "Message from channel 1"
        }
    }()

    go func(){
        defer wg.Done()
        for i := 0; i < 10; i++ {
            select {
            case msg1 := <-ch1:
                fmt.Println("Received message from channel 1:", msg1)
            }
    }}()
    wg.Wait()
}

make one dollar change

There are four types of common coins in US currency:
  o) quarters (25 cents)
  o) dimes (10 cents)
  o) nickels (5 cents)
  o) pennies (1 cent)

There are 6 ways to make change for 15 cents:
  o) A dime and a nickel;
  o) A dime and 5 pennies;
  o) 3 nickels;
  o) 2 nickels and 5 pennies;
  o) A nickel and 10 pennies;
  o) 15 pennies.

How many ways are there to make change for a dollar using these common coins? (1 dollar = 100 cents).

[Source http://rosettacode.org]

package main
import "fmt"
func answer(n int) int {
  c := make([]int, n+1)
  c[0]=1
  list := []int{1,5,10,25}
  list=append(list,n)
  for _,k:=range list {
    for i:=0;i<n+1-k; i++{
      c[i+k] +=c[i]
    }
  }
  return c[n]-1
}

func main() {
  n:=15
  if answer(n)==6 {
    fmt.Printf("%d can pay method:%d ¥n", n, answer(n))
  }
  n=100
  if answer(n)==242 {
    fmt.Printf("%d can pay method:%d ¥n", n, answer(n))
  }
}

wrap command

package main
import (
   "os"
   "os/exec"
   "fmt"
   "bufio"
)
func main(){
  mycmd:="fluent-bit -i dummy -o stdout -f 1"
  cmd:= exec.Command("/bin/bash", "-c", mycmd
  cmdReader, err := cmd.StdoutPipe()
  if err != nil {.
       fmt.Fprintln(os.Stderr, "Error Creaing StdoutPipe for cmd",err)
       return
  }
   
  scanner:=bufio.newScanner(cmdReader)
  go func() { 
     for scanner.Scan() {
          fmt.Printf("\t . %s\n",scanner.Text())
      }
  }()
  
  err=cmd.Start()
  if err != nil {
      fmt.Fprintln(os.Stderr, "Error starting cmd", err)
      return
  }
  err=cmd.Wait()
  if err != nil {
      fmt.Fprintln(os.Stderr, "Error waiting cmd", err)
      return
  }
}

MessagePack msgp

make project; cd project
vim main.go
---
package main
import (
    "fmt"
    "github.com/tinylib/msgp/msgp"
    "bytes"
)//following use for go generate main_go.gen

//go:generate msgp

type Foo struct {
    Bar string  `msg:"bar"`
    Baz float64 `msg:"baz"`
}

func main() {
        foo1 := Foo{ Bar:"hongqi",Baz:70.9, }
        foo2 := Foo{ Bar:"nanna",Baz: 76.0, }
        fmt.Println("inputs:")
        fmt.Printf("foo1: %v\n", foo1)
        fmt.Printf("foo2: %v\n", foo2)

        // Here, we append two messages into data
        data, _ := foo1.MarshalMsg(nil)
        data, _ = foo2.MarshalMsg(data)
        fmt.Printf("Marshal from:%T convert to:%T\n", foo1, data)
        fmt.Println(string(data))

        // Now we'll just decode them into myfoo1,2
        myfoo1:=Foo{}
        myfoo2:=Foo{}

        data, _ = myfoo1.UnmarshalMsg(data)
        data, _ = myfoo2.UnmarshalMsg(data)
        fmt.Printf("Unmarshal from:%T convert to:%T\n", data, myfoo1)
        //len(data) should be 0 because fetch all data
        fmt.Println("len(data) = %d\n", len(data))
      
        fmt.Printf("myfoo1: %v\n", myfoo1)
        fmt.Printf("myfoo2: %v\n", myfoo2)

        fmt.Println("This is stream operation!")
        //pr, pw := io.Pipe()
        var buf bytes.Buffer

        w := msgp.NewWriter(&buf)
        fmt.Printf("fooIn is %v\n", foo1)
        foo1.EncodeMsg(w)
        foo2.EncodeMsg(w)
        fmt.Printf("Encode from:%T convert to:%T\n", foo1, w)
        w.Flush()
        fmt.Printf("fooEncode is %v\n",string( buf.Bytes()) )

        tmp:=buf.Bytes()
        fmt.Printf("%T\n", tmp)
        var fooOut1 Foo
        var fooOut2 Foo
        r := bytes.NewReader(tmp)
        ww := msgp.NewReader(r)
        fmt.Printf("byte Reader from:%T convert to msgp Reader :%T\n", r, ww)

        fooOut1.DecodeMsg(ww)
        fooOut2.DecodeMsg(ww)
        fmt.Printf("Decode from:%T convert to:%T\n", ww, fooOut1)
        fmt.Printf("fooOut1 is %v\n", fooOut1)
        fmt.Printf("fooOut2 is %v\n", fooOut2)
        fmt.Println("End of encode and decoding!")
}

--
go mode init; go mod tidy //create mod.go
go generate                //create main_gen.go
go run .
input message to marshal
output message to unmarshal

Go module and Go generate

make project; cd project
vim main.go
---
package main
import 	"fmt"
var VersionString = "unset"
func main() {
	fmt.Println("Version:", VersionString)
}
---
go mode init; go mod tidy
go run -ldflags '-X main.VersionString=1.0' main.go
>>Version: 1.0
vim cmd/carls/main.go
---
package main
import "project"
func main() {
	project.PrintContributors()
}
---
vim project.go
---
package project
import "fmt"
//go:generate go run gen.go
func PrintContributors() {
	for _, contributor := range Contributors {
		fmt.Println(contributor)
	}
}
---
vim gen.go
---
// The following directive is necessary to make the package coherent:
// +build ignore
// This program generates contributors.go. It can be invoked by running
// go generate
package main
import (
        "bufio"
        "log"
        "net/http"
        "os"
        "strings"
        "text/template"
        "time"
)
func main() {
        const url = "https://github.com/golang/go/raw/master/CONTRIBUTORS"
        rsp, err := http.Get(url)
        die(err)
        defer rsp.Body.Close()
        sc := bufio.NewScanner(rsp.Body)
        carls := []string{}
        for sc.Scan() {
                if strings.Contains(sc.Text(), "Carl") {
                        carls = append(carls, sc.Text())
                }
        }
        die(sc.Err())
        f, err := os.Create("contributors.go")
        die(err)
        defer f.Close()
        packageTemplate.Execute(f, struct {
                Timestamp time.Time
                URL       string
                Carls     []string
        }{
                Timestamp: time.Now(),
                URL:       url,
                Carls:     carls,
        })
}

func die(err error) {
        if err != nil {
        }
}
var packageTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// {{ .Timestamp }}
// using data from
// {{ .URL }}
package project
var Contributors = []string{
{{- range .Carls }}
        {{ printf "%q" . }},
{{- end }}
}
`))
---
go generate //execte gen.go to generate contrabuition.go for package project
go run cmd/carts/main.go
>>>
Carl Chatfield <[email protected]>
Carl Henrik Lunde <[email protected]>
Carl Jackson <[email protected]>
.........

Golang Coding

func findDuplication(Array []int) [] int {
  //flag := make(map[int] bool{})
  my:=false
  flag:= make(map[int] interface{})
  dup:=[]int{}
  for _, v:= range Array {     
    if   flag[v]!= true {
         flag[v]=true
    } else {
      for _, vv:=range dup {
          if v==vv { 
             my=true
             break
          }
      } 
      if my==false {dup=append(dup,v) }   
     }
  }
  return dup
}
#Notes for golang
#create a keypair map
m=make(map[string]interface{})
#function with interface
func myprint(a interface{}){
     fmt.Println(a)
}
#basic number type
int  int8  int16  int32  int64
uint uintN uintptr
byte = uint8
rune = int32
float32 floatN
complex64 complexN
# struc type
type A struct
a:=A{a,b,c,d}
a:=A{A:a,B:b,C:c,D:d}
# array
var a [10]int
a:=[10]int{1,2,3,4,5,6,7,8,9,0}
#slice,point to arrays
var []int
a:=[]int{1,2,3,4,5}
a=append(a,6)
a := make([]int, 0, 5)
# maps
a:=make(map[string]interface{})
a["name"]="emily"
a["age"]=18
delete(m, key)
val, ok=a[key]
#range
for i, v := range a
#picture
// allocate
p := make([][]uint8, dy)
for i := 0; i < dy; i++ {
p[i] = make([]uint8, dx)
}
//function and method
(v X)function()==function(v X)
//interface
var a Shape //interface
var b circle //class
a=b
a.Abs()     // interface to specified
//channel
c := make(chan int,10) //create buffer
go sum(c) // c<-ch
x:=<-c
#mutex
sync.Mutex
Lock() Unlock(()
//initialize
var a int=1
a:=1
// draw
for y, _ := range p {
    for x, _ := range p[y] {
        p[y][x] = uint8(x^y)
    }
}
//wordCount
m := make(map[string]int)
	a := strings.Fields(s)
	for _, v := range a {
		m[v]++
	}
package main

import "fmt"
//function def
func say(s string) {
    for i := 0; i < 5; i++ {
	time.Sleep(100 * time.Millisecond)
	fmt.Println(s)
    }
}
// Here's a basic interface for geometric shapes.
type Shape interface {
    area() float64
}
type rect struct {
    width, height float64
}
type circle struct {
    radius float64
}
func (r rect) area() float64 {
    return r.width * r.height
}
func measure(g Shape) {
    fmt.Println(g)
    fmt.Println(g.area())
}
func reverse_words(s string) string {
    words := strings.Fields(s)  //string to array
    fmt.Println(words)
    for i, j := 0, len(words)-1; i < j; i, j = i+1, j-1 {
         words[i], words[j] = words[j], words[i]
    }
    return strings.Join(words, " ") //array to string
}

func main() {
    //show interface
    r := rect{width: 3, height: 4}
    measure(r)
    //show array vs slice
    var balance [10] int
    for i,num := range balance {
    fmt.Printf("number %d, %d\n", i,num)
   }  
    var numbers []int /* a slice of unspecified size */
    numbers = make([]int,5,5) /* a slice of length 5 and capacity 5*/
    numbers=append(numbers, 9)
    for i,num := range numbers {
    fmt.Printf("number %d, %d\n", i,num)
   }
    //start a go thread
   go say("world")
   say("hello")
   //channel communication
   ch := make(chan int)
}

thread coding

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            longOp()
            wg.Done()
        }()
    }
    // will wait until wg.Done is called 10 times
    // since we made wg.Add(1) call 10 times
    wg.Wait()
}
func longOp() {
    time.Sleep(time.Second * 2)
    fmt.Println("long op done")
}

channal coding

ch <- v    // Send v to channel ch.
v := <-ch  // Receive from ch, and
           // assign value to v.

web coding

sentence reverse

package main

import (
       "fmt"
       "time"
       "log"
       "runtime"
       "math"
       "strings"
       )
func add(a int,b int)int{
    return a+b
}
func swap(a,b string)(string,string){
    return b, a
}
func reverse(s string) string {
	chars := []rune(s)
	for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
		chars[i], chars[j] = chars[j], chars[i]
	}
	return string(chars)
}
func reverse_words(s string) string {
        //make sentence to array
	words := strings.Fields(s)
        fmt.Println(words)
        //swap the words
	for i, j := 0, len(words)-1; i < j; i, j = i+1, j-1 {
		words[i], words[j] = words[j], words[i]
	}
	return strings.Join(words, " ")
}
func sumchannel(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // send sum to c
}

type Pointer struct{
     X float64
     Y float64
}
type AbsIf interface {
	Abs() float64
}
func (v *Pointer) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main(){
    //defer print
    defer log.Println("Finally Hello world!") 
    //time
    fmt.Println("The time is", time.Now())
    //log
    log.Println("my log")
    //debug
    function, file, line, _ := runtime.Caller(1)
    log.Printf("[debug] %s:%s %d", file, runtime.FuncForPC(function).Name(), line)
    //math
    log.Printf("sq root:%g : %d\n", math.Sqrt(2),add(6,4) )
    //function
    log.Println(swap("hi","world") )
    //reverse
    s := "Hello, playground"
    fmt.Println(reverse_words(s))
    //struct
    pt:=Pointer{
        X:8,
        Y:7,
    }
    log.Println(pt)
    log.Println(Pointer{5,9} )
    //array vs slice
    var myarr [10]int
    myslice := make([]int,0, 10)
    for i:=0; i<10; i++ {
       myslice=append(myslice,i)
    }
    //slice changable
    my:=myslice[5:9]
    my[3]=99
    for _,c:=range myslice {
       log.Println(c)
    }
    //slice changable

    log.Printf("%d,%d",len(myarr),cap(myarr) )
    log.Printf("%d,%d",len(myslice),cap(myslice) )
    
    //map
    m := make(map[string]Pointer)
    m["Bell Labs"] = Pointer{
		40, -74,
    }
    log.Println( m)
    //method: (r receiver)function(param,...)
    //interface
    log.Println("Interface....")
    var a AbsIf
    v:=Pointer{3,4}
    a=&v
    log.Println(a.Abs())
    
    //interface type confirm
    var b interface{} ="mystring"
    t,ok:=b.(string)
    log.Println(t,ok)
    //flow control
    //for without bracket no while
    //if else without bracket(round)
    //switch defer
    //go routine
    go reverse_words("hello world")
    //ch <- v    // Send v to channel ch.
    //v := <-ch  // Receive from ch, and
    ss := []int{7, 2, 8, -9, 4, 0}
    
    c := make(chan int)
    go sumchannel(ss[len(ss)/2:], c)
    x := <-c // receive from c

    fmt.Println(x )
}

#Remove Dumplicate

func removeDuplicates(elem []int) []int {
    // Use map to record duplicates as we find them.
    flag := map[int]bool{}
    result := []int{}
    for _,v := range elem {
        if flag[v] != true {
            // Record this element as an encountered element.
            flag[v] = true
            // Append to result slice.
            result = append(result, v])
        }
    }
    // Return the new slice.
    return result
}
func main() {
    elements := []int{1,2,2,3,3,3,4,4,4,4}
    fmt.Println(elements)
    // Test our method.
    result := removeDuplicates(elements)
    fmt.Println(result)
}

#Stack implement

package main
import "fmt"
import "sync"
import "errors"
type stack struct {
     lock sync.Mutex // you don't have to do this if you don't want thread safety
     s [] int
}

func NewStack() *stack {
    return &stack {sync.Mutex{}, make([]int,0), }
}

func (s *stack) Push(v int) {
    s.lock.Lock()
    defer s.lock.Unlock()
    s.s = append(s.s, v)
}

func (s *stack) Pop() (int, error) {
    s.lock.Lock()
    defer s.lock.Unlock()
    l := len(s.s)
    if l == 0 {
        return 0, errors.New("Empty Stack")
    }
    res := s.s[l-1]
    s.s = s.s[:l-1]
    return res, nil
}
func main(){
    s := NewStack()
    s.Push(1)
    s.Push(2)
    s.Push(3)
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
}

Unit Testing vs BenchMark Test

hello.go:
package main
import "fmt"
func Sum(x int, y int) int {
    return x + y
}
func main() {
    fmt.Println("5+5=",Sum(5, 5))
}

hello_test.go
package main
import "testing"
func TestSum(t *testing.T) {
    total := Sum(5, 5)
    if total != 10 {
       t.Errorf("Sum was incorrect, got: %d, want: %d.", total, 10)
    }
}
# do testing
go test

#benchmark is to test performance(running time)
package main
import ("testing")
func BenchmarkFib10(b *testing.B) {
        // run the Fib function b.N times
        for n := 0; n < b.N; n++ {
                Fib(10)
        }
}

go test -bench=.