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=.