├── .gitignore ├── Makefile ├── README.mdown ├── arrays ├── .gitignore └── arrays.go ├── chaint1 ├── .gitignore └── chaint1.go ├── chanasyn ├── .gitignore └── chanasyn.go ├── chanfan01 ├── .gitignore └── chanfan01.go ├── chanfan02 ├── .gitignore └── chanfan02.go ├── chanfan03 ├── .gitignore └── chanfan03.go ├── chanfan04 ├── .gitignore └── chanfan04.go ├── chanfan05 ├── .gitignore └── chanfan05.go ├── chanfan06 ├── .gitignore └── chanfan06.go ├── chanfan07 ├── .gitignore └── chanfan07.go ├── chanfan08 ├── .gitignore └── chanfan08.go ├── chanfanout ├── .gitignore └── chanfanout.go ├── chanfanout2 ├── .gitignore └── chanfanout2.go ├── chanloop ├── .gitignore └── chanloop.go ├── channelLock ├── .gitignore ├── channelLock.go └── fastQuit │ ├── .gitignore │ └── fastQuit.go ├── chanokt ├── .gitignore └── chanokt.go ├── chanrange ├── .gitignore └── chanrange.go ├── chanshunt ├── .gitignore └── chanshunt.go ├── chanshunt_2 ├── .gitignore └── chanshunt_2.go ├── chansvr1 ├── .gitignore └── chansvr1.go ├── chansvr2 ├── .gitignore └── chansvr2.go ├── chansyn ├── .gitignore └── chansyn.go ├── chantest ├── .gitignore └── chantest.go ├── charshow ├── .gitignore └── charshow.go ├── dateshow ├── .gitignore └── dateshow.go ├── defer ├── .gitignore └── defer.go ├── demo_templates ├── call │ ├── .gitignore │ └── call.go ├── conditions │ ├── .gitignore │ └── conditions.go ├── functions │ ├── .gitignore │ └── functions.go ├── golangtutorials │ ├── fieldname │ │ ├── .gitignore │ │ └── fieldname.go │ ├── printf │ │ ├── .gitignore │ │ └── printf.go │ ├── revquotes │ │ ├── .gitignore │ │ └── revquotes.go │ ├── tvars │ │ ├── .gitignore │ │ └── tvars.go │ └── twithend │ │ ├── .gitignore │ │ └── twithend.go ├── insdata │ ├── .gitignore │ └── insdata.go ├── jst │ ├── .gitignore │ └── jst.go ├── must │ ├── .gitignore │ └── must.go ├── nestedfields │ ├── .gitignore │ └── nestedfields.go ├── nestedtemplates │ ├── .gitignore │ ├── nestedtemplages.go │ └── tmplfiles │ │ ├── content.tmpl │ │ ├── footer.tmpl │ │ └── header.tmpl ├── pipelines │ ├── .gitignore │ └── pipelines.go └── readme.txt ├── dtemplex1 ├── .gitignore └── dtemplex1.go ├── dtemplex2 ├── .gitignore └── dtemplex2.go ├── envshow ├── .gitignore └── envshow.go ├── errtest ├── .gitignore └── errtest.go ├── fib ├── .gitignore └── fib.go ├── fib_embellished ├── .gitignore └── fib_embellished.go ├── fib_userop ├── .gitignore └── fib_userop.go ├── fileread ├── .gitignore ├── data.txt ├── datacrlf.txt └── fileread.go ├── filescan ├── .gitignore ├── filescan.go └── t.txt ├── flagdemo ├── .gitignore └── flagdemo.go ├── force_type ├── .gitignore └── force_type.go ├── func_lit ├── .gitignore └── func_lit.go ├── func_ret ├── .gitignore └── func_ret.go ├── fwalker ├── .gitignore └── fwalker.go ├── gio12gs01 ├── .gitignore └── gio12gs01.go ├── gio12gs02 ├── .gitignore └── gio12gs02.go ├── gio12gs03 ├── .gitignore └── gio12gs03.go ├── gio12gs04 ├── .gitignore └── gio12gs04.go ├── gio12gs05 ├── .gitignore └── gio12gs05.go ├── gobdemo ├── .gitignore └── gobdemo.go ├── gorsynchs ├── .gitignore ├── chanex │ ├── .gitignore │ └── chanex.go ├── mutexex │ ├── .gitignore │ └── mutexex.go └── wgroupex │ ├── .gitignore │ └── wgroupex.go ├── gortns01 ├── .gitignore └── gortns01.go ├── greddit ├── .gitignore └── greddit.go ├── gt044 ├── .gitignore └── gt044.go ├── gt045 ├── .gitignore └── gt045.go ├── hello ├── .gitignore └── hello.go ├── hello_small ├── .gitignore └── hello_small.go ├── httpserv ├── .gitignore └── httpserv.go ├── interface_01 ├── .gitignore └── interface_01.go ├── interface_02 ├── .gitignore └── interface_02.go ├── interface_03 ├── .gitignore └── interface_03.go ├── interface_04 ├── .gitignore └── interface_04.go ├── interface_04a ├── .gitignore └── interface_04a.go ├── interface_04b ├── .gitignore └── interface_04b.go ├── interface_05 ├── .gitignore └── interface_05.go ├── list ├── .gitignore └── list.go ├── list_struct ├── .gitignore └── list_struct.go ├── loghello ├── .gitignore └── loghello.go ├── mapcaph ├── .gitignore └── mapcaph.go ├── mapmapstr ├── .gitignore └── mapmapstr.go ├── mapptrs ├── .gitignore └── mapptrs.go ├── maps ├── .gitignore └── maps.go ├── maps_merge ├── .gitignore └── maps_merge.go ├── maps_ss ├── .gitignore └── maps_ss.go ├── methods ├── .gitignore └── methods.go ├── netcon ├── .gitignore └── netcon.go ├── numbers ├── .gitignore ├── README.txt ├── numbers.go └── numbers_test.go ├── numconv ├── .gitignore └── numconv.go ├── oltesta ├── .gitignore └── oltesta.go ├── panrecov ├── .gitignore └── panrecov.go ├── pgmdir ├── .gitignore └── pgmdir.go ├── rand_between ├── .gitignore ├── rand_between.go └── rb_test.go ├── rangecopy ├── .gitignore └── rangecopy.go ├── ranges ├── .gitignore └── ranges.go ├── recover ├── .gitignore └── recover.go ├── reflmem ├── .gitignore └── reflmem.go ├── runpprof ├── .gitignore └── runpprof.go ├── shax ├── .gitignore └── shax.go ├── shifter ├── .gitignore └── shifter.go ├── show64 ├── .gitignore └── show64.go ├── showallocs ├── .gitignore └── showallocs.go ├── showgo ├── .gitignore └── showgo.go ├── showmac ├── .gitignore └── showmac.go ├── showpprof ├── .gitignore └── showpprof.go ├── showrtc ├── .gitignore └── showrtc.go ├── showsetcpus ├── .gitignore └── showsetcpus.go ├── showtime ├── .gitignore └── showtime.go ├── sigshow ├── .gitignore └── sigshow.go ├── sl3index ├── .gitignore └── sl3index.go ├── slappmult ├── .gitignore └── slappmult.go ├── slblog ├── .gitignore └── slblog.go ├── sldemo ├── .gitignore └── sldemo.go ├── sliceappt ├── .gitignore └── sliceappt.go ├── slices ├── .gitignore └── slices.go ├── slofsl ├── .gitignore └── slofsl.go ├── slofsl2 ├── .gitignore └── slofsl2.go ├── sltricks ├── .gitignore └── sltricks.go ├── sortex ├── .gitignore └── sortex.go ├── sqlex ├── .gitignore ├── foo.db └── sqlex.go ├── ssl ├── .gitignore ├── README.mdown ├── certinfo │ ├── .gitignore │ └── certinfo.go ├── certs │ ├── .gitignore │ ├── ca │ │ ├── ca.crt │ │ ├── ca.key │ │ ├── ca.pks │ │ └── ca.store │ ├── client │ │ ├── client.crt │ │ ├── client.csr │ │ ├── client.key │ │ ├── client.pks │ │ └── client.store │ └── server │ │ ├── server.crt │ │ ├── server.csr │ │ ├── server.key │ │ ├── server.pks │ │ └── server.store ├── client1 │ ├── .gitignore │ └── client1.go ├── client2 │ ├── .gitignore │ └── client2.go ├── client3 │ ├── .gitignore │ └── client3.go ├── client4 │ ├── .gitignore │ └── client4.go └── pemload │ ├── .gitignore │ └── pemload.go ├── stacktrace ├── .gitignore └── stacktrace.go ├── stomptest ├── .gitignore ├── receiver1 │ ├── .gitignore │ └── receiver1.go ├── receivernid │ ├── .gitignore │ └── receivernid.go ├── sender │ ├── .gitignore │ └── sender.go ├── sendernid │ ├── .gitignore │ └── sendernid.go ├── sendrcv │ ├── .gitignore │ └── sendrcv.go └── subrecv_examp │ ├── .gitignore │ └── subrecv_examp.go ├── stringlens ├── .gitignore └── stringlens.go ├── strings_utils ├── .gitignore └── strings_utils.go ├── struct ├── .gitignore └── struct.go ├── switch_demo ├── .gitignore └── switch_demo.go ├── symlshow ├── .gitignore └── symlshow.go ├── symltest ├── .gitignore └── symltest.go ├── tcp01 ├── .gitignore └── tcp01.go ├── tcp02 ├── .gitignore └── tcp02.go ├── tcp03 ├── .gitignore └── tcp03.go ├── tcp04 ├── .gitignore └── tcp04.go ├── tcp05 ├── .gitignore └── tcp05.go ├── tcp06 ├── .gitignore └── tcp06.go ├── testgreek ├── .gitignore └── testgreek.go ├── testppack ├── .gitignore └── testppack.go ├── type_String ├── .gitignore └── type_String.go ├── unicloup ├── .gitignore └── unicloup.go ├── unicode_what ├── .gitignore └── unicode_what.go ├── uniques ├── .gitignore └── uniques.go ├── urlshow ├── .gitignore └── urlshow.go ├── utfconv ├── .gitignore └── utfconv.go ├── walker ├── .gitignore └── walker.go ├── xmlshow01 ├── .gitignore ├── data.xml ├── data2.xml └── xmlshow01.go ├── xmlshow02 ├── .gitignore └── xmlshow02.go ├── xmlshow03 ├── .gitignore ├── data.xml └── xmlshow03.go ├── xmlshow04 ├── .gitignore └── xmlshow04.go └── zip_test ├── .gitignore ├── testdata ├── testa.jar └── testfile.zip └── ziptest.go /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | *.out 3 | *.8 4 | *.6 5 | *~ 6 | main 7 | _* 8 | .idea 9 | # Log files 10 | *.log 11 | # temp files 12 | temp* 13 | 14 | -------------------------------------------------------------------------------- /README.mdown: -------------------------------------------------------------------------------- 1 | Project go-samp, Samples of Simple go Language Programs 2 | ======================================================= 3 | This is a collection of extremely simple examples of using the _go_ 4 | programming language. 5 | 6 | These samples were inspired primarily by the _GoCourseDay#.pdf_ files 7 | previously available in the _go_ distrubution. And some additional experiments. 8 | In particular experiments triggered by documentation provided in the go 9 | distribution. 10 | 11 | Prerequisites 12 | ------------- 13 | 14 | In essence, you need a working _go_ environment, and a few small additions. 15 | 16 | At the current HEAD of master, your go build should be at least: weekly.2012-02-07. 17 | 18 | You need certain basic functions available to you in order to build and run 19 | these _go_ programs. 20 | 21 | These include: 22 | 23 | * the _go_ compiler 24 | * the _go_ linker 25 | * make 26 | 27 | If you are not familiar with _go_, and want to install it and learn the 28 | language, see: 29 | 30 | * http://golang.org 31 | 32 | Additional Setup 33 | ---------------- 34 | 35 | In order to use the _make_ system for these samples, you will need to have 36 | the $GOPATH environment variable properly defined. See the go documentation 37 | for details. 38 | 39 | Although this system is still installed using make, the 'go' tool is used under the 40 | covers. If you require previous versions, please examine previous tags. 41 | 42 | Adjust $GOPATH as necessary for your system. 43 | 44 | Install 45 | ------- 46 | 47 | To install all these samples: 48 | 49 | * clone from or fork on github 50 | * _cd_ to your base git repo directory 51 | * make packages 52 | * make 53 | 54 | Other Education Resources 55 | ------------------------- 56 | 57 | * http://www.slideshare.net/alexander.uni.fiis/learning-go-01 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /arrays/.gitignore: -------------------------------------------------------------------------------- 1 | arrays 2 | arrays.exe 3 | -------------------------------------------------------------------------------- /arrays/arrays.go: -------------------------------------------------------------------------------- 1 | /* 2 | A demonstration of using go arrays and slices. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | // 9 | // Function parameter: an array of 3 integers. 10 | // 11 | func f(a [3]int) { 12 | fmt.Println(a) 13 | } 14 | 15 | // 16 | // Function parameter: slice of integers, any length 17 | // Note that slices are not arrays. More like a view onto an array. 18 | // 19 | func fa(a []int) { 20 | fmt.Println(a) 21 | } 22 | 23 | // 24 | // Function parameter: a pointer to an array of 3 integers. 25 | // 26 | func fp(a *[3]int) { 27 | fmt.Println(a) 28 | } 29 | 30 | // 31 | // Function parameter: a pointer to an slice of integers. 32 | // As noted above, this is really a pointer to a slice, *not* a pointer 33 | // to an array. 34 | // 35 | func fsp(a *[]int) { 36 | fmt.Println(a) 37 | } 38 | 39 | /* 40 | 41 | */ 42 | func main() { 43 | // 44 | // Declared array 45 | // 46 | var ar [3]int 47 | f(ar) 48 | fp(&ar) 49 | // 50 | // Array Literal 51 | // 52 | var arb = [3]int{1, 2, 3} 53 | f(arb) 54 | fp(&arb) 55 | // 56 | // This is actually/technically a slice literal, not an array literal. 57 | // 58 | var arc = []int{1, 2, 3, 4, 5} 59 | fa(arc) // Note, different function needed (signature) 60 | fsp(&arc) // .... 61 | // 62 | // ------------------------------------------------------------------------ 63 | // 64 | // Array Literal, implied length of 5. 65 | // 66 | var ard = [...]int{1, 3, 5, 7, 9} 67 | // 68 | // This fails to compile: 69 | // 70 | // fa(ard) 71 | // 72 | // with error messages: 73 | // ..... cannot use ard (type [5]int) as type []int in function argument 74 | // 75 | // This fails to compile: 76 | // 77 | // fsp(&ard) 78 | // 79 | // with error messages: 80 | // ..... cannot use &ard (type *[5]int) as type *[]int in function argument 81 | // 82 | // ------------------------------------------------------------------------ 83 | fmt.Printf("%d\n", len(ard)) 84 | // 85 | // Loop through array - one 86 | // 87 | for i := 0; i < len(arb); i++ { 88 | fmt.Printf("%d\n", arb[i]) 89 | } 90 | // 91 | // Loop through array - two - using range 92 | // 93 | for _, narb := range arb { 94 | // narb is a copy of the element 95 | fmt.Printf("%d\n", narb) 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /chaint1/.gitignore: -------------------------------------------------------------------------------- 1 | chaint1 2 | chaint1.exe 3 | -------------------------------------------------------------------------------- /chaint1/chaint1.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demo chaining 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | type chainer interface { 11 | FuncA(a int) *chainer 12 | FuncB(b int) *chainer 13 | FuncC(c int) *chainer 14 | } 15 | 16 | type cdata struct { 17 | a, b, c int 18 | } 19 | 20 | func (d *cdata) getA() int { 21 | return d.a 22 | } 23 | 24 | func (d *cdata) getB() int { 25 | return d.b 26 | } 27 | 28 | func (d *cdata) getC() int { 29 | return d.c 30 | } 31 | 32 | func (d *cdata) FuncA(a int) *cdata { 33 | d.a = a 34 | return d 35 | } 36 | 37 | func (d *cdata) FuncB(b int) *cdata { 38 | d.b = b 39 | return d 40 | } 41 | 42 | func (d *cdata) FuncC(c int) *cdata { 43 | d.c = c 44 | return d 45 | } 46 | 47 | func showData(d cdata) { 48 | fmt.Printf("a:%d\n", d.a) 49 | fmt.Printf("b:%d\n", d.b) 50 | fmt.Printf("c:%d\n", d.c) 51 | } 52 | 53 | func main() { 54 | fmt.Println("hi") 55 | // 56 | md := new(cdata) 57 | showData(*md) 58 | md.FuncA(1).FuncB(2).FuncC(3) 59 | showData(*md) 60 | 61 | fmt.Println("bye") 62 | 63 | } 64 | -------------------------------------------------------------------------------- /chanasyn/.gitignore: -------------------------------------------------------------------------------- 1 | chanasyn 2 | chanasyn.exe 3 | -------------------------------------------------------------------------------- /chanasyn/chanasyn.go: -------------------------------------------------------------------------------- 1 | /* 2 | A demonstration of using a buffered channel. Originally from gocourseday3.pdf. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | fmt.Println("Start ....") 13 | 14 | c := make(chan int, 50) 15 | go func() { 16 | x := <-c 17 | fmt.Println("received", x) 18 | }() 19 | fmt.Println("sending", 10) 20 | c <- 10 21 | fmt.Println("sent", 10) 22 | time.Sleep(10 * time.Second) 23 | // 24 | fmt.Println("End ....") 25 | } 26 | -------------------------------------------------------------------------------- /chanfan01/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan01 2 | chanfan01.exe 3 | -------------------------------------------------------------------------------- /chanfan01/chanfan01.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | c := fanIn(boring("Joe!"), boring("Ann!")) 14 | // Unsequenced 15 | for i := 0; i < 10; i++ { 16 | fmt.Println(<-c) 17 | } 18 | fmt.Println("You're both boring, I'm leaving") 19 | } 20 | 21 | func boring(msg string) <-chan string { 22 | c := make(chan string) 23 | go func() { // Launch from inside function 24 | for i := 0; ; i++ { 25 | c <- fmt.Sprintf("%s %d", msg, i) 26 | time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond) 27 | } 28 | }() 29 | return c // Return the channel to the caller 30 | } 31 | 32 | // Fanin, or multiplexor 33 | func fanIn(input1, input2 <-chan string) <-chan string { 34 | c := make(chan string) 35 | go func() { 36 | for { 37 | c <- <-input1 38 | } 39 | }() 40 | go func() { 41 | for { 42 | c <- <-input2 43 | } 44 | }() 45 | return c 46 | } 47 | -------------------------------------------------------------------------------- /chanfan02/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan02 2 | chanfan02.exe 3 | -------------------------------------------------------------------------------- /chanfan02/chanfan02.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | type Message struct { 13 | str string 14 | wait chan bool 15 | } 16 | 17 | func main() { 18 | c := fanIn(boring("Joe!"), boring("Ann!")) 19 | // Sequencing restored 20 | for i := 0; i < 10; i++ { 21 | msg1 := <-c 22 | fmt.Println(msg1.str) 23 | msg2 := <-c 24 | fmt.Println(msg2.str) 25 | // 26 | msg1.wait <- true 27 | msg2.wait <- true 28 | } 29 | fmt.Println("You're both boring, I'm leaving") 30 | } 31 | 32 | func boring(msg string) <-chan Message { 33 | c := make(chan Message) 34 | waitForIt := make(chan bool) 35 | go func() { // Launch from inside function 36 | for i := 0; ; i++ { 37 | c <- Message{fmt.Sprintf("%s %d", msg, i), waitForIt} 38 | time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond) 39 | <-waitForIt 40 | } 41 | }() 42 | return c // Return the channel to the caller 43 | } 44 | 45 | // Fanin, or multiplexor 46 | func fanIn(input1, input2 <-chan Message) <-chan Message { 47 | c := make(chan Message) 48 | go func() { 49 | for { 50 | c <- <-input1 51 | } 52 | }() 53 | go func() { 54 | for { 55 | c <- <-input2 56 | } 57 | }() 58 | return c 59 | } 60 | -------------------------------------------------------------------------------- /chanfan03/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan03 2 | chanfan03.exe 3 | -------------------------------------------------------------------------------- /chanfan03/chanfan03.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | c := fanIn(boring("Joe!"), boring("Ann!")) 14 | // Unsequenced 15 | for i := 0; i < 10; i++ { 16 | fmt.Println(<-c) 17 | } 18 | fmt.Println("You're both boring, I'm leaving") 19 | } 20 | 21 | func boring(msg string) <-chan string { 22 | c := make(chan string) 23 | go func() { // Launch from inside function 24 | for i := 0; ; i++ { 25 | c <- fmt.Sprintf("%s %d", msg, i) 26 | time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond) 27 | } 28 | }() 29 | return c // Return the channel to the caller 30 | } 31 | 32 | // Fanin, or multiplexor 33 | func fanIn(input1, input2 <-chan string) <-chan string { 34 | c := make(chan string) 35 | // Single go routine 36 | go func() { 37 | for { 38 | select { 39 | case s := <-input1: 40 | c <- s 41 | case s := <-input2: 42 | c <- s 43 | } 44 | } 45 | }() 46 | return c 47 | } 48 | -------------------------------------------------------------------------------- /chanfan04/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan04 2 | chanfan04.exe 3 | -------------------------------------------------------------------------------- /chanfan04/chanfan04.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | c := boring("Joe!") 14 | // 15 | for { 16 | // Timeout each message 17 | select { 18 | case s := <-c: 19 | fmt.Println(s) 20 | case <-time.After(1 * time.Second): 21 | fmt.Println("You're too slow, I'm leaving") 22 | return 23 | } 24 | } 25 | } 26 | 27 | func boring(msg string) <-chan string { 28 | c := make(chan string) 29 | go func() { // Launch from inside function 30 | for i := 0; ; i++ { 31 | c <- fmt.Sprintf("%s %d", msg, i) 32 | time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond) 33 | } 34 | }() 35 | return c // Return the channel to the caller 36 | } 37 | -------------------------------------------------------------------------------- /chanfan05/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan05 2 | chanfan05.exe 3 | -------------------------------------------------------------------------------- /chanfan05/chanfan05.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | c := boring("Joe!") 14 | // Timeout entire loop 15 | timeout := time.After(5 * time.Second) 16 | for { 17 | select { 18 | case s := <-c: 19 | fmt.Println(s) 20 | case <-timeout: 21 | fmt.Println("You talk too much, I'm leaving") 22 | return 23 | } 24 | } 25 | } 26 | 27 | func boring(msg string) <-chan string { 28 | c := make(chan string) 29 | go func() { // Launch from inside function 30 | for i := 0; ; i++ { 31 | c <- fmt.Sprintf("%s %d", msg, i) 32 | time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond) 33 | } 34 | }() 35 | return c // Return the channel to the caller 36 | } 37 | -------------------------------------------------------------------------------- /chanfan06/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan06 2 | chanfan06.exe 3 | -------------------------------------------------------------------------------- /chanfan06/chanfan06.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | quit := make(chan bool) 14 | c := boring("Joe!", quit) 15 | // Joe can olny talk so much, and then is told to quit. 16 | for i := rand.Intn(10); i >= 0; i-- { 17 | fmt.Println(<-c) 18 | } 19 | quit <- true 20 | time.Sleep(100 * time.Millisecond) 21 | } 22 | 23 | func boring(msg string, quit chan bool) <-chan string { 24 | c := make(chan string) 25 | go func() { // Launch from inside function 26 | i := 1 27 | for { 28 | select { 29 | case c <- fmt.Sprintf("%s %d", msg, i): 30 | i++ 31 | case <-quit: 32 | fmt.Println("Stopping") 33 | return 34 | } 35 | } 36 | }() 37 | return c // Return the channel to the caller 38 | } 39 | -------------------------------------------------------------------------------- /chanfan07/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan07 2 | chanfan07.exe 3 | -------------------------------------------------------------------------------- /chanfan07/chanfan07.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | ) 10 | 11 | func main() { 12 | quit := make(chan string) 13 | c := boring("Joe!", quit) 14 | // Joe can olny talk so much, and then is told to quit. 15 | for i := rand.Intn(10); i >= 0; i-- { 16 | fmt.Println(<-c) 17 | } 18 | quit <- "Bye!" 19 | fmt.Printf("Joe says: %s\n", <-quit) 20 | } 21 | 22 | func boring(msg string, quit chan string) <-chan string { 23 | c := make(chan string) 24 | go func() { // Launch from inside function 25 | i := 1 26 | for { 27 | select { 28 | case c <- fmt.Sprintf("%s %d", msg, i): 29 | i++ 30 | case <-quit: 31 | fmt.Println("Cleanup complete") 32 | quit <- "See ya!" 33 | return 34 | } 35 | } 36 | }() 37 | return c // Return the channel to the caller 38 | } 39 | -------------------------------------------------------------------------------- /chanfan08/.gitignore: -------------------------------------------------------------------------------- 1 | chanfan08 2 | chanfan08.exe 3 | -------------------------------------------------------------------------------- /chanfan08/chanfan08.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | // Daisy chain 11 | 12 | func f(left, right chan int) { 13 | left <- 1 + <-right 14 | } 15 | 16 | func main() { 17 | const n = 10000 18 | leftmost := make(chan int) 19 | right := leftmost 20 | left := leftmost 21 | for i := 0; i < n; i++ { 22 | right = make(chan int) 23 | go f(left, right) 24 | left = right 25 | } 26 | go func(c chan int) { c <- 1 }(right) 27 | fmt.Println(<-leftmost) 28 | } 29 | -------------------------------------------------------------------------------- /chanfanout/.gitignore: -------------------------------------------------------------------------------- 1 | chanfanout 2 | chanfanout.exe 3 | -------------------------------------------------------------------------------- /chanfanout/chanfanout.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // Modified example from: 8 | // http://stackoverflow.com/questions/16930251/go-one-producer-many-consumers 9 | 10 | func fanOut(ch <-chan int, size, lag int) []chan int { 11 | cs := make([]chan int, size) 12 | for i, _ := range cs { 13 | // The size of the channels buffer controls how far behind the recievers 14 | // of the fanOut channels can lag the other channels. 15 | cs[i] = make(chan int, lag) 16 | } 17 | go func() { 18 | for i := range ch { 19 | for _, c := range cs { 20 | c <- i 21 | } 22 | } 23 | for _, c := range cs { 24 | // close all our fanOut channels when the input channel is exhausted. 25 | close(c) 26 | } 27 | }() 28 | return cs 29 | } 30 | 31 | func main() { 32 | fmt.Println("hi") 33 | const ( 34 | chsz = 1 35 | sz = 1 36 | lag = 1 37 | ) 38 | ch := make(chan int, chsz) 39 | co := fanOut(ch, sz, lag) 40 | fmt.Println("CO", co) 41 | fmt.Println("bye") 42 | } 43 | -------------------------------------------------------------------------------- /chanfanout2/.gitignore: -------------------------------------------------------------------------------- 1 | chanfanout2 2 | chanfanout2.exe 3 | -------------------------------------------------------------------------------- /chanfanout2/chanfanout2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // Modified example from: 9 | // http://stackoverflow.com/questions/16930251/go-one-producer-many-consumers 10 | // and the referenced implementation. 11 | 12 | func producer(iters int) <-chan int { 13 | c := make(chan int) 14 | go func() { 15 | for i := 0; i < iters; i++ { 16 | c <- i 17 | time.Sleep(1 * time.Second) 18 | } 19 | close(c) 20 | }() 21 | return c 22 | } 23 | 24 | func consumer(cin <-chan int) { 25 | for i := range cin { 26 | fmt.Println(i) 27 | } 28 | } 29 | 30 | func fanOut(ch <-chan int, size, lag int) []chan int { 31 | cs := make([]chan int, size) 32 | for i, _ := range cs { 33 | // The size of the channels buffer controls how far behind the recievers 34 | // of the fanOut channels can lag the other channels. 35 | cs[i] = make(chan int, lag) 36 | } 37 | go func() { 38 | for i := range ch { 39 | for _, c := range cs { 40 | c <- i 41 | } 42 | } 43 | for _, c := range cs { 44 | // close all our fanOut channels when the input channel is exhausted. 45 | close(c) 46 | } 47 | }() 48 | return cs 49 | } 50 | 51 | func fanOutUnbuffered(ch <-chan int, size int) []chan int { 52 | cs := make([]chan int, size) 53 | for i, _ := range cs { 54 | // The size of the channels buffer controls how far behind the recievers 55 | // of the fanOut channels can lag the other channels. 56 | cs[i] = make(chan int) 57 | } 58 | go func() { 59 | for i := range ch { 60 | for _, c := range cs { 61 | c <- i 62 | } 63 | } 64 | for _, c := range cs { 65 | // close all our fanOut channels when the input channel is exhausted. 66 | close(c) 67 | } 68 | }() 69 | return cs 70 | } 71 | 72 | func main() { 73 | c := producer(10) 74 | chans := fanOutUnbuffered(c, 3) 75 | go consumer(chans[0]) 76 | go consumer(chans[1]) 77 | consumer(chans[2]) 78 | } 79 | -------------------------------------------------------------------------------- /chanloop/.gitignore: -------------------------------------------------------------------------------- 1 | chanloop 2 | chanloop.exe 3 | -------------------------------------------------------------------------------- /chanloop/chanloop.go: -------------------------------------------------------------------------------- 1 | /* 2 | Loop and receive values from a buffered channel. 3 | */ 4 | package main 5 | 6 | // 7 | import ( 8 | "fmt" 9 | // "time" 10 | ) 11 | 12 | // 13 | func runner(inc chan int, wc chan bool) { 14 | fmt.Println("runner starting") 15 | dobreak := false 16 | for { 17 | if dobreak { 18 | break 19 | } 20 | select { 21 | case ival := <-inc: 22 | fmt.Println("runner got value", ival) 23 | default: 24 | fmt.Println("runner found nothing") 25 | dobreak = true 26 | } 27 | } 28 | // 29 | wc <- true // we are done 30 | fmt.Println("runner ending") 31 | } 32 | 33 | // 34 | func main() { 35 | fmt.Println("Start ....") 36 | // 37 | isc := make(chan int, 3) 38 | isc <- 1 39 | isc <- 2 40 | isc <- 3 41 | // 42 | fmt.Println("Three are queued ....") 43 | waitChan := make(chan bool) 44 | go runner(isc, waitChan) 45 | fmt.Println("Starting wait ....") 46 | doneFlag := <-waitChan 47 | fmt.Println("Done", doneFlag) 48 | // 49 | fmt.Println("End ....") 50 | } 51 | -------------------------------------------------------------------------------- /channelLock/.gitignore: -------------------------------------------------------------------------------- 1 | channelLock 2 | channelLock.exe 3 | 4 | -------------------------------------------------------------------------------- /channelLock/fastQuit/.gitignore: -------------------------------------------------------------------------------- 1 | fastQuit 2 | fastQuit.exe 3 | -------------------------------------------------------------------------------- /chanokt/.gitignore: -------------------------------------------------------------------------------- 1 | chanokt 2 | chanokt.exe 3 | -------------------------------------------------------------------------------- /chanokt/chanokt.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func main() { 11 | fmt.Println("starting") 12 | // 13 | c := make(chan int, 1) // A small buffer 14 | fmt.Printf("Print Test: %v\n", c) 15 | fmt.Printf("Length01: %d\n", len(c)) // Ignore races here :-) 16 | c <- 1 17 | fmt.Printf("Length02: %d\n", len(c)) // And here 18 | _ = <- c // clear 19 | 20 | // Test the if comma ok way 21 | c <- 2 22 | close(c) // the test 23 | // This receive works, even with the closed channel 24 | val, ok := <- c 25 | if ok { 26 | fmt.Printf("OK2, len, val: %d , %d\n", len(c), val) // 27 | } else { 28 | fmt.Printf("NOTOK2, len, val: %d , %d\n", len(c), val) // 29 | } 30 | // This receive fails 31 | val, ok = <- c 32 | if ok { 33 | fmt.Printf("OK3, len, val: %d , %d\n", len(c), val) // 34 | } else { 35 | fmt.Printf("NOTOK3, len, val: %d , %d\n", len(c), val) // 36 | } 37 | // 38 | // close(c) // 2nd time: panic 39 | 40 | 41 | // Test the range way 42 | c2 := make(chan int, 1) // A small buffer 43 | fmt.Printf("Print Test2: %v\n", c2) 44 | c2 <- 3 45 | close(c2) // the test 46 | // 47 | for v := range c2 { 48 | fmt.Printf("RANGE1, v: %d\n", v) // 49 | } 50 | fmt.Println("=============") 51 | for v2 := range c2 { 52 | fmt.Printf("RANGE2, v2: %d\n", v2) // Does not run 53 | } 54 | // 55 | fmt.Println("ending") 56 | 57 | // Test the if comma ok way, no close 58 | c3 := make(chan int, 1) // A small buffer 59 | fmt.Printf("Print Test3: %v\n", c3) 60 | c3 <- 4 61 | // no close() here 62 | // This receive works, of course. 63 | val, ok = <- c3 64 | if ok { 65 | fmt.Printf("OK4, len, val: %d , %d\n", len(c3), val) // 66 | } else { 67 | fmt.Printf("NOTOK4, len, val: %d , %d\n", len(c3), val) // 68 | } 69 | // This panics 70 | /* 71 | val4, ok4 := <- c3 // -> fatal error: all goroutines are asleep - deadlock! 72 | if ok4 { 73 | fmt.Printf("OK4, len, val: %d , %d\n", len(c3), val4) // 74 | } else { 75 | fmt.Printf("NOTOK4, len, val: %d , %d\n", len(c3), val4) // 76 | } 77 | */ 78 | // Try this instead. Also panics. 79 | /* 80 | fmt.Println("=============") 81 | for v3 := range c3 { // -> fatal error: all goroutines are asleep - deadlock! 82 | fmt.Printf("RANGE3, v3: %d\n", v3) // 83 | } 84 | */ 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /chanrange/.gitignore: -------------------------------------------------------------------------------- 1 | chanrange 2 | chanrange.exe 3 | -------------------------------------------------------------------------------- /chanrange/chanrange.go: -------------------------------------------------------------------------------- 1 | /* 2 | Loop and receive values from a buffered channel using range. 3 | */ 4 | package main 5 | 6 | // 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | // 12 | func runner(inc chan int, wc chan bool) { 13 | fmt.Println("runner starting") 14 | for ival := range inc { 15 | fmt.Println("runner got value", ival) 16 | // If we do not break here, we get at runtime: 17 | // throw: all goroutines are asleep - deadlock! 18 | if ival == 3 { 19 | break 20 | } 21 | } 22 | wc <- true // we are done 23 | fmt.Println("runner ending") 24 | } 25 | 26 | // 27 | func main() { 28 | fmt.Println("Start ....") 29 | // 30 | isc := make(chan int, 3) 31 | isc <- 1 32 | isc <- 2 33 | isc <- 3 34 | // 35 | fmt.Println("Three are queued ....") 36 | waitChan := make(chan bool) 37 | go runner(isc, waitChan) 38 | fmt.Println("Starting wait ....") 39 | doneFlag := <-waitChan 40 | fmt.Println("Done", doneFlag) 41 | // 42 | fmt.Println("End ....") 43 | } 44 | -------------------------------------------------------------------------------- /chanshunt/.gitignore: -------------------------------------------------------------------------------- 1 | chanshunt 2 | chanshunt.exe 3 | -------------------------------------------------------------------------------- /chanshunt/chanshunt.go: -------------------------------------------------------------------------------- 1 | /* 2 | An example taken from: https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/VdmoZ59jjoE 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | // 9 | // See: 10 | // https://groups.google.com/forum/?fromgroups#!topic/golang-nuts/VdmoZ59jjoE 11 | // http://play.golang.org/p/ZJamJZgeEK 12 | // 13 | // A channel shunt (or shovel). 14 | // 15 | func shunt(input <-chan int, output chan<- int) { 16 | var ( 17 | i int 18 | ok bool 19 | in = input 20 | out chan<- int 21 | ) 22 | for { 23 | select { 24 | case i, ok = <-in: 25 | if !ok { 26 | close(output) 27 | fmt.Println("done") 28 | return 29 | } 30 | fmt.Println("shunt in", i) 31 | in = nil 32 | out = output 33 | case out <- i: 34 | fmt.Println("shunt out", i) 35 | in = input 36 | out = nil 37 | } 38 | } 39 | 40 | } 41 | 42 | func main() { 43 | input := make(chan int, 100) 44 | go func() { // Simulate a sender to input in another part of the program 45 | for i := 0; i < 1000; i++ { 46 | input <- i 47 | } 48 | close(input) 49 | }() 50 | 51 | acc := make(chan int, 10) // accumulator channel 52 | go shunt(input, acc) 53 | for i := range acc { 54 | fmt.Println("acc read:", i) 55 | } 56 | fmt.Println("exit") 57 | } 58 | -------------------------------------------------------------------------------- /chanshunt_2/.gitignore: -------------------------------------------------------------------------------- 1 | chanshunt_2 2 | chanshunt_2.exe 3 | -------------------------------------------------------------------------------- /chansvr1/.gitignore: -------------------------------------------------------------------------------- 1 | chansvr1 2 | chansvr1.exe 3 | -------------------------------------------------------------------------------- /chansvr1/chansvr1.go: -------------------------------------------------------------------------------- 1 | /* 2 | A simple server using channels. Another example from the gocourseday3.pdf. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | // 9 | // This example works as presented in the PDF. This is mostly cut and 10 | // paste. 11 | // 12 | // The request. 13 | // 14 | type request struct { 15 | a, b int 16 | replyc chan int 17 | } 18 | 19 | // 20 | // Operation type definition. 21 | // 22 | type binOp func(a, b int) int 23 | 24 | // 25 | // The low level 'runner'. 26 | // 27 | func run(op binOp, req *request) { 28 | req.replyc <- op(req.a, req.b) 29 | } 30 | 31 | // 32 | // The server logic. 33 | // 34 | func server(op binOp, service chan *request) { 35 | for { 36 | req := <-service // requests arrive here 37 | go run(op, req) // don't wait for op 38 | } 39 | } 40 | 41 | // 42 | // Server startup. 43 | // 44 | func startServer(op binOp) chan *request { 45 | req := make(chan *request) 46 | go server(op, req) 47 | return req 48 | } 49 | 50 | /* 51 | Print requests nicely. 52 | */ 53 | func (r *request) String() string { 54 | return fmt.Sprintf("%d+%d=%d", r.a, r.b, <-r.replyc) 55 | } 56 | 57 | // 58 | // Mainline. 59 | // 60 | func main() { 61 | fmt.Println("Start...") 62 | // Server start. 63 | var adderChan = startServer(func(a, b int) int { return a + b }) 64 | // Create some requests 65 | req1 := &request{7, 8, make(chan int)} 66 | req2 := &request{17, 18, make(chan int)} 67 | // Send the requests 68 | adderChan <- req1 69 | adderChan <- req2 70 | // Get and show reply. 71 | fmt.Println(req2, req1) 72 | // 73 | fmt.Println("End...") 74 | } 75 | -------------------------------------------------------------------------------- /chansvr2/.gitignore: -------------------------------------------------------------------------------- 1 | chansvr2 2 | chansvr2.exe 3 | -------------------------------------------------------------------------------- /chansvr2/chansvr2.go: -------------------------------------------------------------------------------- 1 | /* 2 | A simple server using channels, with client controlled shutdown. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | // 9 | // Another example from the gocourseday3.pdf. 10 | // 11 | // This example works as presented in the PDF. This is mostly cut and 12 | // paste. This adds to the previous example, but shows client controlled 13 | // shutdown of the server. 14 | // 15 | // The request. 16 | // 17 | type request struct { 18 | a, b int 19 | replyc chan int 20 | } 21 | 22 | // 23 | // Operation type definition. 24 | // 25 | type binOp func(a, b int) int 26 | 27 | // 28 | // The low level 'runner'. 29 | // 30 | func run(op binOp, req *request) { 31 | req.replyc <- op(req.a, req.b) 32 | } 33 | 34 | // 35 | // The server logic. 36 | // 37 | func server(op binOp, service chan *request, quit chan bool) { 38 | for { 39 | select { 40 | case req := <-service: 41 | go run(op, req) // don't wait for it 42 | case <-quit: 43 | fmt.Println("OK, serever done") 44 | return 45 | } 46 | } 47 | } 48 | 49 | // 50 | // Server startup. 51 | // 52 | func startServer(op binOp) (chan *request, chan bool) { 53 | service := make(chan *request) 54 | quit := make(chan bool) 55 | go server(op, service, quit) 56 | return service, quit 57 | } 58 | 59 | // 60 | // Print requests nicely. 61 | // 62 | func (r *request) String() string { 63 | return fmt.Sprintf("%d+%d=%d", r.a, r.b, <-r.replyc) 64 | } 65 | 66 | // 67 | // Mainline. 68 | // 69 | func main() { 70 | fmt.Println("Start...") 71 | // Server start. 72 | var adderChan, quitChan = startServer(func(a, b int) int { return a + b }) 73 | // Create some requests 74 | req1 := &request{7, 8, make(chan int)} 75 | req2 := &request{17, 18, make(chan int)} 76 | // Send the requests 77 | adderChan <- req1 78 | adderChan <- req2 79 | // Get and show reply. 80 | fmt.Println(req2, req1) 81 | // 82 | quitChan <- true 83 | // 84 | fmt.Println("End...") 85 | } 86 | -------------------------------------------------------------------------------- /chansyn/.gitignore: -------------------------------------------------------------------------------- 1 | chansyn 2 | chansyn.exe 3 | -------------------------------------------------------------------------------- /chansyn/chansyn.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example of using an unbuffered channel, based on gocourseday3.pdf. 3 | */ 4 | package main 5 | 6 | // 7 | import ( 8 | "fmt" 9 | "time" 10 | ) 11 | 12 | // 13 | // gocourseday3.pdf - simple synchronous channel example. 14 | // Slightly embellished. 15 | // 16 | func main() { 17 | fmt.Println("Start ....") 18 | // 19 | syn_chan := make(chan int) // Synchronous: no buffering specified 20 | done_chan := make(chan bool) // Also synchronous 21 | go func() { 22 | time.Sleep(2 * 1e9) 23 | fmt.Println("receiver is up") 24 | x := <-syn_chan // Receive. Will block until data received 25 | fmt.Println("starting work, received", x) 26 | tw := time.Duration(x * 1e9) 27 | time.Sleep(tw) // Simulate work 28 | fmt.Println("work complete") 29 | done_chan <- true // Signal done 30 | }() 31 | // 32 | fmt.Println("sending", 5) 33 | syn_chan <- 5 // Send. Will block until a receive complete 34 | fmt.Println("sent", 5) 35 | fmt.Println("waiting for complete work") 36 | done_flag := <-done_chan 37 | fmt.Println("done is:", done_flag) 38 | // 39 | fmt.Println("End ....") 40 | } 41 | -------------------------------------------------------------------------------- /chantest/.gitignore: -------------------------------------------------------------------------------- 1 | chantest 2 | chantest.exe 3 | -------------------------------------------------------------------------------- /chantest/chantest.go: -------------------------------------------------------------------------------- 1 | /* 2 | A demonstration of blocking when using an unbuffered channel. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | func worker(c chan int) { 12 | fmt.Println("worker starts ...") 13 | var x int = -1 14 | var ok bool = false 15 | time.Sleep(5 * 1e9) 16 | select { 17 | case x = <-c: 18 | ok = true 19 | default: 20 | ok = false 21 | } 22 | fmt.Printf("received %d %t\n", x, ok) 23 | } 24 | 25 | // 26 | // Tests to see if a channel will block. 27 | // 28 | func main() { 29 | fmt.Println("Start ....") 30 | fmt.Println("===========") 31 | // 32 | var tosend int = 1 33 | c := make(chan int) 34 | go func() { 35 | time.Sleep(5 * 1e9) 36 | x := <-c 37 | fmt.Println("received", x) 38 | }() 39 | // 40 | fmt.Println("sending", tosend) 41 | c <- tosend 42 | fmt.Println("sent1", tosend) 43 | // 44 | fmt.Println("===========") 45 | tosend = 2 46 | unbuf := make(chan int) 47 | go worker(unbuf) // 48 | unbuf <- tosend 49 | fmt.Println("sent2", tosend) 50 | // 51 | fmt.Println("===========") 52 | tosend = 3 53 | buf := make(chan int, 1) 54 | go worker(buf) // 55 | var ok bool = false 56 | select { 57 | case buf <- tosend: 58 | ok = true 59 | default: 60 | ok = false 61 | } 62 | fmt.Println("sent3", tosend, ok) 63 | time.Sleep(6 * 1e9) 64 | // 65 | fmt.Println("End ....") 66 | } 67 | -------------------------------------------------------------------------------- /charshow/.gitignore: -------------------------------------------------------------------------------- 1 | charshow 2 | charshow.exe 3 | -------------------------------------------------------------------------------- /charshow/charshow.go: -------------------------------------------------------------------------------- 1 | /* 2 | Playing with UTF8 strings. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "unicode/utf8" 9 | ) 10 | 11 | func hrune(r rune) string { 12 | return fmt.Sprintf("%08x", r) 13 | } 14 | 15 | func main() { 16 | fmt.Println("hi") 17 | s := "𐒁̸" 18 | fmt.Println(s, len(s), utf8.RuneCountInString(s)) 19 | s = "汉" 20 | fmt.Println(s, len(s), utf8.RuneCountInString(s)) 21 | s = "𐒁̸汉" 22 | fmt.Println(s, len(s), utf8.RuneCountInString(s)) 23 | // 24 | for i, r := range s { 25 | fmt.Println(i, hrune(r), " ", string(r), utf8.RuneLen(r)) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dateshow/.gitignore: -------------------------------------------------------------------------------- 1 | dateshow 2 | dateshow.exe 3 | -------------------------------------------------------------------------------- /dateshow/dateshow.go: -------------------------------------------------------------------------------- 1 | /* 2 | Show oddities about date formatting. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | // Date formatting may show seemingly incorrect values when using a 12 | // local Location. 13 | func main() { 14 | fmt.Println("Start...") 15 | // 16 | l := "01/02/06" // Layout string 17 | d := "08/26/12" // Date string 18 | n, err := time.Parse(l, d[:8]) // Get time.Time 19 | if err != nil { 20 | panic(err) 21 | } 22 | fmt.Println("time.Time1:", n) // UTC, mm/dd/yy is correct 23 | // 24 | i := n.Unix() // Seconds 25 | nd := time.Unix(int64(i), 0) // Has local Location, here at present: EDT 26 | // For this example may show 08/25/12. 27 | fmt.Println("time.Time2:", nd) // Local, e.g. EST, mm/dd/yy may be incorrect 28 | // 29 | nu := nd.UTC() // Force to UTC 30 | fmt.Println("time.Time3:", nu) // UTC again, mm/dd/yy is correct 31 | // 32 | fmt.Println("End...") 33 | } 34 | -------------------------------------------------------------------------------- /defer/.gitignore: -------------------------------------------------------------------------------- 1 | defer 2 | defer.exe 3 | -------------------------------------------------------------------------------- /defer/defer.go: -------------------------------------------------------------------------------- 1 | /* 2 | A contrived example of using defer. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | /* 11 | Defers operate LIFO 12 | */ 13 | func printBack() { 14 | for i := 1; i <= 5; i++ { 15 | defer fmt.Printf("%d ", i) 16 | } 17 | } 18 | 19 | /* 20 | Using defer for tracing. 21 | */ 22 | func trace(s string) string { 23 | fmt.Println("entering: ", s) 24 | return s 25 | } 26 | 27 | // 28 | func un(s string) { 29 | fmt.Println("leaving: ", s) 30 | } 31 | func inner() { 32 | defer un(trace("inner")) 33 | fmt.Println("in inner()") 34 | } 35 | func outer() { 36 | defer un(trace("outer")) 37 | fmt.Println("in outer() before call") 38 | inner() 39 | fmt.Println("in outer() after call") 40 | } 41 | 42 | func main() { 43 | fmt.Println("Start...") 44 | printBack() 45 | // 46 | fmt.Println() 47 | outer() 48 | // 49 | fmt.Println("End...") 50 | } 51 | -------------------------------------------------------------------------------- /demo_templates/call/.gitignore: -------------------------------------------------------------------------------- 1 | call 2 | call.exe 3 | -------------------------------------------------------------------------------- /demo_templates/call/call.go: -------------------------------------------------------------------------------- 1 | /* 2 | From: 3 | https://github.com/golang/go/issues/10653 4 | https://play.golang.org/p/Ka8bN3_V1f 5 | */ 6 | package main 7 | 8 | import ( 9 | "os" 10 | "text/template" 11 | ) 12 | 13 | type TestStructA struct { 14 | Test func(string) string 15 | } 16 | 17 | func test(s string) string { 18 | return "Test A Says " + s + "\n" 19 | } 20 | 21 | type TestStructB struct { 22 | } 23 | 24 | func (self TestStructB) Test() func(string) string { 25 | return func(s string) string { return "Test B Says " + s + "\n" } 26 | } 27 | 28 | // DOES NOT WORK 29 | type TestStructC struct { 30 | } 31 | 32 | func (self TestStructC) Test(s string) string { 33 | return "Test C Says " + s + "\n" 34 | } 35 | 36 | func noCall() { 37 | tempStr := "{{.Test \"hi\"}}" // NB: no 'call' function used 38 | t := template.Must(template.New("test_temp2").Parse(tempStr)) 39 | testC := TestStructC{} 40 | err := t.Execute(os.Stdout, testC) 41 | if err != nil { 42 | panic(err) 43 | } 44 | } 45 | 46 | func main() { 47 | tempStr := "{{call .Test \"hi\"}}" 48 | t := template.Must(template.New("test_temp").Parse(tempStr)) 49 | 50 | testA := TestStructA{Test: test} 51 | err := t.Execute(os.Stdout, testA) 52 | if err != nil { 53 | panic(err) 54 | } 55 | 56 | testB := TestStructB{} 57 | err = t.Execute(os.Stdout, testB) 58 | if err != nil { 59 | panic(err) 60 | } 61 | 62 | noCall() // other way to do the 'does not work' part below 63 | 64 | // DOES NOT WORK 65 | testC := TestStructC{} 66 | err = t.Execute(os.Stdout, testC) 67 | if err != nil { 68 | panic(err) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /demo_templates/conditions/.gitignore: -------------------------------------------------------------------------------- 1 | conditions 2 | conditions.exe 3 | -------------------------------------------------------------------------------- /demo_templates/conditions/conditions.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example from: 3 | https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "os" 10 | "text/template" 11 | ) 12 | 13 | func main() { 14 | tEmpty := template.New("template test") 15 | tEmpty = template.Must(tEmpty.Parse("Empty pipeline if demo: {{if ``}} will not be outputted. {{end}}\n")) 16 | tEmpty.Execute(os.Stdout, nil) 17 | 18 | tWithValue := template.New("template test") 19 | tWithValue = template.Must(tWithValue.Parse("Not empty pipeline if demo: {{if `anything`}} will be outputted. {{end}}\n")) 20 | tWithValue.Execute(os.Stdout, nil) 21 | 22 | tIfElse := template.New("template test") 23 | tIfElse = template.Must(tIfElse.Parse("if-else demo: {{if `anything`}} if part {{else}} else part.{{end}}\n")) 24 | tIfElse.Execute(os.Stdout, nil) 25 | } 26 | -------------------------------------------------------------------------------- /demo_templates/functions/.gitignore: -------------------------------------------------------------------------------- 1 | functions 2 | functions.exe 3 | -------------------------------------------------------------------------------- /demo_templates/functions/functions.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example from: 3 | https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "html/template" 11 | "os" 12 | "strings" 13 | ) 14 | 15 | type Friend struct { 16 | Fname string 17 | } 18 | 19 | type Person struct { 20 | UserName string 21 | Emails []string 22 | Friends []*Friend 23 | } 24 | 25 | func EmailDealWith(args ...interface{}) string { 26 | ok := false 27 | var s string 28 | if len(args) == 1 { 29 | s, ok = args[0].(string) 30 | } 31 | if !ok { 32 | s = fmt.Sprint(args...) 33 | } 34 | // find the @ symbol 35 | substrs := strings.Split(s, "@") 36 | if len(substrs) != 2 { 37 | return s 38 | } 39 | // replace the @ by " at " 40 | return (substrs[0] + " at " + substrs[1]) 41 | } 42 | 43 | func main() { 44 | f1 := Friend{Fname: "Chris"} 45 | f2 := Friend{Fname: "George"} 46 | t := template.New("fieldname example") 47 | t = t.Funcs(template.FuncMap{"emailDeal": EmailDealWith}) 48 | t, _ = t.Parse(`hello {{.UserName}}! 49 | {{range .Emails}} 50 | an emails {{.|emailDeal}} 51 | {{end}} 52 | {{with .Friends}} 53 | {{range .}} 54 | my friend name is {{.Fname}} 55 | {{end}} 56 | {{end}} 57 | `) 58 | p := Person{UserName: "Guy", 59 | Emails: []string{"guy@gmallard.com", "allard.guy.m@gmail.com"}, 60 | Friends: []*Friend{&f1, &f2}} 61 | t.Execute(os.Stdout, p) 62 | } 63 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/fieldname/.gitignore: -------------------------------------------------------------------------------- 1 | fieldname 2 | fieldname.exe 3 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/fieldname/fieldname.go: -------------------------------------------------------------------------------- 1 | /* 2 | Modified From: http://golangtutorials.blogspot.com/2011/06/go-templates.html 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "text/template" 10 | ) 11 | 12 | type Person struct { 13 | Name string 14 | AgeField string // OK 15 | } 16 | 17 | func main() { 18 | p := Person{Name: "Mary", AgeField: "31"} 19 | 20 | t := template.New("nonexported template demo") 21 | t, _ = t.Parse("hello1 {{.Name}}! ") 22 | err := t.Execute(os.Stdout, p) 23 | if err != nil { 24 | fmt.Println("There was an error:", err) 25 | } 26 | // 27 | t, _ = t.Parse("Age {{.AgeField}}!\n") 28 | err = t.Execute(os.Stdout, p) 29 | if err != nil { 30 | fmt.Println("There was an error:", err) 31 | } 32 | // 33 | t, _ = t.Parse("hello2 {{.Name}}! Age {{.AgeField}}!\n") 34 | err = t.Execute(os.Stdout, p) 35 | if err != nil { 36 | fmt.Println("There was an error:", err) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/printf/.gitignore: -------------------------------------------------------------------------------- 1 | printf 2 | printf.exe 3 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/printf/printf.go: -------------------------------------------------------------------------------- 1 | /* 2 | From: 3 | http://golangtutorials.blogspot.com/2011/10/go-templates-part-2.html 4 | */ 5 | package main 6 | 7 | import ( 8 | "os" 9 | "text/template" 10 | ) 11 | 12 | func main() { 13 | t := template.New("test") 14 | t = template.Must(t.Parse("{{with $x := `hello`}}{{printf `%s %s` $x `Mary`}}{{end}}!\n")) 15 | t.Execute(os.Stdout, nil) 16 | } 17 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/revquotes/.gitignore: -------------------------------------------------------------------------------- 1 | revquotes 2 | revquotes.exe 3 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/revquotes/revquotes.go: -------------------------------------------------------------------------------- 1 | /* 2 | From: 3 | http://golangtutorials.blogspot.com/2011/10/go-templates-part-2.html 4 | */ 5 | package main 6 | 7 | import ( 8 | "os" 9 | "text/template" 10 | ) 11 | 12 | func main() { 13 | t := template.New("template test") 14 | t = template.Must(t.Parse("This is just static text. \n{{\"This is pipeline data - because it is evaluated within the double braces.\"}} {{`So is this, but within reverse quotes.`}}\n")) 15 | t.Execute(os.Stdout, nil) 16 | } 17 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/tvars/.gitignore: -------------------------------------------------------------------------------- 1 | tvars 2 | tvars.exe 3 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/tvars/tvars.go: -------------------------------------------------------------------------------- 1 | /* 2 | From: 3 | http://golangtutorials.blogspot.com/2011/10/go-templates-part-2.html 4 | */ 5 | package main 6 | 7 | /* 8 | You can create local variables for the pipelines within the template by 9 | prefixing the variable name with a "$" sign. Variable names have to be composed 10 | of alphanumeric characters and the underscore. In the example below I have used 11 | a few variations that work for variable names. 12 | */ 13 | import ( 14 | "os" 15 | "text/template" 16 | ) 17 | 18 | func main() { 19 | t := template.Must(template.New("name").Parse("{{with $3 := `hello`}}{{$3}}{{end}}!\n")) 20 | t.Execute(os.Stdout, nil) 21 | 22 | t1 := template.Must(template.New("name1").Parse("{{with $x3 := `hola`}}{{$x3}}{{end}}!\n")) 23 | t1.Execute(os.Stdout, nil) 24 | 25 | t2 := template.Must(template.New("name2").Parse("{{with $x_1 := `hey`}}{{$x_1}} {{.}} {{$x_1}}{{end}}!\n")) 26 | t2.Execute(os.Stdout, nil) 27 | } 28 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/twithend/.gitignore: -------------------------------------------------------------------------------- 1 | twithend 2 | twithend.exe 3 | -------------------------------------------------------------------------------- /demo_templates/golangtutorials/twithend/twithend.go: -------------------------------------------------------------------------------- 1 | /* 2 | From: 3 | http://golangtutorials.blogspot.com/2011/10/go-templates-part-2.html 4 | */ 5 | package main 6 | 7 | import ( 8 | "os" 9 | "text/template" 10 | ) 11 | 12 | func main() { 13 | t, _ := template.New("test").Parse("{{with `hello`}}{{.}}{{end}}!\n") 14 | t.Execute(os.Stdout, nil) 15 | 16 | t1, _ := template.New("test").Parse("{{with `hello`}}{{.}} {{with `Mary`}}{{.}}{{end}}{{end}}!\n") //when nested, the dot takes the value according to closest scope. 17 | t1.Execute(os.Stdout, nil) 18 | } 19 | -------------------------------------------------------------------------------- /demo_templates/insdata/.gitignore: -------------------------------------------------------------------------------- 1 | insdata 2 | insdata.exe 3 | -------------------------------------------------------------------------------- /demo_templates/insdata/insdata.go: -------------------------------------------------------------------------------- 1 | /* 2 | From: https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 3 | */ 4 | package main 5 | 6 | import ( 7 | "html/template" 8 | "os" 9 | ) 10 | 11 | type Person struct { 12 | UserName string 13 | } 14 | 15 | func main() { 16 | t := template.New("fieldname example") 17 | t, _ = t.Parse("hello {{.UserName}}!\n") 18 | p := Person{UserName: "Guy"} 19 | t.Execute(os.Stdout, p) 20 | } 21 | -------------------------------------------------------------------------------- /demo_templates/jst/.gitignore: -------------------------------------------------------------------------------- 1 | jst 2 | jst.exe 3 | -------------------------------------------------------------------------------- /demo_templates/jst/jst.go: -------------------------------------------------------------------------------- 1 | /* 2 | js function example. 3 | */ 4 | package main 5 | 6 | import ( 7 | "os" 8 | "text/template" 9 | ) 10 | 11 | type Person struct { 12 | UserName string 13 | UserID int 14 | } 15 | 16 | func main() { 17 | // Not sure I see a practical use for the 'js' function. 18 | t := template.New("JS example") 19 | as := `{{js .}} 20 | ` 21 | t, _ = t.Parse(as) 22 | p := Person{UserName: "Guy", UserID: 123456} 23 | // The output here is somewhat unexpected. At the very least, it is not 24 | // what I anticipated. 25 | t.Execute(os.Stdout, p) 26 | } 27 | -------------------------------------------------------------------------------- /demo_templates/must/.gitignore: -------------------------------------------------------------------------------- 1 | must 2 | must.exe 3 | -------------------------------------------------------------------------------- /demo_templates/must/must.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example from: 3 | https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "text/template" 11 | ) 12 | 13 | func main() { 14 | tOk := template.New("first") 15 | template.Must(tOk.Parse(" some static text /* and a comment */")) 16 | fmt.Println("The first one parsed OK.") 17 | 18 | template.Must(template.New("second").Parse("some static text {{ .Name }}")) 19 | fmt.Println("The second one parsed OK.") 20 | 21 | fmt.Println("The next one ought to fail.") 22 | tErr := template.New("check parse error with Must") 23 | template.Must(tErr.Parse(" some static text {{ .Name }")) 24 | } 25 | -------------------------------------------------------------------------------- /demo_templates/nestedfields/.gitignore: -------------------------------------------------------------------------------- 1 | nestedfields 2 | nestedfields.exe 3 | 4 | -------------------------------------------------------------------------------- /demo_templates/nestedfields/nestedfields.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example from: 3 | https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "os" 10 | "text/template" 11 | ) 12 | 13 | type Friend struct { 14 | Fname string 15 | } 16 | 17 | type Person struct { 18 | UserName string 19 | Emails []string 20 | Friends []*Friend 21 | } 22 | 23 | func main() { 24 | f1 := Friend{Fname: "Chris"} 25 | f2 := Friend{Fname: "George"} 26 | t := template.New("fieldname example 2") 27 | t, _ = t.Parse(`hello {{.UserName}}! 28 | {{range .Emails}} 29 | an email {{.}} 30 | {{end}} 31 | {{/* Next section */}} 32 | {{with .Friends}} 33 | {{range .}} 34 | my friend's name is {{.Fname}} 35 | {{end}} 36 | {{end}} 37 | `) 38 | p := Person{UserName: "Guy", 39 | Emails: []string{"guy@gmallard.com", "allard.guy.m@gmail.com"}, 40 | Friends: []*Friend{&f1, &f2}} 41 | t.Execute(os.Stdout, p) 42 | } 43 | -------------------------------------------------------------------------------- /demo_templates/nestedtemplates/.gitignore: -------------------------------------------------------------------------------- 1 | nestedtemplates 2 | nestedtemplates.exe 3 | -------------------------------------------------------------------------------- /demo_templates/nestedtemplates/nestedtemplages.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example (modified) from: 3 | https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "io/ioutil" 11 | "os" 12 | "strings" 13 | "text/template" 14 | ) 15 | 16 | var templates *template.Template 17 | 18 | func main() { 19 | var allFiles []string 20 | files, err := ioutil.ReadDir("./tmplfiles") 21 | if err != nil { 22 | fmt.Println(err) 23 | } 24 | for _, file := range files { 25 | filename := file.Name() 26 | if strings.HasSuffix(filename, ".tmpl") { 27 | allFiles = append(allFiles, "./tmplfiles/"+filename) 28 | } 29 | } 30 | 31 | templates, err = template.ParseFiles(allFiles...) // parses all .tmpl files in the 'templates' folder 32 | 33 | //s1 := templates.Lookup("header.tmpl") 34 | //s1.ExecuteTemplate(os.Stdout, "header", nil) 35 | //fmt.Println() 36 | s2 := templates.Lookup("content.tmpl") 37 | s2.ExecuteTemplate(os.Stdout, "content", nil) 38 | fmt.Println() 39 | //s3 := templates.Lookup("footer.tmpl") 40 | //s3.ExecuteTemplate(os.Stdout, "footer", nil) 41 | //fmt.Println() 42 | //s3.Execute(os.Stdout, nil) 43 | } 44 | -------------------------------------------------------------------------------- /demo_templates/nestedtemplates/tmplfiles/content.tmpl: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 | {{template "header"}} 3 |

Nested here

4 | 8 | {{template "footer"}} 9 | {{end}} -------------------------------------------------------------------------------- /demo_templates/nestedtemplates/tmplfiles/footer.tmpl: -------------------------------------------------------------------------------- 1 | {{define "footer"}} 2 | 3 | 4 | {{end}} -------------------------------------------------------------------------------- /demo_templates/nestedtemplates/tmplfiles/header.tmpl: -------------------------------------------------------------------------------- 1 | {{define "header"}} 2 | 3 | 4 | Something here 5 | 6 | 7 | {{end}} -------------------------------------------------------------------------------- /demo_templates/pipelines/.gitignore: -------------------------------------------------------------------------------- 1 | pipelines 2 | pipelines.exe 3 | 4 | -------------------------------------------------------------------------------- /demo_templates/readme.txt: -------------------------------------------------------------------------------- 1 | Some examples from: 2 | 3 | - The template documentation (godoc) 4 | 5 | - https://astaxie.gitbooks.io/build-web-application-with-golang/en/07.4.html 6 | 7 | // Some of the examples from golangtutorials are basicallly the same as 8 | // examples from the astaxie project. 9 | - http://golangtutorials.blogspot.com/2011/06/go-templates.html 10 | - http://golangtutorials.blogspot.com/2011/10/go-templates-part-2.html 11 | - http://golangtutorials.blogspot.com/2011/11/go-templates-part-3-template-sets.html 12 | -------------------------------------------------------------------------------- /dtemplex1/.gitignore: -------------------------------------------------------------------------------- 1 | dtemplex1 2 | dtemplex1.exe 3 | -------------------------------------------------------------------------------- /dtemplex1/dtemplex1.go: -------------------------------------------------------------------------------- 1 | /* 2 | Simple template example. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "text/template" 10 | ) 11 | 12 | type Data struct { 13 | Title string 14 | Vi int 15 | Vs string 16 | } 17 | 18 | const td = ` 19 | This is the title: {{.Title}} 20 | 21 | The int is: {{.Vi}} 22 | The string is: {{.Vs}} 23 | ` 24 | 25 | var Datum = Data{Title: "Chapter 1", Vi: 123, Vs: "bogus line"} 26 | 27 | func main() { 28 | fmt.Println("Datum:", Datum) 29 | // 30 | t1 := template.New("T1") 31 | t1, err := t1.Parse(td) 32 | if err != nil { 33 | fmt.Println("err1", err) 34 | } 35 | err = t1.Execute(os.Stdout, Datum) 36 | if err != nil { 37 | fmt.Println("err2", err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dtemplex2/.gitignore: -------------------------------------------------------------------------------- 1 | dtemplex2 2 | dtemplex2.exe 3 | -------------------------------------------------------------------------------- /dtemplex2/dtemplex2.go: -------------------------------------------------------------------------------- 1 | /* 2 | Template example. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "text/template" 10 | ) 11 | 12 | type Headers []string 13 | 14 | type Body []uint8 15 | 16 | type Data struct { 17 | Command string 18 | Headers Headers 19 | Body Body 20 | } 21 | 22 | func (h Headers) String() string { 23 | s := "" 24 | for i := 0; i < len(h); i += 2 { 25 | s = s + h[i] + "," + h[i+1] + "\n" 26 | } 27 | return s 28 | } 29 | 30 | func (b Body) String() string { 31 | return string(b) 32 | } 33 | 34 | const td = `{{.Command}} 35 | {{.Headers}} 36 | {{.Body}} 37 | ` 38 | 39 | var Datum = Data{Command: "ACOMMAND", 40 | Headers: Headers{"K1", "v1", "K2", "v2"}, 41 | Body: []uint8("test")} 42 | 43 | func main() { 44 | // fmt.Println("Datum:", Datum) 45 | // fmt.Println("thp:", Datum.Headers) 46 | // fmt.Println("thb:", Datum.Body) 47 | // 48 | t1 := template.New("T1") 49 | t1, err := t1.Parse(td) 50 | if err != nil { 51 | fmt.Println("err1", err) 52 | } 53 | err = t1.Execute(os.Stdout, Datum) 54 | if err != nil { 55 | fmt.Println("err2", err) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /envshow/.gitignore: -------------------------------------------------------------------------------- 1 | envshow 2 | envshow.exe 3 | -------------------------------------------------------------------------------- /envshow/envshow.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using OS environment variables. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "os" // 9 | ) 10 | 11 | func main() { 12 | fmt.Println("Start...") 13 | // 14 | env_hello := os.Getenv("PATH") // Probably here 15 | fmt.Printf("PATH is: !%s!\n", env_hello) 16 | // 17 | env_hello = os.Getenv("SOME_JUNK") // Probably not here 18 | fmt.Printf("SOME_JUNK is: !%s!\n", env_hello) 19 | // 20 | fmt.Println("End...") 21 | } 22 | -------------------------------------------------------------------------------- /errtest/.gitignore: -------------------------------------------------------------------------------- 1 | errtest 2 | errtest.exe 3 | -------------------------------------------------------------------------------- /errtest/errtest.go: -------------------------------------------------------------------------------- 1 | /* 2 | Fiddling with Error types. 3 | */ 4 | package main 5 | 6 | import "fmt" // 7 | 8 | type Error string 9 | 10 | func (e Error) Error() string { 11 | return string(e) 12 | } 13 | 14 | const ( 15 | ERRA = Error("error A") 16 | ERRB = Error("error B") 17 | ) 18 | 19 | func badA() error { 20 | return ERRA 21 | } 22 | 23 | func badB() error { 24 | return ERRB 25 | } 26 | 27 | func main() { 28 | fmt.Println("Start...") 29 | 30 | ea := badA() 31 | fmt.Println("ea:", ea) 32 | 33 | eb := badB() 34 | fmt.Println("eb:", eb) 35 | 36 | if ea == ERRA { 37 | fmt.Println("yep, ea is OK") 38 | } 39 | 40 | if ea != eb { 41 | fmt.Println("yep, eb is OK also") 42 | } 43 | 44 | fmt.Println("End...") 45 | } 46 | -------------------------------------------------------------------------------- /fib/.gitignore: -------------------------------------------------------------------------------- 1 | fib 2 | fib.exe 3 | -------------------------------------------------------------------------------- /fib/fib.go: -------------------------------------------------------------------------------- 1 | /* 2 | The obligatory Fibonacci number example. 3 | */ 4 | package main 5 | 6 | // Import formatting package 7 | import "fmt" 8 | 9 | // 10 | // A somewhat classical recursive function to determine the n'th 11 | // fibonacci number. This includes the definition of fibinacci 12 | // numbers for negative integers. 13 | // 14 | // Reference: http://en.wikipedia.org/wiki/Fibonacci_number 15 | // 16 | func fib(i int) int { 17 | // The basics: 0 and 1 18 | if i == 0 || i == 1 { 19 | return i 20 | } 21 | // For negative integers. 22 | if i < 0 { 23 | posfib := fib(-1 * i) 24 | // See formulae at the above reference. 25 | if (-1*i+1)%2 != 0 { 26 | return -posfib 27 | } 28 | return posfib 29 | } 30 | // And for all other positives. 31 | return fib(i-1) + fib(i-2) 32 | } 33 | 34 | // 35 | // Mainline. 36 | // 37 | func main() { 38 | // List some fibonacci numbers. 39 | fmt.Printf("n \tfib(n)\n") 40 | fmt.Printf("==\t======\n") 41 | for x := -10; x < 11; x++ { 42 | fmt.Printf("%d\t%d\n", x, fib(x)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /fib_embellished/.gitignore: -------------------------------------------------------------------------------- 1 | fib_embellished 2 | fib_embellished.exe 3 | -------------------------------------------------------------------------------- /fib_embellished/fib_embellished.go: -------------------------------------------------------------------------------- 1 | /* 2 | An embellished Fibinacci number example. 3 | */ 4 | package main 5 | 6 | // 7 | import "fmt" 8 | 9 | /* 10 | Demonstrate: 11 | 12 | a) multiple return values 13 | b) use of := in functions 14 | 15 | */ 16 | 17 | // 18 | // -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 19 | // ...,-8, 5,-3, 2,-1, 1, 0, 1, 1, 2, 3, 5, 8,... 20 | // 21 | // Reference: http://en.wikipedia.org/wiki/Fibonacci_number 22 | // 23 | func fib(i int) (result int, flag bool) { 24 | // The basics: 0 and 1 25 | if i == 0 || i == 1 { 26 | return i, true 27 | } 28 | // For negative integers. 29 | if i < 0 { 30 | posfib, ok := fib(-1 * i) 31 | // See formulae at the above reference. 32 | if (-1*i+1)%2 != 0 { 33 | return -posfib, ok 34 | } 35 | return posfib, ok 36 | } 37 | // 38 | resm1, flagm1 := fib(i - 1) 39 | resm2, flagm2 := fib(i - 2) 40 | return resm1 + resm2, flagm1 || flagm2 41 | } 42 | 43 | func main() { 44 | fmt.Printf("n \tfib(n)\tCheck\n") 45 | fmt.Printf("==\t======\t=====\n") 46 | // 47 | for ni := -7; ni <= 6; ni++ { 48 | result, flag := fib(ni) 49 | fmt.Printf("%d\t%d\t%t\n", ni, result, flag) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /fib_userop/.gitignore: -------------------------------------------------------------------------------- 1 | fib_userop 2 | fib_userop.exe 3 | -------------------------------------------------------------------------------- /fib_userop/fib_userop.go: -------------------------------------------------------------------------------- 1 | /* 2 | Yet another Fibonacci number example using a user defined operator. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | /* 9 | User supplied add function. 10 | */ 11 | func myadd(i, j int) int { 12 | return i + j 13 | } 14 | 15 | /* 16 | Demonstrate: 17 | 18 | a) Use of user supplied add operation 19 | 20 | */ 21 | func fib(i int) (result int, flag bool) { 22 | // The basics: 0 and 1 23 | if i == 0 || i == 1 { 24 | return i, true 25 | } 26 | // For negative integers. 27 | if i < 0 { 28 | posfib, ok := fib(-1 * i) 29 | // See formulae at the above reference. 30 | if (-1*i+1)%2 != 0 { 31 | return -posfib, ok 32 | } 33 | return posfib, ok 34 | } 35 | // 36 | resm1, flagm1 := fib(i - 1) 37 | resm2, flagm2 := fib(i - 2) 38 | return myadd(resm1, resm2), flagm1 || flagm2 39 | } 40 | 41 | func main() { 42 | fmt.Printf("n \tfib(n)\tCheck\n") 43 | fmt.Printf("==\t======\t=====\n") 44 | // 45 | for ni := -6; ni < 7; ni++ { 46 | result, flag := fib(ni) 47 | fmt.Printf("%d\t%d\t%t\n", ni, result, flag) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /fileread/.gitignore: -------------------------------------------------------------------------------- 1 | fileread 2 | fileread.exe 3 | -------------------------------------------------------------------------------- /fileread/data.txt: -------------------------------------------------------------------------------- 1 | Line 1 2 | Line 2 3 | Line 3 4 | Line 4 5 | Line 5 6 | -------------------------------------------------------------------------------- /fileread/datacrlf.txt: -------------------------------------------------------------------------------- 1 | Line 1 2 | Line 2 3 | Line 3 4 | Line 4 5 | Line 5 6 | -------------------------------------------------------------------------------- /fileread/fileread.go: -------------------------------------------------------------------------------- 1 | /* 2 | A text file reader. 3 | */ 4 | package main 5 | 6 | // 7 | // A text file reader. 8 | // 9 | import ( 10 | "bufio" 11 | "fmt" 12 | "io" 13 | "os" 14 | ) 15 | 16 | func main() { 17 | fmt.Println("Start....") 18 | 19 | fname := "./data.txt" 20 | if os.Getenv("INFILE") != "" { 21 | fname = os.Getenv("INFILE") 22 | } 23 | // Open 24 | // f is *File. 25 | f, err := os.OpenFile(fname, os.O_RDONLY, 0644) 26 | if err != nil { 27 | fmt.Printf("\nOpen Error => %s\n\n", err) 28 | os.Exit(1) 29 | } 30 | 31 | // Read lines 32 | reader := bufio.NewReader(f) // Buffered reader 33 | for { 34 | line, err := reader.ReadString('\n') 35 | if err == io.EOF { 36 | break 37 | } 38 | line = line[0 : len(line)-1] 39 | fmt.Printf("Line Detail: |%q|\n", line) 40 | fmt.Printf("Line as a string: |%s|\n", line) 41 | } 42 | 43 | // Close 44 | err = f.Close() 45 | if err != nil { 46 | fmt.Printf("\nClose Error => %s\n\n", err) 47 | os.Exit(1) 48 | } 49 | // 50 | fmt.Println("End....") 51 | } 52 | -------------------------------------------------------------------------------- /filescan/.gitignore: -------------------------------------------------------------------------------- 1 | filescan 2 | filescan.exe 3 | -------------------------------------------------------------------------------- /filescan/filescan.go: -------------------------------------------------------------------------------- 1 | /* 2 | A demonstration of using a bufio scanner. Requires go 1.1. 3 | */ 4 | package main 5 | 6 | import ( 7 | "bufio" 8 | "fmt" 9 | "os" 10 | ) 11 | 12 | func main() { 13 | fmt.Println("hi") 14 | f, e := os.Open("./t.txt") 15 | if e != nil { 16 | panic(e) 17 | } 18 | defer f.Close() 19 | s := bufio.NewScanner(f) 20 | for s.Scan() { 21 | t := s.Text() 22 | if t == "" { 23 | continue 24 | } 25 | fmt.Println(t) 26 | } 27 | if e = s.Err(); e != nil { 28 | panic(e) 29 | } 30 | fmt.Println("bye") 31 | } 32 | -------------------------------------------------------------------------------- /filescan/t.txt: -------------------------------------------------------------------------------- 1 | Line 1 2 | Line 2 3 | Line 3 4 | 5 | -------------------------------------------------------------------------------- /flagdemo/.gitignore: -------------------------------------------------------------------------------- 1 | flagdemo 2 | flagdemo.exe 3 | -------------------------------------------------------------------------------- /flagdemo/flagdemo.go: -------------------------------------------------------------------------------- 1 | /* 2 | Flag package, a short demo. 3 | */ 4 | package main 5 | 6 | import ( 7 | "flag" 8 | "fmt" // 9 | "time" 10 | ) 11 | 12 | // Flag variables 13 | var ( 14 | intFlag int 15 | strFlag string 16 | boolFlag bool 17 | durFlag time.Duration 18 | ) 19 | 20 | // Main initialization, a convenient place to set flags up 21 | func init() { 22 | flag.IntVar(&intFlag, "fintflag", 1234, "help message for fintflag") 23 | flag.StringVar(&strFlag, "fstrflag", "abcd", "help message for fstrflag") 24 | flag.BoolVar(&boolFlag, "fboolflag", false, "help message for fboolflag") 25 | flag.DurationVar(&durFlag, "fdurflag", 3*time.Minute, "help message for fdurflag") 26 | } 27 | 28 | func main() { 29 | // 30 | fmt.Println("Start...") 31 | 32 | // 33 | flag.Parse() // Parse all flags 34 | 35 | // Print them 36 | fmt.Println("fintflag", intFlag) 37 | fmt.Println("fstrflag", strFlag) 38 | fmt.Println("fboolflag", boolFlag) 39 | fmt.Println("fdurflag", durFlag) 40 | 41 | // 42 | fmt.Println("End...") 43 | } 44 | -------------------------------------------------------------------------------- /force_type/.gitignore: -------------------------------------------------------------------------------- 1 | force_type 2 | force_type.exe 3 | -------------------------------------------------------------------------------- /force_type/force_type.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using type coercion with automatic declares. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | func main() { 11 | fmt.Println("Start...") 12 | // Corece type with auto declaration 13 | i := int32(0) 14 | fmt.Printf("%v\n", i) 15 | // Corece type with auto declaration 16 | j := int64(5) 17 | fmt.Printf("%v\n", j) 18 | fmt.Println("End...") 19 | } 20 | -------------------------------------------------------------------------------- /func_lit/.gitignore: -------------------------------------------------------------------------------- 1 | func_lit 2 | func_lit.exe 3 | -------------------------------------------------------------------------------- /func_lit/func_lit.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using function literals. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | /* 11 | Functions cannot be defined inside functions. 12 | However, function literals may be defined and used. 13 | */ 14 | func runLit() { 15 | // 16 | g := func(i int) { fmt.Printf("%d\n", i) } 17 | // 18 | for i := 0; i < 10; i++ { 19 | g(i) 20 | } 21 | } 22 | 23 | /* 24 | Function literals are closures. 25 | */ 26 | func adder() func(int) int { 27 | var x int 28 | return func(delta int) int { 29 | x += delta 30 | return x 31 | } 32 | } 33 | 34 | // 35 | func main() { 36 | fmt.Println("Start...") 37 | // 38 | runLit() 39 | // 40 | fmt.Println() 41 | var f = adder() 42 | fmt.Println(f(1)) 43 | fmt.Println(f(20)) 44 | fmt.Println(f(300)) 45 | // 46 | fmt.Println("End...") 47 | } 48 | -------------------------------------------------------------------------------- /func_ret/.gitignore: -------------------------------------------------------------------------------- 1 | func_ret 2 | func_ret.exe 3 | -------------------------------------------------------------------------------- /fwalker/.gitignore: -------------------------------------------------------------------------------- 1 | fwalker 2 | fwalker.exe 3 | 4 | -------------------------------------------------------------------------------- /fwalker/fwalker.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demo a 'os' package based directory walker. 3 | */ 4 | package main 5 | 6 | import ( 7 | //"fmt" 8 | "log" 9 | "os" 10 | "path" 11 | ) 12 | 13 | var ( 14 | seltype = "" 15 | ) 16 | 17 | func walkDir(wd string) { 18 | fd, e := os.Open(wd) 19 | if e != nil { 20 | log.Fatalln("Open error:", e) 21 | } 22 | log.Printf("===== Start Next Dir:%s\n", wd) 23 | var subdirs []string 24 | fil, e := fd.Readdir(-1) 25 | if e != nil { 26 | log.Fatalln("Readdir error:", e) 27 | } 28 | // Process Files 29 | for _, nfi := range fil { 30 | prtFileInfo(nfi) 31 | if nfi.IsDir() { 32 | subdirs = append(subdirs, nfi.Name()) 33 | continue 34 | } 35 | nfn := wd + string(os.PathSeparator) + nfi.Name() 36 | log.Printf("Next File Name:%s\n", nfn) 37 | if seltype != "" { 38 | fext := path.Ext(nfn) 39 | log.Printf("File Extension:%s\n", fext) 40 | if fext != "" { 41 | fext = fext[1:] // Eliminate the '.' 42 | } 43 | if fext == seltype { 44 | log.Printf("Selected File:%s\n", nfn) 45 | } 46 | } 47 | } 48 | // Process subdirs 49 | for _, nsd := range subdirs { 50 | absd := wd + string(os.PathSeparator) + nsd 51 | walkDir(absd) 52 | } 53 | } 54 | 55 | func main() { 56 | log.Printf("Start") 57 | seltype = os.Getenv("SELTYPE") // Use this to 'select' a file extension 58 | log.Printf("Select Type:%s\n", seltype) 59 | walkbase := os.Getenv("WALKDIR") // Supply your own start subdirectoy here 60 | e := os.Chdir(walkbase) 61 | if e != nil { 62 | log.Fatalln("Chdir error:", e) 63 | } 64 | fdn, e := os.Getwd() 65 | if e != nil { 66 | log.Fatalln("Getwd error:", e) 67 | } 68 | log.Println("Full Path:", fdn) 69 | walkDir(fdn) 70 | log.Printf("End") 71 | } 72 | 73 | func prtFileInfo(fi os.FileInfo) { 74 | log.Println("===== Next File Info:") 75 | log.Printf("Name:%s\n", fi.Name()) 76 | log.Printf("Size:%d\n", fi.Size()) 77 | fm := fi.Mode() 78 | bp := fm.Perm() 79 | log.Printf("Mode:%v (%0o)\n", fm, uint32(bp)) 80 | log.Printf("ModTime:%v\n", fi.ModTime()) 81 | log.Printf("IsDir:%v\n", fi.IsDir()) 82 | //log.Printf("Sys:%v\n", fi.Sys()) 83 | } 84 | -------------------------------------------------------------------------------- /gio12gs01/.gitignore: -------------------------------------------------------------------------------- 1 | gio12gs01 2 | gio12gs01.exe 3 | -------------------------------------------------------------------------------- /gio12gs01/gio12gs01.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | type Result string 13 | 14 | type Search func(query string) Result 15 | 16 | var ( 17 | Web = fakeSearch("web") 18 | Image = fakeSearch("image") 19 | Video = fakeSearch("video") 20 | ) 21 | 22 | func fakeSearch(kind string) Search { 23 | return func(query string) Result { 24 | time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) 25 | return Result(fmt.Sprintf("%s result for %q\n", kind, query)) 26 | } 27 | } 28 | 29 | func Google(query string) (results []Result) { 30 | 31 | // return []Result{Web(query), Image(query), Video(query)} // This works 32 | 33 | // Code from the presentation: 34 | results = append(results, Web(query)) 35 | results = append(results, Image(query)) 36 | results = append(results, Video(query)) 37 | return 38 | } 39 | 40 | func main() { 41 | rand.Seed(time.Now().UnixNano()) 42 | start := time.Now() 43 | results := Google("golang") 44 | elapsed := time.Since(start) 45 | fmt.Println(results) 46 | fmt.Println("elapsed:", elapsed) 47 | } 48 | -------------------------------------------------------------------------------- /gio12gs02/.gitignore: -------------------------------------------------------------------------------- 1 | gio12gs02 2 | gio12gs02.exe 3 | -------------------------------------------------------------------------------- /gio12gs02/gio12gs02.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | type Result string 13 | 14 | type Search func(query string) Result 15 | 16 | var ( 17 | Web = fakeSearch("web") 18 | Image = fakeSearch("image") 19 | Video = fakeSearch("video") 20 | ) 21 | 22 | func fakeSearch(kind string) Search { 23 | return func(query string) Result { 24 | time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) 25 | return Result(fmt.Sprintf("%s result for %q\n", kind, query)) 26 | } 27 | } 28 | 29 | func Google(query string) (results []Result) { 30 | 31 | // Code from the presentation: 32 | c := make(chan Result) 33 | // Run queries concurrently (fanIn) 34 | go func() { c <- Web(query) }() 35 | go func() { c <- Image(query) }() 36 | go func() { c <- Video(query) }() 37 | for i := 0; i < 3; i++ { 38 | result := <-c 39 | results = append(results, result) 40 | } 41 | return 42 | } 43 | 44 | func main() { 45 | rand.Seed(time.Now().UnixNano()) 46 | start := time.Now() 47 | results := Google("golang") 48 | elapsed := time.Since(start) 49 | fmt.Println(results) 50 | fmt.Println("elapsed:", elapsed) 51 | } 52 | -------------------------------------------------------------------------------- /gio12gs03/.gitignore: -------------------------------------------------------------------------------- 1 | gio12gs03 2 | gio12gs03.exe 3 | -------------------------------------------------------------------------------- /gio12gs03/gio12gs03.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | type Result string 13 | 14 | type Search func(query string) Result 15 | 16 | var ( 17 | Web = fakeSearch("web") 18 | Image = fakeSearch("image") 19 | Video = fakeSearch("video") 20 | ) 21 | 22 | func fakeSearch(kind string) Search { 23 | return func(query string) Result { 24 | time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) 25 | return Result(fmt.Sprintf("%s result for %q\n", kind, query)) 26 | } 27 | } 28 | 29 | func Google(query string) (results []Result) { 30 | 31 | // Code from the presentation: 32 | c := make(chan Result) 33 | // Run queries concurrently (fanIn) 34 | go func() { c <- Web(query) }() 35 | go func() { c <- Image(query) }() 36 | go func() { c <- Video(query) }() 37 | timeout := time.After(80 * time.Millisecond) 38 | 39 | for i := 0; i < 3; i++ { 40 | select { 41 | case result := <-c: 42 | results = append(results, result) 43 | case <-timeout: 44 | fmt.Println("timed out") 45 | return 46 | } 47 | } 48 | return 49 | } 50 | 51 | func main() { 52 | rand.Seed(time.Now().UnixNano()) 53 | start := time.Now() 54 | results := Google("golang") 55 | elapsed := time.Since(start) 56 | fmt.Println(results) 57 | fmt.Println("elapsed:", elapsed) 58 | } 59 | -------------------------------------------------------------------------------- /gio12gs04/.gitignore: -------------------------------------------------------------------------------- 1 | gio12gs04 2 | gio12gs04.exe 3 | -------------------------------------------------------------------------------- /gio12gs04/gio12gs04.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | type Result string 13 | 14 | type Search func(query string) Result 15 | 16 | func fakeSearch(kind string) Search { 17 | return func(query string) Result { 18 | time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) 19 | return Result(fmt.Sprintf("%s result for %q\n", kind, query)) 20 | } 21 | } 22 | 23 | func First(query string, replicas ...Search) Result { 24 | c := make(chan Result) 25 | searchReplica := func(i int) { c <- replicas[i](query) } 26 | for i := range replicas { 27 | go searchReplica(i) 28 | } 29 | return <-c 30 | } 31 | 32 | func main() { 33 | rand.Seed(time.Now().UnixNano()) 34 | start := time.Now() 35 | result := First("golang", fakeSearch("replica 1"), fakeSearch("replica 2")) 36 | elapsed := time.Since(start) 37 | fmt.Println(result) 38 | fmt.Println("elapsed:", elapsed) 39 | } 40 | -------------------------------------------------------------------------------- /gio12gs05/.gitignore: -------------------------------------------------------------------------------- 1 | gio12gs05 2 | gio12gs05.exe 3 | -------------------------------------------------------------------------------- /gio12gs05/gio12gs05.go: -------------------------------------------------------------------------------- 1 | /* 2 | Example code based on Google I/O 2012 concurrency presentation. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math/rand" 9 | "time" 10 | ) 11 | 12 | type Result string 13 | 14 | type Search func(query string) Result 15 | 16 | var ( 17 | Web1 = fakeSearch("web") 18 | Image1 = fakeSearch("image") 19 | Video1 = fakeSearch("video") 20 | Web2 = fakeSearch("web") 21 | Image2 = fakeSearch("image") 22 | Video2 = fakeSearch("video") 23 | ) 24 | 25 | func fakeSearch(kind string) Search { 26 | return func(query string) Result { 27 | time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) 28 | return Result(fmt.Sprintf("%s result for %q\n", kind, query)) 29 | } 30 | } 31 | 32 | func Google(query string) (results []Result) { 33 | 34 | // Code from the presentation: 35 | c := make(chan Result) 36 | // Run queries concurrently (fanIn) 37 | go func() { c <- First(query, Web1, Web2) }() // Multiple back ends ..... 38 | go func() { c <- First(query, Image1, Image2) }() 39 | go func() { c <- First(query, Video1, Video2) }() 40 | timeout := time.After(80 * time.Millisecond) 41 | 42 | for i := 0; i < 3; i++ { 43 | select { 44 | case result := <-c: 45 | results = append(results, result) 46 | case <-timeout: 47 | fmt.Println("timed out") 48 | return 49 | } 50 | } 51 | return 52 | } 53 | 54 | func First(query string, replicas ...Search) Result { 55 | c := make(chan Result) 56 | searchReplica := func(i int) { c <- replicas[i](query) } 57 | for i := range replicas { 58 | go searchReplica(i) 59 | } 60 | return <-c 61 | } 62 | 63 | func main() { 64 | rand.Seed(time.Now().UnixNano()) 65 | start := time.Now() 66 | results := Google("golang") 67 | elapsed := time.Since(start) 68 | fmt.Println(results) 69 | fmt.Println("elapsed:", elapsed) 70 | } 71 | -------------------------------------------------------------------------------- /gobdemo/.gitignore: -------------------------------------------------------------------------------- 1 | gobdemo 2 | gobdemo.exe 3 | -------------------------------------------------------------------------------- /gobdemo/gobdemo.go: -------------------------------------------------------------------------------- 1 | /* 2 | A demonstration of gob encoding and decoding. 3 | */ 4 | package main 5 | 6 | import ( 7 | "bytes" 8 | "encoding/gob" 9 | "fmt" 10 | "os" 11 | ) 12 | 13 | type sample struct { 14 | Id string 15 | Headers []string 16 | Body []byte 17 | } 18 | 19 | // Persist the encoded data. 20 | func writeFile(n string, d []byte) error { 21 | f, e := os.Create(n) 22 | if e != nil { 23 | return e 24 | } 25 | defer f.Close() 26 | nr, e := f.Write(d) 27 | if e != nil { 28 | return e 29 | } 30 | fmt.Println("WriteDataLen:", len(d), "Written:", nr) 31 | return nil 32 | } 33 | 34 | // Load the encoded data. 35 | func readFile(n string) ([]byte, error) { 36 | fi, e := os.Lstat(n) 37 | if e != nil { 38 | return nil, e 39 | } 40 | f, e := os.Open(n) 41 | if e != nil { 42 | return nil, e 43 | } 44 | defer f.Close() 45 | sz := int(fi.Size()) 46 | b := make([]byte, sz) 47 | nr, e := f.Read(b) 48 | if e != nil { 49 | return nil, e 50 | } 51 | fmt.Println("ReadDataLen:", len(b), "Read:", nr) 52 | return b, nil 53 | } 54 | 55 | func main() { 56 | // Sample data 57 | s := sample{"NAMEA", []string{"str1", "str2", "str3", "str4"}, 58 | []byte{0xa, 0xb, 0xc}} 59 | fmt.Printf("%+v\n", s) 60 | 61 | // Encode. 62 | buf := new(bytes.Buffer) 63 | enc := gob.NewEncoder(buf) 64 | err := enc.Encode(s) 65 | if err != nil { 66 | fmt.Println("enc.Encode failed:", err) 67 | return 68 | } 69 | 70 | // Persist and Reload. 71 | err = writeFile("./tempdata.dat", buf.Bytes()) 72 | if err != nil { 73 | fmt.Println("writeFile failed:", err) 74 | return 75 | } 76 | b, err := readFile("./tempdata.dat") 77 | if err != nil { 78 | fmt.Println("readFile failed:", err) 79 | return 80 | } 81 | 82 | // Decode. 83 | buf = bytes.NewBuffer(b) 84 | dec := gob.NewDecoder(buf) 85 | var d sample 86 | err = dec.Decode(&d) 87 | if err != nil { 88 | fmt.Println("dec.Decode failed:", err) 89 | return 90 | } 91 | fmt.Printf("%+v\n", d) 92 | } 93 | -------------------------------------------------------------------------------- /gorsynchs/.gitignore: -------------------------------------------------------------------------------- 1 | gorsynchs 2 | -------------------------------------------------------------------------------- /gorsynchs/chanex/.gitignore: -------------------------------------------------------------------------------- 1 | chanex 2 | 3 | chanex.exe 4 | -------------------------------------------------------------------------------- /gorsynchs/chanex/chanex.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using channels for synchronization of go routines. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "time" // 9 | ) 10 | 11 | type gdata struct { 12 | id string 13 | loops, sltime int 14 | } 15 | 16 | var runData = []gdata{gdata{"1", 6, 2}, 17 | gdata{"2", 5, 1}, 18 | gdata{"3", 8, 3}, 19 | } 20 | 21 | var doneChan = make(chan bool) 22 | 23 | func called(cd gdata) { 24 | for i := 0; i < cd.loops; i++ { 25 | wnum := i + 1 26 | fmt.Printf("id %s, waitnum: %d\n", cd.id, wnum) 27 | time.Sleep(time.Duration(int64(cd.sltime) * 1e9)) 28 | } 29 | doneChan <- true 30 | fmt.Println(cd.id, "is done") 31 | } 32 | 33 | func main() { 34 | fmt.Println("Start...") 35 | // 36 | for _, curgd := range runData { 37 | go called(curgd) 38 | } 39 | // 40 | fmt.Println("Starting main wait") 41 | for i := 0; i < len(runData); i++ { 42 | <-doneChan 43 | } 44 | // 45 | fmt.Println("End...") 46 | } 47 | -------------------------------------------------------------------------------- /gorsynchs/mutexex/.gitignore: -------------------------------------------------------------------------------- 1 | mutexex 2 | 3 | mutexex.exe 4 | -------------------------------------------------------------------------------- /gorsynchs/mutexex/mutexex.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using a mutex for synchronization of go routines. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "sync" // 9 | "time" // 10 | ) 11 | 12 | type gdata struct { 13 | id string 14 | loops, sltime int 15 | } 16 | 17 | var runData = []gdata{gdata{"1", 6, 2}, 18 | gdata{"2", 5, 1}, 19 | gdata{"3", 8, 3}, 20 | } 21 | 22 | var processing, decrCtl sync.Mutex 23 | var numRtns int 24 | 25 | func called(cd gdata) { 26 | for i := 0; i < cd.loops; i++ { 27 | wnum := i + 1 28 | fmt.Printf("id %s, waitnum: %d\n", cd.id, wnum) 29 | time.Sleep(time.Duration(int64(cd.sltime) * 1e9)) 30 | } 31 | // 32 | decrCtl.Lock() 33 | numRtns-- 34 | if numRtns == 0 { 35 | processing.Unlock() 36 | } 37 | decrCtl.Unlock() 38 | // 39 | fmt.Println(cd.id, "is done") 40 | } 41 | 42 | func main() { 43 | fmt.Println("Start...") 44 | // 45 | numRtns = len(runData) 46 | processing.Lock() 47 | // 48 | for _, curgd := range runData { 49 | go called(curgd) 50 | } 51 | // 52 | fmt.Println("Starting main wait") 53 | processing.Lock() 54 | // 55 | fmt.Println("End...") 56 | } 57 | -------------------------------------------------------------------------------- /gorsynchs/wgroupex/.gitignore: -------------------------------------------------------------------------------- 1 | wgroupex 2 | 3 | wgroupex.exe 4 | -------------------------------------------------------------------------------- /gorsynchs/wgroupex/wgroupex.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using a wait group for go routine synchronization. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "sync" // 9 | "time" // 10 | ) 11 | 12 | var wg sync.WaitGroup 13 | 14 | type gdata struct { 15 | id string 16 | loops, sltime int 17 | } 18 | 19 | var runData = []gdata{gdata{"1", 6, 2}, 20 | gdata{"2", 5, 1}, 21 | gdata{"3", 8, 3}, 22 | } 23 | 24 | func called(cd gdata) { 25 | for i := 0; i < cd.loops; i++ { 26 | wnum := i + 1 27 | fmt.Printf("id %s, waitnum: %d\n", cd.id, wnum) 28 | time.Sleep(time.Duration(int64(cd.sltime) * 1e9)) 29 | } 30 | fmt.Println(cd.id, "is done") 31 | wg.Done() 32 | } 33 | 34 | func main() { 35 | fmt.Println("Start...") 36 | // 37 | for _, curgd := range runData { 38 | wg.Add(1) 39 | go called(curgd) 40 | } 41 | // 42 | fmt.Println("Starting main wait") 43 | wg.Wait() 44 | fmt.Println("End...") 45 | } 46 | -------------------------------------------------------------------------------- /gortns01/.gitignore: -------------------------------------------------------------------------------- 1 | gortns01 2 | gortns01.exe 3 | -------------------------------------------------------------------------------- /gortns01/gortns01.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using sleep, and example from gocourseday3.pdf. 3 | */ 4 | package main 5 | 6 | // 7 | import ( 8 | "fmt" 9 | "time" 10 | ) 11 | 12 | // 13 | // The simplest example from gocourseday3.pdf, modified to prevent a 14 | // premature end to the example. 15 | // 16 | func IsReady(what string, minutes int64) { 17 | time.Sleep(time.Duration(minutes * 60 * 1e9)) 18 | fmt.Println(what, "is ready") 19 | } 20 | 21 | func main() { 22 | fmt.Println("Starting .....") 23 | // 24 | go IsReady("tea", 6) 25 | go IsReady("coffee", 2) 26 | fmt.Println("I'm waiting....") 27 | 28 | // Crude synchronize with the go routines. 29 | time.Sleep(time.Duration(6.25 * 60 * 1e9)) 30 | 31 | // 32 | fmt.Println("Ending .....") 33 | } 34 | -------------------------------------------------------------------------------- /greddit/.gitignore: -------------------------------------------------------------------------------- 1 | greddit 2 | greddit.exe 3 | -------------------------------------------------------------------------------- /greddit/greddit.go: -------------------------------------------------------------------------------- 1 | /* 2 | Reddit pages in JSON format, from http://www.youtube.com/watch?v=2KmHtgtEZ1s sligtly embellished. 3 | */ 4 | package main 5 | 6 | import ( 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | "log" 11 | "net/http" 12 | ) 13 | 14 | type Item struct { 15 | Title string 16 | URL string 17 | Comments int `json:"num_comments"` 18 | Score int 19 | Downs int 20 | Ups int 21 | } 22 | 23 | type Response struct { 24 | Data struct { 25 | Children []struct { 26 | Data Item 27 | } 28 | } 29 | } 30 | 31 | func Get(reddit string) ([]Item, error) { 32 | url := fmt.Sprintf("http://reddit.com/r/%s.json", reddit) 33 | resp, err := http.Get(url) 34 | if err != nil { 35 | return nil, err 36 | } 37 | defer resp.Body.Close() 38 | if resp.StatusCode != http.StatusOK { 39 | return nil, errors.New(resp.Status) 40 | } 41 | r := new(Response) 42 | err = json.NewDecoder(resp.Body).Decode(r) 43 | if err != nil { 44 | return nil, err 45 | } 46 | items := make([]Item, len(r.Data.Children)) 47 | for i, child := range r.Data.Children { 48 | items[i] = child.Data 49 | } 50 | return items, nil 51 | } 52 | 53 | func (i Item) String() string { 54 | com := "" 55 | switch i.Comments { 56 | case 0: 57 | com = "(no comments)" 58 | case 1: 59 | com = "(1 comment)" 60 | default: 61 | com = fmt.Sprintf("(%d comments)", i.Comments) 62 | } 63 | return fmt.Sprintf("Title: %s\n%s\n%s\nScore=%d, Ups=%d, Downs=%d", 64 | i.Title, com, i.URL, i.Score, i.Ups, i.Downs) 65 | } 66 | 67 | func main() { 68 | items, err := Get("golang") 69 | if err != nil { 70 | log.Fatal(err) 71 | } 72 | // 73 | for _, item := range items { 74 | fmt.Println(item) 75 | fmt.Println() 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gt044/.gitignore: -------------------------------------------------------------------------------- 1 | gt044 2 | gt044.exe 3 | -------------------------------------------------------------------------------- /gt044/gt044.go: -------------------------------------------------------------------------------- 1 | /* 2 | Go tour, number 44. 3 | */ 4 | package main 5 | 6 | // go tour #44: http://tour.golang.org/#44 7 | 8 | import ( 9 | "fmt" 10 | "math" 11 | ) 12 | 13 | const ( 14 | d = 0.0000000001 // Quit looking when this close 15 | m = 100 // Max loops, to prevent infinite loop 16 | n = 20 // Maximim square root to caclulate 17 | ) 18 | 19 | func Sqrt(x float64) float64 { 20 | r := x // First guess 21 | var i int 22 | for i = 1; i <= m; i++ { 23 | l := r // Previous result 24 | r = r - (r*r-x)/(2*r) // New result 25 | // fmt.Println("l:", l, "r:", r) 26 | if (l - r) < d { // Within tolerance? 27 | break 28 | } 29 | } 30 | fmt.Println("Number of loops was:", i) 31 | return r 32 | } 33 | 34 | func main() { 35 | // Estimage square roots using Newton's method 36 | for i := 1; i <= n; i++ { 37 | f := float64(i) 38 | fmt.Println(i, Sqrt(f), math.Sqrt(f)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /gt045/.gitignore: -------------------------------------------------------------------------------- 1 | gt045 2 | gt045.exe 3 | -------------------------------------------------------------------------------- /gt045/gt045.go: -------------------------------------------------------------------------------- 1 | /* 2 | Go tour, number 45. 3 | */ 4 | package main 5 | 6 | // go tour #45: http://tour.golang.org/#45 7 | 8 | // You need to have the tour installed locally to compile this example. 9 | // 10 | // Install by e.g.: 11 | // 12 | // unset GOPATH # YMMV 13 | // go get code.google.com/p/go-tour/gotour 14 | // 15 | 16 | import ( 17 | "code.google.com/p/go-tour/wc" 18 | "strings" 19 | ) 20 | 21 | func WordCount(s string) map[string]int { 22 | m := make(map[string]int) 23 | for _, v := range strings.Fields(s) { 24 | m[v] += 1 25 | } 26 | return m 27 | } 28 | 29 | func main() { 30 | wc.Test(WordCount) 31 | } 32 | -------------------------------------------------------------------------------- /hello/.gitignore: -------------------------------------------------------------------------------- 1 | hello 2 | hello.exe 3 | -------------------------------------------------------------------------------- /hello/hello.go: -------------------------------------------------------------------------------- 1 | /* 2 | Hello world program, and pattern for project starts. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | func main() { 11 | fmt.Println("Start...") 12 | fmt.Println("End...") 13 | } 14 | -------------------------------------------------------------------------------- /hello_small/.gitignore: -------------------------------------------------------------------------------- 1 | hello_small 2 | hello_small.exe 3 | -------------------------------------------------------------------------------- /hello_small/hello_small.go: -------------------------------------------------------------------------------- 1 | /* 2 | Hello world, no imports. 3 | */ 4 | package main 5 | 6 | // 7 | // Produce a much smaller executable than when using "fmt". 8 | // 9 | func main() { 10 | println("Hello World") 11 | } 12 | -------------------------------------------------------------------------------- /httpserv/.gitignore: -------------------------------------------------------------------------------- 1 | httpserv 2 | httpserv.exe 3 | -------------------------------------------------------------------------------- /httpserv/httpserv.go: -------------------------------------------------------------------------------- 1 | /* 2 | A very simple HTTP server. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "net/http" 9 | ) 10 | 11 | // 12 | // Modified for weekly 2012-01-20 13 | // 14 | 15 | func HelloServer(rwtr http.ResponseWriter, req *http.Request) { 16 | fmt.Fprintf(rwtr, "Hello, World!!!!!!\n") 17 | // 18 | fmt.Fprintf(rwtr, "Method: |%s|\n", req.Method) 19 | fmt.Fprintf(rwtr, "Scheme: |%s|\n", req.URL.Scheme) 20 | fmt.Fprintf(rwtr, "Opaque: |%s|\n", req.URL.Opaque) 21 | fmt.Fprintf(rwtr, "User: |%v|\n", req.URL.User) 22 | fmt.Fprintf(rwtr, "Host: |%s|\n", req.URL.Host) 23 | fmt.Fprintf(rwtr, "Path: |%s|\n", req.URL.Path) 24 | fmt.Fprintf(rwtr, "Raw Query: |%s|\n", req.URL.RawQuery) 25 | fmt.Fprintf(rwtr, "Fragment: |%s|\n", req.URL.Fragment) 26 | 27 | // 28 | fmt.Fprintf(rwtr, "Later ....\n") 29 | } 30 | 31 | func main() { 32 | fmt.Println("Hello, World!!") 33 | http.Handle("/hello", http.HandlerFunc(HelloServer)) 34 | http.ListenAndServe(":54321", nil) 35 | } 36 | -------------------------------------------------------------------------------- /interface_01/.gitignore: -------------------------------------------------------------------------------- 1 | interface_01 2 | interface_01.exe 3 | -------------------------------------------------------------------------------- /interface_01/interface_01.go: -------------------------------------------------------------------------------- 1 | /* 2 | Interface example from the gocourse PDFs. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "math" 9 | ) 10 | 11 | type Point struct { 12 | x, y float32 13 | } 14 | 15 | // 16 | func (p *Point) Abs() float32 { 17 | x64 := float64(p.x) 18 | y64 := float64(p.y) 19 | r64 := math.Sqrt(x64*x64 + y64*y64) 20 | return float32(r64) 21 | } 22 | 23 | // Point implements this. 24 | // As does MyFloat. 25 | // float64 does not. 26 | 27 | type AbsInterface interface { 28 | Abs() float32 // receiver is implied 29 | } 30 | 31 | type MyFloat float32 32 | 33 | // This does *NOT* cpmpile .... 34 | // Even when 'float' was supported .... 35 | // 36 | // func (f MyFloat) Abs() float { 37 | // if f < 0.0 { return -f } 38 | // return f 39 | // } 40 | // 41 | 42 | // This does. 43 | func (f MyFloat) Abs() float32 { 44 | if f < 0.0 { 45 | return float32(-f) 46 | } 47 | return float32(f) 48 | } 49 | 50 | func main() { 51 | fmt.Println("Start .....") 52 | 53 | var ai AbsInterface 54 | 55 | pp := new(Point) 56 | fmt.Println(pp.Abs()) // method call 57 | 58 | ai = pp // OK: *Point has Abs() 59 | fmt.Println(ai.Abs()) // method call 60 | 61 | ai = MyFloat(-7.) // OK, MyFloat has Abs() 62 | fmt.Println(ai.Abs()) // method call 63 | 64 | ai = &Point{3, 4} 65 | fmt.Println(ai.Abs()) // method call 66 | 67 | fmt.Println("End .....") 68 | } 69 | -------------------------------------------------------------------------------- /interface_02/.gitignore: -------------------------------------------------------------------------------- 1 | interface_02 2 | interface_02.exe 3 | -------------------------------------------------------------------------------- /interface_02/interface_02.go: -------------------------------------------------------------------------------- 1 | /* 2 | Interface example from gocourseday2.pdf. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | type MyFloat float32 11 | 12 | // 13 | // The gocourseday2.pdf shows this function definition as: 14 | // func (f MyFloat) Abs() float { ... 15 | // which does not compile. 16 | // After some thinking, I guess this is what is (might be?) intended: 17 | // 18 | func (f MyFloat) Abs() MyFloat { 19 | if f < 0.0 { 20 | return -f 21 | } 22 | return f 23 | } 24 | 25 | // 26 | // And then the experiments with variable 'ftryb' below suggested this 27 | // approach/technique. Perhaps it is what is intended in the PDF. 28 | // 29 | func (f MyFloat) Abs2() float32 { 30 | if f < 0.0 { 31 | return float32(-f) 32 | } 33 | return float32(f) 34 | } 35 | 36 | // 37 | func main() { 38 | fmt.Println("Start .....") 39 | var mfa MyFloat 40 | fmt.Printf("%v\n", mfa) 41 | 42 | // OK, assign ... 43 | mfa = 1.234 44 | fmt.Printf("%v\n", mfa) 45 | 46 | // Change value and do the Abs() method 47 | mfa = -3.14159 48 | fmt.Printf("Neg: %v\n", mfa) 49 | fmt.Printf("Abs: %v\n", mfa.Abs()) 50 | 51 | // Sanity check 52 | var ftrya float32 53 | fmt.Printf("TryA: %v\n", ftrya) 54 | 55 | // Coerced conversion 56 | var ftryb float32 = 0.0 57 | ftryb = float32(mfa) 58 | fmt.Printf("TryB: %v\n", ftryb) 59 | 60 | // And use if alternate Abs2() method 61 | var mfb MyFloat = -4.567 62 | fmt.Printf("MFBa: %v\n", mfb) 63 | fmt.Printf("MFBaAbs2: %v\n", mfb.Abs2()) 64 | 65 | // And yeah, we can add MyFloat types ..... 66 | var mfc MyFloat 67 | mfc = mfa + mfb 68 | fmt.Printf("MFC: %v\n", mfc) 69 | 70 | // 71 | fmt.Println("End .....") 72 | } 73 | -------------------------------------------------------------------------------- /interface_03/.gitignore: -------------------------------------------------------------------------------- 1 | interface_03 2 | interface_03.exe 3 | -------------------------------------------------------------------------------- /interface_03/interface_03.go: -------------------------------------------------------------------------------- 1 | /* 2 | Interface example, using interface{}. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | ) 10 | 11 | type hmap map[string]string 12 | type hstr []string 13 | 14 | func pickem(iv interface{}) { 15 | switch iv.(type) { 16 | case hmap: 17 | fmt.Println("is hmap") 18 | case hstr: 19 | fmt.Println("is hstr") 20 | default: 21 | fmt.Println("NOT!") 22 | } 23 | } 24 | 25 | func dumpem(iv interface{}) { 26 | fmt.Println("raw", iv) 27 | fmt.Println("type:", reflect.TypeOf(iv)) 28 | v := reflect.ValueOf(iv) 29 | fmt.Println("value:", v) 30 | fmt.Println("kind:", v.Kind()) 31 | fmt.Println("interface:", v.Interface()) 32 | } 33 | 34 | func showdata(iv interface{}) { 35 | switch w := iv.(type) { 36 | case hmap: 37 | fmt.Println("showdata hmap") 38 | for k, v := range w { 39 | fmt.Println("key:", k, "value:", v) 40 | } 41 | case hstr: 42 | fmt.Println("showdata hstr") 43 | for i, v := range w { 44 | fmt.Println("index:", i, "value:", v) 45 | } 46 | default: 47 | fmt.Println("SHOWDATA NOT!") 48 | } 49 | 50 | } 51 | 52 | func main() { 53 | fmt.Println("Start .....") 54 | // 55 | h := hmap{"a": "va"} 56 | sa := hstr{"a", "b"} 57 | // 58 | fmt.Println("==========================") 59 | pickem(h) 60 | fmt.Println("--------------------------") 61 | dumpem(h) 62 | fmt.Println("..........................") 63 | showdata(h) 64 | fmt.Println("==========================") 65 | pickem(sa) 66 | fmt.Println("--------------------------") 67 | dumpem(sa) 68 | fmt.Println("..........................") 69 | showdata(sa) 70 | // 71 | fmt.Println("End .....") 72 | } 73 | -------------------------------------------------------------------------------- /interface_04/.gitignore: -------------------------------------------------------------------------------- 1 | interface_04 2 | interface_04.exe 3 | -------------------------------------------------------------------------------- /interface_04/interface_04.go: -------------------------------------------------------------------------------- 1 | /* 2 | A more realistic demonstration of interfaces. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | type Gap interface { 11 | // Get data 12 | Get() (s string, e error) 13 | // Put data 14 | Put(s string) (e error) 15 | } 16 | 17 | // Will implement Gap 18 | type ImpOne struct { 19 | ios string 20 | } 21 | 22 | // Implement Gap.Get 23 | func (o *ImpOne) Get() (s string, e error) { 24 | return o.ios, nil 25 | } 26 | 27 | // Implement Gap.Put 28 | func (o *ImpOne) Put(s string) (e error) { 29 | o.ios = s 30 | return nil 31 | } 32 | 33 | // Will also implement Gap 34 | type ImpTwo struct { 35 | its string 36 | } 37 | 38 | // Implement Gap.Get 39 | func (o *ImpTwo) Get() (s string, e error) { 40 | return o.its + o.its, nil 41 | } 42 | 43 | // Implement Gap.Put 44 | func (o *ImpTwo) Put(s string) (e error) { 45 | o.its = s + s 46 | return nil 47 | } 48 | 49 | func main() { 50 | fmt.Println("Start...") 51 | 52 | // ImpOne pointer 53 | dOne := &ImpOne{"abcd"} 54 | fmt.Println("dOne.ios:", dOne.ios) 55 | 56 | // ImpTwo pointer 57 | dTwo := &ImpTwo{"1234"} 58 | fmt.Println("dTwo.its:", dTwo.its) 59 | 60 | // ImpOne leaves data alone 61 | _ = dOne.Put("1time") 62 | w, _ := dOne.Get() 63 | fmt.Println("dOnePutGet", "1time", w) 64 | 65 | // ImpTwo munges the data 66 | _ = dTwo.Put("1time") 67 | w, _ = dTwo.Get() 68 | fmt.Println("dTwoPutGet", "1time", w) 69 | 70 | // An array of Gaps 71 | ga := [...]Gap{dOne, dTwo} 72 | 73 | // Use array offsets 74 | w, _ = ga[0].Get() 75 | fmt.Println("ga0Get", w) 76 | w, _ = ga[1].Get() 77 | fmt.Println("ga1Get", w) 78 | 79 | // Declare a Gap and use offset 0 80 | var g Gap = ga[0] 81 | w, _ = g.Get() 82 | fmt.Println("gga0Get", w) 83 | 84 | // Now use offset 1 85 | g = ga[1] 86 | w, _ = g.Get() 87 | fmt.Println("gga1Get", w) 88 | 89 | fmt.Println("End...") 90 | } 91 | -------------------------------------------------------------------------------- /interface_04a/.gitignore: -------------------------------------------------------------------------------- 1 | interface_04a 2 | interface_04a.exe 3 | -------------------------------------------------------------------------------- /interface_04a/interface_04a.go: -------------------------------------------------------------------------------- 1 | /* 2 | A more realistic demonstration of interfaces, with explicit (?) declaration. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | type Gap interface { 11 | // Get data 12 | Get() (s string, e error) 13 | // Put data 14 | Put(s string) (e error) 15 | } 16 | 17 | // Will implement Gap 18 | type ImpOne struct { 19 | Gap // Implement Gap 20 | ios string 21 | } 22 | 23 | // Implement Gap.Get 24 | func (o *ImpOne) Get() (s string, e error) { 25 | return o.ios, nil 26 | } 27 | 28 | // Implement Gap.Put 29 | func (o *ImpOne) Put(s string) (e error) { 30 | o.ios = s 31 | return nil 32 | } 33 | 34 | // Will also implement Gap 35 | type ImpTwo struct { 36 | Gap // Implement Gap 37 | its string 38 | } 39 | 40 | // Implement Gap.Get 41 | func (o *ImpTwo) Get() (s string, e error) { 42 | return o.its + o.its, nil 43 | } 44 | 45 | // Implement Gap.Put 46 | func (o *ImpTwo) Put(s string) (e error) { 47 | o.its = s + s 48 | return nil 49 | } 50 | 51 | func main() { 52 | fmt.Println("Start...") 53 | 54 | // ImpOne pointer 55 | dOne := &ImpOne{} // Parmater initialization not allowed like this 56 | fmt.Println("dOne.ios:", dOne.ios) 57 | 58 | // ImpTwo pointer 59 | dTwo := &ImpTwo{} // Parmater initialization not allowed like this 60 | fmt.Println("dTwo.its:", dTwo.its) 61 | 62 | // ImpOne leaves data alone 63 | _ = dOne.Put("1time") 64 | w, _ := dOne.Get() 65 | fmt.Println("dOnePutGet", "1time", w) 66 | 67 | // ImpTwo munges the data 68 | _ = dTwo.Put("1time") 69 | w, _ = dTwo.Get() 70 | fmt.Println("dTwoPutGet", "1time", w) 71 | 72 | // An array of Gaps 73 | ga := [...]Gap{dOne, dTwo} 74 | 75 | // Use array offsets 76 | w, _ = ga[0].Get() 77 | fmt.Println("ga0Get", w) 78 | w, _ = ga[1].Get() 79 | fmt.Println("ga1Get", w) 80 | 81 | // Declare a Gap and use offset 0 82 | var g Gap = ga[0] 83 | w, _ = g.Get() 84 | fmt.Println("gga0Get", w) 85 | 86 | // Now use offset 1 87 | g = ga[1] 88 | w, _ = g.Get() 89 | fmt.Println("gga1Get", w) 90 | 91 | fmt.Println("End...") 92 | } 93 | -------------------------------------------------------------------------------- /interface_04b/.gitignore: -------------------------------------------------------------------------------- 1 | interface_04b 2 | interface_04b.exe 3 | -------------------------------------------------------------------------------- /interface_04b/interface_04b.go: -------------------------------------------------------------------------------- 1 | /* 2 | A more realistic demonstration of interfaces, with explicit (?) declaration. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | type Gap interface { 11 | // Get data 12 | Get() (s string, e error) 13 | // Put data 14 | Put(s string) (e error) 15 | } 16 | 17 | // Will implement Gap 18 | type ImpOne struct { 19 | Gap // Implement Gap 20 | ios string 21 | } 22 | 23 | // Implement Gap.Get 24 | func (o *ImpOne) Get() (s string, e error) { 25 | return o.ios, nil 26 | } 27 | 28 | // Implement Gap.Put 29 | func (o *ImpOne) Put(s string) (e error) { 30 | o.ios = s 31 | return nil 32 | } 33 | 34 | // Will also implement Gap 35 | type ImpTwo struct { 36 | Gap // Implement Gap 37 | its string 38 | } 39 | 40 | // Implement Gap.Get 41 | func (o *ImpTwo) Get() (s string, e error) { 42 | return o.its + o.its, nil 43 | } 44 | 45 | // Implement Gap.Put 46 | func (o *ImpTwo) Put(s string) (e error) { 47 | o.its = s + s 48 | return nil 49 | } 50 | 51 | func main() { 52 | fmt.Println("Start...") 53 | 54 | // ImpOne pointer 55 | dOne := &ImpOne{} // Parmater initialization not allowed like this 56 | fmt.Println("dOne.ios:", dOne.ios) 57 | 58 | // ImpTwo pointer 59 | dTwo := &ImpTwo{} // Parmater initialization not allowed like this 60 | fmt.Println("dTwo.its:", dTwo.its) 61 | 62 | // ImpOne leaves data alone 63 | _ = dOne.Put("1time") 64 | w, _ := dOne.Get() 65 | fmt.Println("dOnePutGet", "1time", w) 66 | 67 | // ImpTwo munges the data 68 | _ = dTwo.Put("1time") 69 | w, _ = dTwo.Get() 70 | fmt.Println("dTwoPutGet", "1time", w) 71 | 72 | // An slice of Gaps 73 | ga := []Gap{dOne, dTwo} 74 | 75 | // Use array offsets 76 | w, _ = ga[0].Get() 77 | fmt.Println("ga0Get", w) 78 | w, _ = ga[1].Get() 79 | fmt.Println("ga1Get", w) 80 | 81 | // Declare a Gap and use offset 0 82 | var g Gap = ga[0] 83 | w, _ = g.Get() 84 | fmt.Println("gga0Get", w) 85 | 86 | // Now use offset 1 87 | g = ga[1] 88 | w, _ = g.Get() 89 | fmt.Println("gga1Get", w) 90 | 91 | fmt.Println("End...") 92 | } 93 | -------------------------------------------------------------------------------- /interface_05/.gitignore: -------------------------------------------------------------------------------- 1 | interface_05 2 | interface_05.exe 3 | -------------------------------------------------------------------------------- /interface_05/interface_05.go: -------------------------------------------------------------------------------- 1 | /* 2 | Show a more interesting use in interface{}. 3 | A function is passed two very different type of interfacesm and figures 4 | ut which to use. 5 | */ 6 | package main 7 | 8 | import ( 9 | "log" 10 | "net" 11 | "reflect" 12 | ) 13 | 14 | type Figer interface { 15 | Configure() 16 | } 17 | 18 | type Configuration struct { 19 | Figer 20 | NetConn net.Conn 21 | Ival int 22 | } 23 | 24 | func (c Configuration) Configure() { 25 | log.Println("Configure runs:", c.Ival) 26 | } 27 | 28 | var ( 29 | mc net.Conn 30 | cfg Configuration 31 | err error 32 | ) 33 | 34 | func Taker(as string, ai interface{}) { 35 | log.Println("====================================") 36 | log.Println("Taker runs", as) 37 | log.Println("ai is a:", reflect.TypeOf(ai)) 38 | isnc, iscfg := false, false 39 | switch mytype := ai.(type) { 40 | case net.Conn: 41 | log.Println("found net.Conn", reflect.TypeOf(mytype)) 42 | isnc = true 43 | case Configuration: 44 | log.Println("found Configuration", reflect.TypeOf(mytype)) 45 | iscfg = true 46 | default: 47 | panic(reflect.TypeOf(ai)) 48 | } 49 | log.Println(isnc, iscfg) 50 | log.Println("====================================") 51 | if isnc { 52 | tc := ai.(*net.TCPConn) 53 | log.Println(tc.RemoteAddr()) 54 | } else { 55 | cfg := ai.(Configuration) 56 | cfg.Configure() 57 | } 58 | } 59 | 60 | func main() { 61 | log.Println("start") 62 | cfg = Configuration{Ival: 42} 63 | cfg.Configure() 64 | // 65 | mc, err = net.Dial("tcp", "localhost:5900") 66 | if err != nil { 67 | panic(err) 68 | } 69 | Taker("net.Conn", mc) 70 | Taker("Configuration", cfg) 71 | log.Println("end") 72 | } 73 | -------------------------------------------------------------------------------- /list/.gitignore: -------------------------------------------------------------------------------- 1 | list 2 | list.exe 3 | -------------------------------------------------------------------------------- /list/list.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate using the List container. 3 | */ 4 | package main 5 | 6 | import ( 7 | "container/list" // 8 | "fmt" // 9 | ) 10 | 11 | func lexamp01() { 12 | var myl = list.New() 13 | if myl == nil { 14 | fmt.Println("is nil") 15 | } 16 | fmt.Printf("Len: %v\n", myl.Len()) 17 | fmt.Printf("myl: %v\n", myl) 18 | var elts = []string{"elt1", "elt2", "elt3"} 19 | for _, nelt := range elts { 20 | myl.PushBack(nelt) 21 | } 22 | fmt.Printf("myl: %v\n", myl) 23 | // 24 | for nelt := myl.Front(); nelt != nil; nelt = nelt.Next() { 25 | fmt.Printf("Next: %v\n", nelt.Value) 26 | } 27 | } 28 | 29 | func main() { 30 | fmt.Println("Start...") 31 | lexamp01() 32 | fmt.Println("End...") 33 | } 34 | -------------------------------------------------------------------------------- /list_struct/.gitignore: -------------------------------------------------------------------------------- 1 | list_struct 2 | list_struct.exe 3 | -------------------------------------------------------------------------------- /list_struct/list_struct.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate using the List container, embellished. 3 | */ 4 | package main 5 | 6 | import ( 7 | "container/list" // 8 | "fmt" // 9 | ) 10 | 11 | type Pair struct { 12 | key string 13 | value string 14 | } 15 | 16 | func generate(key, value string) Pair { 17 | var pair Pair 18 | pair.key = key 19 | pair.value = value 20 | return pair 21 | } 22 | 23 | func lexamp01() { 24 | var myl = list.New() 25 | fmt.Printf("myl: %v\n", myl) 26 | // 27 | var pa Pair = generate("key1", "value1") 28 | fmt.Printf("Key: %s, Value: %s\n", pa.key, pa.value) 29 | myl.PushBack(pa) 30 | // 31 | pa = generate("key2", "value2") 32 | myl.PushBack(pa) 33 | // 34 | pa = generate("key3", "value3") 35 | myl.PushBack(pa) 36 | // 37 | fmt.Printf("myl: %v\n", myl) 38 | // 39 | fmt.Println("==================================") 40 | for nelt := myl.Front(); nelt != nil; nelt = nelt.Next() { 41 | fmt.Printf("Next: %v\n", nelt) 42 | if np, ok := nelt.Value.(Pair); ok { 43 | fmt.Println("ok", np) 44 | fmt.Printf("Next Key: %s, Next Value: %s\n", np.key, np.value) 45 | } 46 | } 47 | // 48 | fmt.Println("==================================") 49 | for nelt := myl.Front(); nelt != nil; nelt = nelt.Next() { 50 | fmt.Printf("Next: %v\n", nelt) 51 | np, _ := nelt.Value.(Pair) 52 | fmt.Printf("Next Key: %s, Next Value: %s\n", np.key, np.value) 53 | } 54 | } 55 | 56 | func main() { 57 | fmt.Println("Start...") 58 | lexamp01() 59 | fmt.Println("End...") 60 | } 61 | -------------------------------------------------------------------------------- /loghello/.gitignore: -------------------------------------------------------------------------------- 1 | loghello 2 | loghello.exe 3 | -------------------------------------------------------------------------------- /loghello/loghello.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using the log package. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // formatter 8 | "log" // 9 | "os" // 10 | ) 11 | 12 | func main() { 13 | fmt.Println("Start...") 14 | // var logger = log.New(os.Stdout, nil, 1) // NOT OK 15 | // var logger = log.New(os.Stdout, "LPR ", 1) // OK 16 | // var logger = log.New(os.Stdout, "LPR ", log.Ldate|log.Ltime|log.Lshortfile) // OK 17 | var logger1 = log.New(os.Stdout, "LPR1 ", log.Ldate|log.Lmicroseconds|log.Lshortfile) // OK 18 | var logger2 = log.New(os.Stdout, "LPR2 ", log.Ldate|log.Lmicroseconds|log.Lshortfile) // OK 19 | 20 | logger1.Println("logline L1a") 21 | logger2.Println("logline L2a") 22 | logger1.Println("logline L1b") 23 | logger2.Println("logline L2b") 24 | 25 | fmt.Println("End...") 26 | } 27 | -------------------------------------------------------------------------------- /mapcaph/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | mapcaph 3 | mapcaph.exe 4 | 5 | -------------------------------------------------------------------------------- /mapcaph/mapcaph.go: -------------------------------------------------------------------------------- 1 | /* 2 | Map capacity hint demo. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | mm := make(map[string]int, 2) // 2 is a "capacity hint", not a hard bound 10 | /* From the language spec: 11 | The initial capacity does not bound its size: maps grow to accommodate the 12 | number of items stored in them, with the exception of nil maps. A nil map 13 | is equivalent to an empty map except that no elements may be added. 14 | */ 15 | 16 | // Also note that maps do not support the 'cap' builtin. Saying: 17 | // cap(mm) 18 | // is an compile error, with a message like: 19 | // invalid argument mm (type map[string]int) for cap 20 | 21 | mm["a"] = 1 22 | fmt.Println(mm["a"], len(mm)) 23 | mm["b"] = 2 24 | fmt.Println(mm["b"], len(mm)) 25 | mm["c"] = 3 26 | fmt.Println(mm["c"], len(mm)) 27 | mm["d"] = 4 28 | fmt.Println(mm["d"], len(mm)) 29 | } 30 | -------------------------------------------------------------------------------- /mapmapstr/.gitignore: -------------------------------------------------------------------------------- 1 | mapmapstr 2 | mapmapstr.exe 3 | -------------------------------------------------------------------------------- /mapmapstr/mapmapstr.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate a map[string]map[string]string: 3 | a map of a string to map of a string to a string. 4 | */ 5 | 6 | package main 7 | 8 | import "fmt" 9 | 10 | func main() { 11 | type mss map[string]string 12 | mosa := mss{"asa": "astra", "asb": "astrb"} 13 | fmt.Println("mosa", mosa) 14 | mosb := mss{"bsa": "bstra", "bsb": "bstrb"} 15 | fmt.Println("mosb", mosb) 16 | // 17 | type msmss map[string]mss 18 | mossab := msmss{"mosa": mosa, "mosb": mosb} 19 | fmt.Println("mossab", mossab) 20 | // 21 | fmt.Println("------- mosa ----------") 22 | for k, v := range mosa { 23 | fmt.Printf("key=%s, value=%s\n", k, v) 24 | } 25 | fmt.Println("------- mosb ----------") 26 | for k, v := range mosb { 27 | fmt.Printf("key=%s, value=%s\n", k, v) 28 | } 29 | fmt.Println("------ mossab ---------") 30 | for ok, ov := range mossab { 31 | for ik, iv := range ov { 32 | fmt.Printf("ok=%s, ik=%s, iv=%s\n", ok, ik, iv) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mapptrs/.gitignore: -------------------------------------------------------------------------------- 1 | mapptrs 2 | mapptrs.exe 3 | -------------------------------------------------------------------------------- /mapptrs/mapptrs.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using maps of pointers. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | // 10 | type ts struct { 11 | tval int 12 | } 13 | // 14 | sp1 := new(ts) 15 | sp1.tval = 12345 16 | sp2 := new(ts) 17 | sp2.tval = 34567 18 | // 19 | fmt.Printf("sp1: [%v]\n", sp1) 20 | fmt.Printf("sp1: [%v]\n", sp2) 21 | // 22 | ms := make(map[string]*ts) 23 | ms["sp1"] = sp1 24 | ms["sp2"] = sp2 25 | // 26 | fmt.Printf("ms: [%v]\n", ms) 27 | // 28 | if v, ok := ms["sp1"]; ok { 29 | fmt.Println("sp1 check ok", v, v.tval) 30 | } else { 31 | fmt.Println("sp1 check fail") 32 | } 33 | // 34 | if v, ok := ms["sp2"]; ok { 35 | fmt.Println("sp2 check ok", v, v.tval) 36 | } else { 37 | fmt.Println("sp2 check fail") 38 | } 39 | // 40 | if v, ok := ms["sp3"]; ok { 41 | fmt.Println("sp3 check", v) 42 | } else { 43 | fmt.Println("sp3 check fail") 44 | } 45 | // 46 | fmt.Println() 47 | } 48 | 49 | -------------------------------------------------------------------------------- /maps/.gitignore: -------------------------------------------------------------------------------- 1 | maps 2 | maps.exe 3 | -------------------------------------------------------------------------------- /maps/maps.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using maps, from the gocourse PDFs. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | // 10 | var value float32 11 | var present bool 12 | // 13 | // Create a map using a literal. Access a particular vlaue using the key. 14 | // 15 | var m = map[string]float32{"1": 1, "pi": 3.1415} 16 | fmt.Printf("%g\n", m["pi"]) 17 | // 18 | // Add a key and value. 19 | // 20 | m["2"] = 2 21 | fmt.Printf("%g\n", m["2"]) 22 | // 23 | // Change a value! 24 | // 25 | m["2"] = 3 26 | fmt.Printf("%g\n", m["2"]) 27 | // 28 | // Determine if a key is present in the map. 29 | // 30 | value, present = m["1"] // value is there 31 | fmt.Printf("%g\t%t\n", value, present) // present=true 32 | value, present = m["6"] // value is not there 33 | fmt.Printf("%g\t%t\n", value, present) // present=false 34 | // 35 | // Show how not using the ", OK" format works. 36 | // 37 | fmt.Println() 38 | crash := m["nothere"] // Examples said crash. Different I suppose. 39 | fmt.Printf("%g\n", crash) // Gives zero value for type 40 | // 41 | // Loop over all map members/elements. 42 | // 43 | fmt.Println() 44 | for key, value := range m { 45 | fmt.Printf("%s\t%g\n", key, value) 46 | } 47 | fmt.Println() 48 | // 49 | // Loop over just the keys. 50 | // 51 | fmt.Println() 52 | for key := range m { 53 | fmt.Printf("%s\n", key) 54 | } 55 | fmt.Println() 56 | // 57 | // Delete a element/member. 58 | // 59 | value, present = m["2"] // value is there 60 | fmt.Printf("%g\t%t\n", value, present) // present=true 61 | delete(m, "2") // Delete, use the zero value for the values, and false 62 | value, present = m["2"] // value is not there 63 | fmt.Printf("%g\t%t\n", value, present) // present=false 64 | fmt.Println() 65 | } 66 | -------------------------------------------------------------------------------- /maps_merge/.gitignore: -------------------------------------------------------------------------------- 1 | maps_merge 2 | maps_merge.exe 3 | -------------------------------------------------------------------------------- /maps_merge/maps_merge.go: -------------------------------------------------------------------------------- 1 | /* 2 | Merging two maps, with optional overwrite. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | type Mymss map[string]string 9 | 10 | func mapMerge(ma Mymss, mb Mymss, overlay bool) { 11 | var present bool 12 | for bk, bv := range mb { 13 | if overlay { 14 | ma[bk] = bv 15 | } else { 16 | _, present = ma[bk] 17 | if !present { 18 | ma[bk] = bv 19 | } 20 | } 21 | } 22 | return 23 | } 24 | 25 | func main() { 26 | fmt.Println("Start...") 27 | // 28 | var mss1 = Mymss{"a": "av", "b": "bv", "c": "cv"} 29 | fmt.Println("mss1:") 30 | for k, v := range mss1 { 31 | fmt.Printf("Key: %s, Value: %s\n", k, v) 32 | } 33 | // 34 | var mss2 = Mymss{"d": "dv", "e": "ev"} 35 | fmt.Println("mss2:") 36 | for k, v := range mss2 { 37 | fmt.Printf("Key: %s, Value: %s\n", k, v) 38 | } 39 | // 40 | mapMerge(mss1, mss2, false) 41 | fmt.Println("merged1:") 42 | for k, v := range mss1 { 43 | fmt.Printf("Key: %s, Value: %s\n", k, v) 44 | } 45 | 46 | // 47 | var mss3 = Mymss{"c": "cnew", "d": "dv", "e": "ev"} 48 | fmt.Println("mss3:") 49 | for k, v := range mss3 { 50 | fmt.Printf("Key: %s, Value: %s\n", k, v) 51 | } 52 | // 53 | mss1 = Mymss{"a": "av", "b": "bv", "c": "cv"} // Reset 54 | mapMerge(mss1, mss3, false) 55 | fmt.Println("merged2:") 56 | for k, v := range mss1 { 57 | fmt.Printf("Key: %s, Value: %s\n", k, v) 58 | } 59 | // 60 | mss1 = Mymss{"a": "av", "b": "bv", "c": "cv"} // Reset 61 | mapMerge(mss1, mss3, true) 62 | fmt.Println("merged3:") 63 | for k, v := range mss1 { 64 | fmt.Printf("Key: %s, Value: %s\n", k, v) 65 | } 66 | // 67 | fmt.Println("End...") 68 | } 69 | -------------------------------------------------------------------------------- /maps_ss/.gitignore: -------------------------------------------------------------------------------- 1 | maps_ss 2 | maps_ss.exe 3 | -------------------------------------------------------------------------------- /maps_ss/maps_ss.go: -------------------------------------------------------------------------------- 1 | /* 2 | Simple play with map[string]string. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | type Mymss map[string]string 9 | 10 | func main() { 11 | // 12 | fmt.Println("Start...") 13 | var mss1 = map[string]string{"a": "av", "b": "bv"} 14 | for k, v := range mss1 { 15 | fmt.Printf("Key: %s, Value: %s\n", k, v) 16 | } 17 | // 18 | var mss2 = Mymss{"a2": "av2", "b2": "bv2"} 19 | for k, v := range mss2 { 20 | fmt.Printf("Key: %s, Value: %s\n", k, v) 21 | } 22 | // 23 | mss3 := Mymss{"a3": "av3", "b3": "bv3"} 24 | for k, v := range mss3 { 25 | fmt.Printf("Key: %s, Value: %s\n", k, v) 26 | } 27 | fmt.Println("End...") 28 | } 29 | -------------------------------------------------------------------------------- /methods/.gitignore: -------------------------------------------------------------------------------- 1 | methods 2 | methods.exe 3 | -------------------------------------------------------------------------------- /netcon/.gitignore: -------------------------------------------------------------------------------- 1 | netcon 2 | netcon.exe 3 | -------------------------------------------------------------------------------- /netcon/netcon.go: -------------------------------------------------------------------------------- 1 | /* 2 | Use a net.Conn connection, which is an interface. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "net" // 9 | "os" // 10 | "time" // 11 | ) 12 | 13 | func main() { 14 | fmt.Println("Start...") 15 | conn, err := net.Dial("tcp", "localhost:54321") 16 | // 17 | if err != nil { 18 | fmt.Printf("Dial Error received: %v\n", err) 19 | os.Exit(4) 20 | } 21 | // 22 | time.Sleep(5 * time.Second) // 5 seconds 23 | // 24 | err = conn.Close() 25 | if err != nil { 26 | fmt.Printf("Close Error received: %v\n", err) 27 | os.Exit(4) 28 | } 29 | // 30 | fmt.Println("End...") 31 | } 32 | -------------------------------------------------------------------------------- /numbers/.gitignore: -------------------------------------------------------------------------------- 1 | numbers 2 | -------------------------------------------------------------------------------- /numbers/README.txt: -------------------------------------------------------------------------------- 1 | # 2 | # = Sample Package Install 3 | # 4 | # This package shows how to install a local package which will be available 5 | # to all go programs via 'import'. 6 | # 7 | # == Testing 8 | # 9 | # To test this package enter the command: 10 | # 11 | # * go test 12 | # 13 | # == Installation 14 | # 15 | # To install this package to your local go package directory enter the 16 | # command: 17 | # 18 | # * go install 19 | # 20 | # == Notes 21 | # 22 | # This example shows a number of subtle aspects of the go language. 23 | # 24 | # See comments in the code for more information. 25 | # 26 | 27 | -------------------------------------------------------------------------------- /numbers/numbers.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate implementing a package. 3 | */ 4 | package numbers 5 | // 6 | // Note function with name that is capitalized. It _is_ exported. 7 | // 8 | func Double(i int) int { 9 | // 10 | // Not much to do here. Just multiply by 2. 11 | // 12 | return i * 2 13 | } 14 | -------------------------------------------------------------------------------- /numbers/numbers_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | package numbers 4 | // 5 | // Could import multiple packages here. And also 'rename' the package for local 6 | // use. 7 | // 8 | import ( 9 | "testing" 10 | ) 11 | // 12 | // Declcare a type. It is a struct. 13 | // 14 | type doubleTest struct { 15 | in, out int 16 | } 17 | // 18 | // A literal declaration. An array of types. 19 | // 20 | var doubleTests = []doubleTest{ 21 | doubleTest{1, 2}, 22 | doubleTest{2, 4}, 23 | doubleTest{-5, -10}, 24 | } 25 | // 26 | // A basic test function. Make sure multiply works. 27 | // Note: exported. 28 | // 29 | func TestDouble(t *testing.T) { 30 | for _, dt := range doubleTests { 31 | v := Double(dt.in) 32 | if v != dt.out { 33 | t.Errorf("Double(%d) = %d, want %d.", dt.in, v, dt.out) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /numconv/.gitignore: -------------------------------------------------------------------------------- 1 | numconv 2 | numconv.exe 3 | -------------------------------------------------------------------------------- /numconv/numconv.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate type coercion with numbers. 3 | */ 4 | package main 5 | 6 | // Demo basic coercion of numbers from one type to another 7 | 8 | import ( 9 | "fmt" 10 | "math" 11 | ) 12 | 13 | func main() { 14 | fmt.Println("Start .....") 15 | // 16 | var f64 float64 = 1.23456 17 | fmt.Printf("f64: %g\n", f64) 18 | // 19 | var f32 float32 = 3.45678 20 | fmt.Printf("f32: %g\n", f32) 21 | // 22 | var f float32 = 5.6789 23 | fmt.Printf("f: %g\n", f) 24 | // 25 | f64 = float64(f32) 26 | fmt.Printf("f64: %g\n", f64) 27 | // 28 | f32 = float32(f) 29 | fmt.Printf("f32: %g\n", f32) 30 | // 31 | f64 = float64(f32) 32 | fmt.Printf("f64: %g\n", f64) 33 | // 34 | f64 = math.Pi 35 | fmt.Printf("f64: %g\n", f64) 36 | f32 = float32(f64) 37 | fmt.Printf("f32: %g\n", f32) 38 | // 39 | fmt.Println("End .....") 40 | } 41 | -------------------------------------------------------------------------------- /oltesta/.gitignore: -------------------------------------------------------------------------------- 1 | oltesta 2 | oltesta.exe 3 | -------------------------------------------------------------------------------- /oltesta/oltesta.go: -------------------------------------------------------------------------------- 1 | /* 2 | Originally meant to be a test of overloading, which of course is not implemented. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | /* 9 | From examples. Interesting notes: 10 | 11 | a) Function overloads are unsupported :-(. 12 | b) Arrays are values 13 | c) Can take address of an Array 14 | 15 | */ 16 | func f(a [3]int) { fmt.Println(a) } 17 | 18 | // func f(a *[3]int) { fmt.Println(a) } // fails to compile 19 | func fp(a *[3]int) { fmt.Println(a) } 20 | 21 | /* 22 | */ 23 | func main() { 24 | fmt.Printf("Basic overload tester ....\n") 25 | var ar [3]int 26 | f(ar) 27 | // passes a copy of ar 28 | fp(&ar) // passes a pointer to ar 29 | } 30 | -------------------------------------------------------------------------------- /panrecov/.gitignore: -------------------------------------------------------------------------------- 1 | panrecov 2 | panrecov.exe 3 | -------------------------------------------------------------------------------- /panrecov/panrecov.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "runtime" 7 | ) 8 | 9 | // A blatant copy from and thanks to: 10 | // http://www.goinggo.net/2013/06/understanding-defer-panic-and-recover.html 11 | 12 | func main() { 13 | var err error 14 | 15 | err = TestFinal() 16 | 17 | if err != nil { 18 | fmt.Printf("Main Error: %v\n", err) 19 | } 20 | } 21 | 22 | func _CatchPanic(err *error, functionName string) { 23 | if r := recover(); r != nil { 24 | fmt.Printf("%s : PANIC Defered : %v\n", functionName, r) 25 | 26 | // Capture the stack trace 27 | buf := make([]byte, 10000) 28 | runtime.Stack(buf, false) 29 | 30 | fmt.Printf("%s : Stack Trace : %s", functionName, string(buf)) 31 | 32 | if err != nil { 33 | 34 | *err = errors.New(fmt.Sprintf("%v", r)) 35 | } 36 | } else if err != nil && *err != nil { 37 | 38 | fmt.Printf("%s : ERROR : %v\n", functionName, *err) 39 | 40 | // Capture the stack trace 41 | buf := make([]byte, 10000) 42 | runtime.Stack(buf, false) 43 | 44 | fmt.Printf("%s : Stack Trace : %s", functionName, string(buf)) 45 | } 46 | } 47 | 48 | func MimicError(key string) error { 49 | return errors.New(fmt.Sprintf("Mimic Error : %s", key)) 50 | } 51 | 52 | func TestFinal() (err error) { 53 | defer _CatchPanic(&err, "TestFinal") 54 | 55 | fmt.Printf("Start Test\n") 56 | 57 | err = MimicError("1") 58 | 59 | panic("Mimic Panic") 60 | 61 | fmt.Printf("End Test\n") 62 | 63 | return err 64 | } 65 | -------------------------------------------------------------------------------- /pgmdir/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | pgmdir 3 | pgmdir.exe 4 | 5 | -------------------------------------------------------------------------------- /pgmdir/pgmdir.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | Show executable file name and directory. 5 | */ 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | "path/filepath" 11 | ) 12 | 13 | func main() { 14 | pgm, e := os.Executable() 15 | if e != nil { 16 | log.Fatalln("Error:", e) 17 | } 18 | fmt.Printf("Executable Name:\n[%s]\n", pgm) 19 | // 20 | dir := filepath.Dir(pgm) 21 | fmt.Printf("Executable Directory:\n[%s]\n", dir) 22 | } 23 | -------------------------------------------------------------------------------- /rand_between/.gitignore: -------------------------------------------------------------------------------- 1 | rand_between 2 | rand_between.exe 3 | -------------------------------------------------------------------------------- /rand_between/rand_between.go: -------------------------------------------------------------------------------- 1 | /* 2 | Generate a random int64 number between min and max bounds. 3 | */ 4 | package main 5 | 6 | import ( 7 | "crypto/rand" 8 | "fmt" // 9 | "math/big" // 10 | ) 11 | 12 | var max int64 = 1e9 13 | var min int64 = 10 * max / 100 14 | 15 | // 16 | 17 | func randBetween(min, max int64) int64 { 18 | br, _ := rand.Int(rand.Reader, big.NewInt(max-min)) // Ignore errors here 19 | return br.Add(big.NewInt(min), br).Int64() 20 | } 21 | 22 | func randBetween2(min, max int64) int64 { 23 | rt, _ := rand.Int(rand.Reader, big.NewInt(max-min)) // Ignore errors here 24 | return min + rt.Int64() 25 | } 26 | 27 | func randBetween3(min, max int64, fact float64) int64 { 28 | rt, _ := rand.Int(rand.Reader, big.NewInt(max-min)) // Ignore errors here 29 | return int64(fact * float64(min+rt.Int64())) 30 | } 31 | 32 | func main() { 33 | fmt.Printf("MIN: %d\n", min) 34 | fmt.Printf("MAX: %d\n", max) 35 | // 36 | fmt.Println("StartT1...") 37 | for i := 1; i <= 100; i++ { 38 | fmt.Printf("Iteration %d\n", i) 39 | r := randBetween(min, max) 40 | fmt.Printf("Result: %d\n", r) 41 | if r < min || r > max { 42 | fmt.Printf("Error, unexpected results: %v, %v, %v\n", min, max, r) 43 | panic("unexpected results") 44 | } 45 | } 46 | fmt.Println("EndT1...") 47 | // 48 | fmt.Println("StartT2...") 49 | for i := 1; i <= 100; i++ { 50 | fmt.Printf("Iteration %d\n", i) 51 | r := randBetween2(min, max) 52 | fmt.Printf("Result: %d\n", r) 53 | if r < min || r > max { 54 | fmt.Printf("Error, unexpected results: %v, %v, %v\n", min, max, r) 55 | panic("unexpected results") 56 | } 57 | } 58 | fmt.Println("EndT2...") 59 | // 60 | fmt.Println("StartT3...") 61 | for i := 1; i <= 100; i++ { 62 | fmt.Printf("Iteration %d\n", i) 63 | r := randBetween3(min, max, 1.0) 64 | fmt.Printf("Result: %d\n", r) 65 | if r < min || r > max { 66 | fmt.Printf("Error, unexpected results: %v, %v, %v\n", min, max, r) 67 | panic("unexpected results") 68 | } 69 | } 70 | fmt.Println("EndT3...") 71 | } 72 | -------------------------------------------------------------------------------- /rand_between/rb_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func BenchmarkBetween(b *testing.B) { 6 | for n := 0; n < b.N; n++ { 7 | _ = randBetween(min, max) 8 | } 9 | } 10 | 11 | func BenchmarkBetween2(b *testing.B) { 12 | for n := 0; n < b.N; n++ { 13 | _ = randBetween2(min, max) 14 | } 15 | } 16 | 17 | func BenchmarkBetween3(b *testing.B) { 18 | for n := 0; n < b.N; n++ { 19 | _ = randBetween3(min, max, 1.0) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rangecopy/.gitignore: -------------------------------------------------------------------------------- 1 | rangecopy 2 | rangecopy.exe 3 | -------------------------------------------------------------------------------- /rangecopy/rangecopy.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate that range makes copies. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | type Foo struct { 11 | a int 12 | } 13 | 14 | // 15 | // Based on discussion: 16 | // https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/e08r1Vk7ufQ 17 | // 18 | func main() { 19 | 20 | // A range of primitives 21 | someInts := []int{1, 2} 22 | fmt.Println("somei1", someInts[0], someInts[1]) 23 | 24 | for _, si := range someInts { 25 | si = si + 1 26 | } 27 | fmt.Println("somei2", someInts[0], someInts[1]) // Not modified 28 | 29 | for _, si := range someInts { 30 | z := &si 31 | *z = *z + 1 32 | } 33 | fmt.Println("somei3", someInts[0], someInts[1]) // Not modified 34 | 35 | for i := range someInts { // A slight surprize 36 | someInts[i] = someInts[i] + 1 37 | } 38 | fmt.Println("somei3B", someInts[0], someInts[1]) // Modified 39 | 40 | for i := 0; i < len(someInts); i++ { 41 | someInts[i] = someInts[i] + 1 42 | } 43 | fmt.Println("somei4", someInts[0], someInts[1]) // Modified 44 | 45 | for i := 0; i < len(someInts); i++ { 46 | z := &someInts[i] 47 | *z = *z + 1 48 | } 49 | fmt.Println("somei5", someInts[0], someInts[1]) // Modified again 50 | 51 | afoo := Foo{1} 52 | fmt.Println("afooa", afoo.a) 53 | 54 | // A range of structs 55 | someFoos := []Foo{Foo{2}, Foo{3}} 56 | fmt.Println("somex1", someFoos[0].a, someFoos[1].a) 57 | 58 | for _, sf := range someFoos { 59 | sf.a = sf.a + 1 60 | } 61 | fmt.Println("somex2", someFoos[0].a, someFoos[1].a) // Not modified 62 | 63 | for _, sf := range someFoos { 64 | z := &sf 65 | z.a = z.a + 1 66 | } 67 | fmt.Println("somex3", someFoos[0].a, someFoos[1].a) // Not modified 68 | 69 | for i := range someFoos { 70 | someFoos[i].a = someFoos[i].a + 1 71 | } 72 | fmt.Println("somex3B", someFoos[0].a, someFoos[1].a) // Modified 73 | 74 | for i := 0; i < len(someFoos); i++ { 75 | someFoos[i].a = someFoos[i].a + 1 76 | } 77 | fmt.Println("somex4", someFoos[0].a, someFoos[1].a) // Modified 78 | 79 | for i := 0; i < len(someFoos); i++ { 80 | z := &someFoos[i] 81 | z.a = z.a + 1 82 | } 83 | fmt.Println("somex5", someFoos[0].a, someFoos[1].a) // Modified again 84 | 85 | } 86 | -------------------------------------------------------------------------------- /ranges/.gitignore: -------------------------------------------------------------------------------- 1 | ranges 2 | ranges.exe 3 | -------------------------------------------------------------------------------- /ranges/ranges.go: -------------------------------------------------------------------------------- 1 | /* 2 | Using range with maps and strings. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | fmt.Println("Start....") 10 | // 11 | m := map[string]float32{"1": 1.0, "pi": 3.1415} 12 | // Key, Value 13 | for key, value := range m { 14 | fmt.Printf("key %s, value %g\n", key, value) 15 | } 16 | // Key only 17 | for key := range m { 18 | fmt.Printf("key %s\n", key) 19 | } 20 | // Characters. 21 | s := "[\u00ff\u754c]" 22 | for i, c := range s { 23 | fmt.Printf("%d:%c ", i, c) 24 | } 25 | // 26 | t := "\u754c" 27 | fmt.Printf("\nLen: %d\n", len(t)) 28 | fmt.Println("End....") 29 | } 30 | -------------------------------------------------------------------------------- /recover/.gitignore: -------------------------------------------------------------------------------- 1 | recover 2 | recover.exe 3 | -------------------------------------------------------------------------------- /recover/recover.go: -------------------------------------------------------------------------------- 1 | /* 2 | An example of using recover, from http://play.golang.org/p/m96skGjRjo 3 | */ 4 | package main 5 | 6 | import ( 7 | "log" 8 | "runtime/debug" 9 | ) 10 | 11 | func deep2(n int) { 12 | defer func() { 13 | log.Printf("Resource %d closed", n) 14 | if err := recover(); err != nil { 15 | panic(err) 16 | } 17 | }() 18 | 19 | panic("I'm afraid I can't do that") 20 | } 21 | 22 | func deep1(n int) { 23 | defer func() { 24 | log.Printf("Resource %d closed", n) 25 | if err := recover(); err != nil { 26 | panic(err) 27 | } 28 | }() 29 | deep2(n + 1) 30 | } 31 | 32 | func main() { 33 | defer func() { 34 | log.Print("Main exiting") 35 | if err := recover(); err != nil { 36 | log.Fatalf("Stack trace:\n%s----\n%s", debug.Stack(), err) 37 | } 38 | }() 39 | 40 | log.Println("Main started") 41 | deep1(1) 42 | } 43 | 44 | -------------------------------------------------------------------------------- /reflmem/.gitignore: -------------------------------------------------------------------------------- 1 | reflmem 2 | reflmem.exe 3 | -------------------------------------------------------------------------------- /reflmem/reflmem.go: -------------------------------------------------------------------------------- 1 | /* 2 | Reflection and memory layout. 3 | Ref: 4 | https://syslog.ravelin.com/go-and-memory-layout-6ef30c730d51 5 | */ 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "reflect" 11 | "unsafe" 12 | ) 13 | 14 | type MyData struct { 15 | aByte byte 16 | anotherByte byte 17 | aShort int16 18 | anInt32 int32 19 | aSlice []byte 20 | } 21 | 22 | type SliceHeader struct { 23 | Data uintptr 24 | Len int 25 | Cap int 26 | } 27 | 28 | func main() { 29 | // First ask Go to give us some information about the MyData type 30 | typ := reflect.TypeOf(MyData{}) 31 | fmt.Printf("Struct is %d bytes long\n", typ.Size()) 32 | 33 | // We can run through the fields in the structure in order 34 | n := typ.NumField() 35 | for i := 0; i < n; i++ { 36 | field := typ.Field(i) 37 | fmt.Printf("%s at offset %v, size=%d, align=%d\n", 38 | field.Name, field.Offset, field.Type.Size(), 39 | field.Type.Align()) 40 | } 41 | // A real instance of the struct 42 | data := MyData{ 43 | aByte: 0x1, 44 | aShort: 0x0203, 45 | anInt32: 0x04050607, 46 | aSlice: []byte{ 47 | 0x08, 0x09, 0x0a, 48 | }, 49 | } 50 | // Show it. 51 | // 32 is hardcoded based on previous output. 52 | dataBytes := (*[32]byte)(unsafe.Pointer(&data)) 53 | fmt.Printf("Bytes are %#v\n", dataBytes) 54 | // 55 | afield := (unsafe.Pointer(&data.aByte)) 56 | fmt.Printf("aByte data is %#v\n", 57 | (*[1]byte)(unsafe.Pointer(afield))) 58 | // 59 | afield = (unsafe.Pointer(&data.aShort)) 60 | work2 := (*[2]byte)(unsafe.Pointer(afield)) 61 | fmt.Printf("aShort data is %#v, BigEnd: %#v %#v\n", 62 | work2, work2[1], work2[0]) 63 | // 64 | afield = (unsafe.Pointer(&data.anInt32)) 65 | work4 := (*[4]byte)(unsafe.Pointer(afield)) 66 | fmt.Printf("anInt32 data is %#v, BigEnd: %#v %#v %#v %#v\n", 67 | work4, work4[3], work4[2], work4[1], work4[0]) 68 | // 69 | dataslice := *(*reflect.SliceHeader)(unsafe.Pointer(&data.aSlice)) 70 | work3 := (*[3]byte)(unsafe.Pointer(dataslice.Data)) 71 | fmt.Printf("Slice data is %#v\n", 72 | work3) 73 | // 74 | } 75 | -------------------------------------------------------------------------------- /runpprof/.gitignore: -------------------------------------------------------------------------------- 1 | runpprof 2 | runpprof.exe 3 | -------------------------------------------------------------------------------- /runpprof/runpprof.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demo generating a CPU profile. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "runtime/pprof" 10 | "time" 11 | ) 12 | 13 | func runner() { 14 | for i := 0; i < 1000000000; i++ { 15 | for j := 0; j < 30; j++ { // 16 | _ = i + j 17 | } 18 | } 19 | } 20 | 21 | func main() { 22 | s := time.Now() 23 | fmt.Println("Start", s) 24 | // 25 | f, err := os.Create("./cpu.prof") 26 | if err != nil { 27 | panic(err) 28 | } 29 | err = pprof.StartCPUProfile(f) 30 | if err != nil { 31 | panic(err) 32 | } 33 | runner() 34 | pprof.StopCPUProfile() 35 | // 36 | err = f.Close() 37 | if err != nil { 38 | panic(err) 39 | } 40 | e := time.Now() 41 | fmt.Println("End", s) 42 | fmt.Println("Elapsed", e.Sub(s)) 43 | } 44 | -------------------------------------------------------------------------------- /shax/.gitignore: -------------------------------------------------------------------------------- 1 | shax 2 | shax.exe 3 | -------------------------------------------------------------------------------- /shax/shax.go: -------------------------------------------------------------------------------- 1 | /* 2 | Generating sha1 and sha256 sums. 3 | */ 4 | package main 5 | 6 | import ( 7 | "crypto/sha1" 8 | "crypto/sha256" 9 | "fmt" // 10 | ) 11 | 12 | func main() { 13 | fmt.Println("Start...") 14 | // String from: 15 | // http://en.wikipedia.org/wiki/WebSocket 16 | s := "x3JJHMbDL1EzLkh9GBhXDw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 17 | 18 | // sha1 stuff ... 19 | sha1 := sha1.New() 20 | sha1.Write([]byte(s)) 21 | ss := fmt.Sprintf("%x", sha1.Sum(nil)) 22 | fmt.Printf("%s\n", ss) 23 | w := "1d29ab734b0c9585240069a6e4e3e91b61da1969" 24 | fmt.Printf("%s\n", w) 25 | if ss != w { 26 | panic("Uh oh, something is not right") 27 | } 28 | // --------------------------------------------------------------------------- 29 | // The base64 encoding part of that post is left as an exercise for now. 30 | // From the article the base64 result should be: 31 | // HSmrc0sMlYUkAGmm5OPpG2HaGWk= 32 | // *not tested* 33 | // --------------------------------------------------------------------------- 34 | // sha256 stuff ... 35 | sha256 := sha256.New() 36 | sha256.Write([]byte(s)) 37 | ss = fmt.Sprintf("%x", sha256.Sum(nil)) 38 | fmt.Printf("%s\n", ss) 39 | fmt.Println("End...") 40 | } 41 | -------------------------------------------------------------------------------- /shifter/.gitignore: -------------------------------------------------------------------------------- 1 | shifter 2 | shifter.exe 3 | -------------------------------------------------------------------------------- /shifter/shifter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Effects of shifts on signed and unsigned numbers. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func demoa() { 11 | d := 0x7fffffff 12 | fmt.Printf("positive %d, hex is %08x\n", d, d) 13 | m := -(d) 14 | fmt.Printf("negative %d, hex is %08x\n", m, m) 15 | // 16 | var i int = m 17 | fmt.Println("i1", i) 18 | fmt.Printf("i1 is: %d, and hex is: %08x\n", i, i) 19 | // 20 | 21 | var u uint = uint(m) 22 | fmt.Println("u1", u) 23 | fmt.Printf("u1 is: %d, and hex is: %08x\n", u, u) 24 | // 25 | var is int = i >> 1 26 | fmt.Println("is1", is) 27 | fmt.Printf("is1 is: %d, and hex is: %08x\n", is, is) 28 | // 29 | var is31 int = i >> 31 30 | fmt.Println("is31", is) 31 | fmt.Printf("is31 is: %d, and hex is: %08x\n", is31, is31) 32 | // 33 | var us uint = u >> 1 34 | fmt.Println("us1", us) 35 | fmt.Printf("us1 is: %d, and hex is: %08x\n", us, us) 36 | // 37 | var us31 uint = u >> 31 38 | fmt.Println("us31", us31) 39 | fmt.Printf("us31 is: %d, and hex is: %08x\n", us31, us31) 40 | } 41 | 42 | /* 43 | The bits in a byte. Bit numbers start at 0. 44 | */ 45 | func demoBitNumbers() { 46 | var b uint 47 | for b = 0; b < 8; b++ { // The bit number 48 | sval := 0x100 >> (b + 1) 49 | fmt.Printf("b:%d sval:%d svalhex:0x%02x\n", b, sval, sval) 50 | } 51 | } 52 | 53 | func main() { 54 | demoa() 55 | fmt.Println("====================================") 56 | fmt.Println("========= Next Demo ================") 57 | fmt.Println("====================================") 58 | demoBitNumbers() 59 | } 60 | -------------------------------------------------------------------------------- /show64/.gitignore: -------------------------------------------------------------------------------- 1 | show64 2 | show64.exe 3 | -------------------------------------------------------------------------------- /show64/show64.go: -------------------------------------------------------------------------------- 1 | /* 2 | Short demo of base64 encoding/decoding. 3 | */ 4 | package main 5 | 6 | import ( 7 | "encoding/base64" 8 | "fmt" 9 | ) 10 | 11 | func main() { 12 | n := base64.StdEncoding // Use a standard encoding 13 | 14 | // Show some encoded lengths ... 15 | for i := 1; i <= 16; i++ { 16 | fmt.Println(i, n.EncodedLen(i)) 17 | } 18 | 19 | fmt.Println() 20 | 21 | // Encode and then decode some strings ... 22 | s := []string{"A", "AB", "ABC", "ABCD"} 23 | for _, v := range s { 24 | b := []byte(v) 25 | ev := n.EncodeToString(b) 26 | fmt.Println(v, ev) 27 | ob, e := n.DecodeString(ev) 28 | if e != nil { 29 | panic(e) 30 | } 31 | fmt.Println(v, string(ob)) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /showallocs/.gitignore: -------------------------------------------------------------------------------- 1 | showallocs 2 | showallocs.exe 3 | -------------------------------------------------------------------------------- /showallocs/showallocs.go: -------------------------------------------------------------------------------- 1 | /* 2 | Show memory statistics gathering. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "runtime" 9 | "time" 10 | ) 11 | 12 | func main() { 13 | runtime.GOMAXPROCS(runtime.NumCPU()) 14 | 15 | stats := make([]runtime.MemStats, 60) 16 | for i := range stats { 17 | runtime.ReadMemStats(&stats[i]) 18 | time.Sleep(time.Second) 19 | } 20 | for _, m := range stats { 21 | fmt.Printf("%d, %d, %d, %d, %d\n", runtime.NumGoroutine(), m.Alloc, 22 | m.TotalAlloc, m.HeapAlloc, m.NumGC) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /showgo/.gitignore: -------------------------------------------------------------------------------- 1 | showgo 2 | showgo.exe 3 | -------------------------------------------------------------------------------- /showgo/showgo.go: -------------------------------------------------------------------------------- 1 | /* 2 | Display go information. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "runtime" 10 | ) 11 | 12 | func main() { 13 | fmt.Println("Start....") 14 | fmt.Printf("GOROOT: %s\n", runtime.GOROOT()) 15 | fmt.Printf("Architecture: %s\n", runtime.GOARCH) 16 | fmt.Printf("OS: %s\n", runtime.GOOS) 17 | fmt.Printf("Version: %s\n", runtime.Version()) 18 | // 19 | fmt.Println() 20 | fmt.Printf("TempDir: %s\n", os.TempDir()) 21 | fmt.Printf("PathSep: %s\n", string(os.PathSeparator)) 22 | fmt.Printf("PathListSep: %s\n", string(os.PathListSeparator)) 23 | fmt.Printf("DevNull: %s\n", os.DevNull) 24 | fmt.Println("End....") 25 | } 26 | -------------------------------------------------------------------------------- /showmac/.gitignore: -------------------------------------------------------------------------------- 1 | showmac 2 | showmac.exe 3 | -------------------------------------------------------------------------------- /showmac/showmac.go: -------------------------------------------------------------------------------- 1 | /* 2 | Show MAC / NIC information for this system. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "net" 9 | "strings" 10 | ) 11 | 12 | func getLocalMac() (result string, error error) { 13 | result = "" 14 | error = nil 15 | // 16 | ifaces, error := net.Interfaces() 17 | if error != nil { 18 | return 19 | } 20 | for _, face := range ifaces { 21 | // Eliminate local and possible Virtual Box interfaces 22 | if face.Name == "lo" || strings.HasPrefix(face.Name, "vbox") { 23 | continue 24 | } 25 | // Prefer known names for local interfaces 26 | if strings.HasPrefix(face.Name, "eth") || strings.HasPrefix(face.Name, "en") { 27 | result = face.HardwareAddr.String() 28 | break 29 | } 30 | // Otherwise, take what we can get 31 | result = face.HardwareAddr.String() 32 | } 33 | // 34 | return 35 | } 36 | 37 | func getAllMacs() (result string, error error) { 38 | result = "" 39 | error = nil 40 | // 41 | ifaces, error := net.Interfaces() 42 | if error != nil { 43 | return 44 | } 45 | for _, face := range ifaces { 46 | // 47 | result += (face.HardwareAddr.String() + "~") 48 | } 49 | // 50 | return 51 | } 52 | 53 | func main() { 54 | // 55 | ifaces, err := net.Interfaces() 56 | if err != nil { 57 | // fmt.Printf("Error: %v\n", err) 58 | panic("ooops 1") 59 | } 60 | // fmt.Printf("Interfaces: %v\n", ifaces) 61 | for _, face := range ifaces { 62 | fmt.Println("Interface") 63 | fmt.Println("---------") 64 | fmt.Printf("Name: %s\n", face.Name) 65 | fmt.Printf("MAC: %s\n", face.HardwareAddr) 66 | fmt.Println("") 67 | } 68 | // 69 | preferred, err := getLocalMac() 70 | if err != nil { 71 | panic("ooops 2") 72 | } 73 | fmt.Printf("Preferred MAC: %v\n", preferred) 74 | // 75 | allmacs, err := getAllMacs() 76 | if err != nil { 77 | panic("ooops 3") 78 | } 79 | fmt.Printf("All MACs: %v\n", allmacs) 80 | } 81 | -------------------------------------------------------------------------------- /showpprof/.gitignore: -------------------------------------------------------------------------------- 1 | showpprof 2 | showpprof.exe 3 | -------------------------------------------------------------------------------- /showpprof/showpprof.go: -------------------------------------------------------------------------------- 1 | /* 2 | Display available profiles. 3 | */ 4 | package main 5 | 6 | import ( 7 | "log" 8 | "os" 9 | "runtime/pprof" 10 | ) 11 | 12 | var logger = log.New(os.Stdout, "SHOWPPROF ", log.Ldate|log.Lmicroseconds|log.Lshortfile) 13 | 14 | func main() { 15 | logger.Println("Start...") 16 | // 17 | profs := pprof.Profiles() 18 | for _, p := range profs { 19 | logger.Println(p.Name()) 20 | } 21 | logger.Println("End...") 22 | } 23 | -------------------------------------------------------------------------------- /showrtc/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | showrtc 3 | showrtc.exe 4 | -------------------------------------------------------------------------------- /showrtc/showrtc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | ) 7 | 8 | /* 9 | Show the constants from the runtime package. 10 | */ 11 | func main() { 12 | log.Println("runtime.Compiler", runtime.Compiler) 13 | log.Println("runtime.GOARCH", runtime.GOARCH) 14 | log.Println("runtime.GOOS", runtime.GOOS) 15 | } 16 | -------------------------------------------------------------------------------- /showsetcpus/.gitignore: -------------------------------------------------------------------------------- 1 | showsetcpus 2 | showsetcpus.exe 3 | -------------------------------------------------------------------------------- /showsetcpus/showsetcpus.go: -------------------------------------------------------------------------------- 1 | /* 2 | Show retrieving NumCPU and setting GOMAXPROCS. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "runtime" 9 | ) 10 | 11 | func main() { 12 | nc := runtime.NumCPU() 13 | fmt.Println("NumCPUs present:", nc) 14 | nrc := runtime.GOMAXPROCS(-1) 15 | fmt.Println("GOMAXPROCS Default:", nrc) 16 | _ = runtime.GOMAXPROCS(nc) // Set 17 | nrc = runtime.GOMAXPROCS(-1) // Retrieve again 18 | fmt.Println("GOMAXPROCS After Final Set:", nrc) 19 | } 20 | -------------------------------------------------------------------------------- /showtime/.gitignore: -------------------------------------------------------------------------------- 1 | showtime 2 | showtime.exe 3 | -------------------------------------------------------------------------------- /showtime/showtime.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate using the time package. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | "time" 11 | ) 12 | 13 | var logger = log.New(os.Stdout, "SHOWTIME ", log.Ldate|log.Lmicroseconds|log.Lshortfile) 14 | 15 | func runTicker(quit chan bool) { 16 | ticker := time.NewTicker(time.Duration(1e9 * 3)) 17 | q := false 18 | for { 19 | logger.Println("loop start") 20 | select { 21 | case ct := <-ticker.C: 22 | logger.Println(ct) 23 | case q = <-quit: 24 | logger.Println("runTicker done") 25 | ticker.Stop() 26 | break 27 | } 28 | if q { 29 | break 30 | } 31 | } 32 | logger.Println("runTicker ends") 33 | } 34 | 35 | func main() { 36 | fmt.Println() 37 | logger.Println("Start...") 38 | 39 | logger.Println(time.Now()) 40 | 41 | time.Sleep(time.Duration(1e9 * 10)) // 10 secs 42 | logger.Println(time.Now()) 43 | logger.Println(time.Now().UTC()) 44 | 45 | donechan := make(chan bool) 46 | go runTicker(donechan) 47 | 48 | logger.Println("start 30") 49 | time.Sleep(time.Duration(1e9 * 30)) // 30 secs 50 | logger.Println("done 30") 51 | donechan <- true 52 | 53 | time.Sleep(1e9) // 1 sec 54 | 55 | lt := time.Now() 56 | ft := lt.Format(time.StampMicro) 57 | logger.Println(ft) 58 | logger.Println(time.Now().Format(time.StampMicro)) 59 | fmt.Println(time.Now().Format(time.StampMicro)) 60 | logger.Println("End...") 61 | } 62 | -------------------------------------------------------------------------------- /sigshow/.gitignore: -------------------------------------------------------------------------------- 1 | sigshow 2 | sigshow.exe 3 | -------------------------------------------------------------------------------- /sigshow/sigshow.go: -------------------------------------------------------------------------------- 1 | /* 2 | Short demonstration of signals. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "os/signal" 10 | "sync" 11 | ) 12 | 13 | var wg sync.WaitGroup 14 | 15 | func handleSignal(c chan os.Signal) { 16 | s := <-c 17 | fmt.Println("signal handled:", s) 18 | wg.Done() 19 | } 20 | 21 | func main() { 22 | fmt.Println("Start...") 23 | wg.Add(1) 24 | 25 | i := make(chan os.Signal, 1) 26 | go handleSignal(i) 27 | signal.Notify(i) // All handleable signals 28 | 29 | wg.Wait() 30 | fmt.Println("End...") 31 | } 32 | -------------------------------------------------------------------------------- /sl3index/.gitignore: -------------------------------------------------------------------------------- 1 | sl3index 2 | sl3index.exe 3 | -------------------------------------------------------------------------------- /sl3index/sl3index.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demo 3 index slicing. Requires go 1.2. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func main() { 11 | // Init 12 | var array [10]int 13 | for i := 0; i < 10; i++ { 14 | array[i] = i + 1 15 | } 16 | 17 | fmt.Printf("array: %v\n", array) 18 | slice := array[2:4] 19 | fmt.Printf("slice: %v %d %d\n", slice, len(slice), cap(slice)) 20 | fmt.Printf("array: %v\n", array) 21 | slice[1] = 77 22 | fmt.Printf("slice: %v %d %d\n", slice, len(slice), cap(slice)) 23 | fmt.Printf("array: %v\n", array) 24 | slice2 := array[2:4:6] 25 | fmt.Printf("slice2: %v %d %d\n", slice2, len(slice2), cap(slice2)) 26 | slice2 = append(slice2, 43) 27 | fmt.Printf("slice2: %v %d %d\n", slice2, len(slice2), cap(slice2)) 28 | fmt.Printf("array: %v\n", array) 29 | slice2[2] = 99 30 | fmt.Printf("slice2: %v %d %d\n", slice2, len(slice2), cap(slice2)) 31 | fmt.Printf("array: %v\n", array) 32 | slice2 = append(slice2, 88) 33 | fmt.Printf("slice2: %v %d %d\n", slice2, len(slice2), cap(slice2)) 34 | fmt.Printf("array: %v\n", array) 35 | for i := 101; i <= 105; i++ { 36 | slice2 = append(slice2, i) 37 | fmt.Printf("slice2: %v %d %d\n", slice2, len(slice2), cap(slice2)) 38 | fmt.Printf("array: %v\n", array) 39 | } 40 | // Output: 41 | /* 42 | array: [1 2 3 4 5 6 7 8 9 10] 43 | slice: [3 4] 2 8 44 | array: [1 2 3 4 5 6 7 8 9 10] 45 | slice: [3 77] 2 8 46 | array: [1 2 3 77 5 6 7 8 9 10] 47 | slice2: [3 77] 2 4 48 | slice2: [3 77 43] 3 4 49 | array: [1 2 3 77 43 6 7 8 9 10] 50 | slice2: [3 77 99] 3 4 51 | array: [1 2 3 77 99 6 7 8 9 10] 52 | slice2: [3 77 99 88] 4 4 53 | array: [1 2 3 77 99 88 7 8 9 10] 54 | slice2: [3 77 99 88 101] 5 8 55 | array: [1 2 3 77 99 88 7 8 9 10] 56 | slice2: [3 77 99 88 101 102] 6 8 57 | array: [1 2 3 77 99 88 7 8 9 10] 58 | slice2: [3 77 99 88 101 102 103] 7 8 59 | array: [1 2 3 77 99 88 7 8 9 10] 60 | slice2: [3 77 99 88 101 102 103 104] 8 8 61 | array: [1 2 3 77 99 88 7 8 9 10] 62 | slice2: [3 77 99 88 101 102 103 104 105] 9 16 63 | array: [1 2 3 77 99 88 7 8 9 10] 64 | */ 65 | 66 | } 67 | -------------------------------------------------------------------------------- /slappmult/.gitignore: -------------------------------------------------------------------------------- 1 | slappmult 2 | slappmult.exe 3 | -------------------------------------------------------------------------------- /slappmult/slappmult.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate append multiple slices. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func addmult(orig []byte, stuff ...[]byte) []byte { 11 | b := make([]byte, 0) 12 | b = append(b, orig...) 13 | for _, val := range stuff { 14 | b = append(b, val...) 15 | } 16 | return b 17 | } 18 | 19 | func addmultv(stuff [][]byte) []byte { 20 | b := make([]byte, 0) 21 | for _, val := range stuff { 22 | b = append(b, val...) 23 | } 24 | return b 25 | } 26 | 27 | // Append multiple splices. 28 | func main() { 29 | fmt.Println("Hi") 30 | s1 := "1\n" 31 | s1b := []byte(s1) 32 | s2 := "2\n" 33 | s2b := []byte(s2) 34 | s3 := "3\n" 35 | s3b := []byte(s3) 36 | 37 | // 38 | fmt.Printf("%v", s1) 39 | fmt.Printf("%v\n", s1b) 40 | fmt.Printf("%v", s2) 41 | fmt.Printf("%v\n", s2b) 42 | fmt.Printf("%v", s3) 43 | fmt.Printf("%v\n", s3b) 44 | 45 | // Here is one way to do this. 46 | ob := make([]byte, 0) 47 | ob = append(ob, s1b...) 48 | ob = append(ob, s2b...) 49 | ob = append(ob, s3b...) 50 | fmt.Printf("%v\n", ob) 51 | 52 | // And here is a somewhat more generalized way. 53 | ob2 := make([]byte, 0) // An empty orig ..... 54 | ob2 = addmult(ob2, s1b, s2b, s3b) 55 | fmt.Printf("%v\n", ob2) 56 | 57 | // And here is yet another somewhat more generalized way. 58 | bat := addmultv([][]byte{s1b, s2b, s3b}) 59 | fmt.Printf("%v\n", bat) 60 | 61 | // Is there a way to do this with a single append call ??? 62 | // Is there a better way to do this in general ??? 63 | 64 | } 65 | -------------------------------------------------------------------------------- /slblog/.gitignore: -------------------------------------------------------------------------------- 1 | slblog 2 | slblog.exe 3 | 4 | -------------------------------------------------------------------------------- /sldemo/.gitignore: -------------------------------------------------------------------------------- 1 | sldemo 2 | sldemo.exe 3 | -------------------------------------------------------------------------------- /sldemo/sldemo.go: -------------------------------------------------------------------------------- 1 | /* 2 | Another slice demo. From: 3 | https://appliedgo.net/slices/ 4 | Slightly embellished. 5 | */ 6 | package main 7 | 8 | import ( 9 | "bytes" 10 | "fmt" 11 | ) 12 | 13 | func splitDemo() { 14 | fmt.Println("Split demo") 15 | a := []byte("a,b,c") 16 | b := bytes.Split(a, []byte(",")) 17 | 18 | // a -> mem_location(x) 19 | // b[0] -> mem_location(x) 20 | // b[1] -> mem_location(x) + 2 21 | // b[2] -> mem_location(x) + 4 22 | fmt.Println("Addresses:") 23 | fmt.Printf("a: %p\n", a) 24 | fmt.Printf("b[0]: %p\n", b[0]) 25 | fmt.Printf("b[1]: %p\n", b[1]) 26 | fmt.Printf("b[2]: %p\n", b[2]) 27 | 28 | fmt.Printf("a before changing b[0][0]: %q\n", a) 29 | b[0][0] = byte('*') 30 | fmt.Printf("a after changing b[0][0]: %q\n", a) 31 | fmt.Printf("b[1] before appending to b[0]: %q\n", b[1]) 32 | b[0] = append(b[0], 'd', 'e', 'f') 33 | fmt.Printf("b[1] after appending to b[0]: %q\n", b[1]) 34 | fmt.Printf("a after appending to b[0]: %q\n", a) 35 | } 36 | 37 | func appendDemo() { 38 | fmt.Println("\nAppend demo") 39 | s1 := make([]int, 2, 4) // Initial cap is 4 40 | s1[0] = 1 41 | s1[1] = 2 42 | fmt.Printf("Initial address and value: %p: %[1]v\n", s1) 43 | s1 = append(s1, 3, 4) // Two elements, up to cap 44 | fmt.Printf("After first append: %p: %[1]v\n", s1) 45 | s1 = append(s1, 5) // Overflows cap, causes alloc and copy 46 | fmt.Printf("After second append: %p: %[1]v\n", s1) 47 | } 48 | 49 | func alwaysCopy() { 50 | fmt.Println("\nAppend and always copy") 51 | s1 := []int{1, 2, 3, 4} 52 | fmt.Printf("s1: %p: %[1]v\n", s1) 53 | s2 := make([]int, 4, 8) 54 | copy(s2, s1) 55 | fmt.Printf("s2: %p: %[1]v\n", s2) 56 | s2 = append(s2, 5, 6, 7, 8) 57 | fmt.Printf("s2: %p: %[1]v\n", s2) 58 | } 59 | 60 | func main() { 61 | splitDemo() 62 | appendDemo() 63 | alwaysCopy() 64 | } 65 | -------------------------------------------------------------------------------- /sliceappt/.gitignore: -------------------------------------------------------------------------------- 1 | sliceappt 2 | sliceappt.exe 3 | -------------------------------------------------------------------------------- /sliceappt/sliceappt.go: -------------------------------------------------------------------------------- 1 | /* 2 | Brief slice of strings demonstration. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | type paired_slice []string 11 | 12 | func (p paired_slice) Add(k, v string) paired_slice { 13 | r := append(p, k, v) 14 | return r 15 | } 16 | 17 | func main() { 18 | fmt.Println("Start...") 19 | ps := paired_slice{} 20 | fmt.Println("ps01:", ps) 21 | ps = ps.Add("k1", "v1") 22 | fmt.Println("ps02:", ps) 23 | ps = ps.Add("k2", "v2") 24 | fmt.Println("ps03:", ps) 25 | // 26 | ps = ps.Add("k3", "v3").Add("k4", "v4") 27 | fmt.Println("ps04:", ps) 28 | // 29 | fmt.Println("ps90:", paired_slice{}. 30 | Add("ak1", "av1"). 31 | Add("ak2", "av2")) 32 | fmt.Println("End...") 33 | } 34 | -------------------------------------------------------------------------------- /slices/.gitignore: -------------------------------------------------------------------------------- 1 | slices 2 | slices.exe 3 | -------------------------------------------------------------------------------- /slices/slices.go: -------------------------------------------------------------------------------- 1 | /* 2 | Slice demonstration from the gocourse PDFs. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | /* 9 | From examples. 10 | */ 11 | // 12 | // Print a slice of int's. 13 | // 14 | func prtsl_int(a []int) { 15 | fmt.Printf("len: %d, cap: %d\n", len(a), cap(a)) 16 | fmt.Println(a) 17 | fmt.Println() 18 | } 19 | 20 | // 21 | func appendToSlice(i int, sl []int) []int { 22 | // 23 | // Exceeding capacity should be handled, but is not: 24 | // if len(sl) == cap(sl) { error(...) } 25 | // 26 | n := len(sl) // Current len 27 | sl = sl[0 : n+1] // extend length by 1 28 | sl[n] = i // store caller's value 29 | return sl 30 | } 31 | 32 | // 33 | func main() { 34 | // 35 | // Slice literals look like an array literal without a size. 36 | // 37 | var slice = []int{1, 2, 3, 5, 6, 7, 9, 10, 11} 38 | prtsl_int(slice) 39 | // 40 | sla := slice[:] 41 | prtsl_int(sla) 42 | // 43 | slb := slice[4:] 44 | prtsl_int(slb) 45 | // 46 | slc := slice[4:6] 47 | prtsl_int(slc) 48 | // Range is over 'len', not 'cap' 49 | for _, nse := range slc { 50 | fmt.Printf("Next: %d\n", nse) 51 | } 52 | fmt.Println() 53 | // 54 | var s25 = make([]int, 25) 55 | prtsl_int(s25) 56 | // 57 | for n := 0; n < cap(s25); n++ { 58 | // fmt.Printf("Next: %d\n", n) 59 | s25[n] = n 60 | } 61 | prtsl_int(s25) 62 | for _, n := range s25 { 63 | fmt.Printf("Next: %d\n", n) 64 | } 65 | // 66 | fmt.Println() 67 | var ar = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // An array, not a slice 68 | fmt.Println(ar) 69 | // 70 | var sld = ar[3:5] // 71 | fmt.Println(sld) 72 | // 73 | var sl = make([]int, 0, 100) // len 0, cap 100 74 | prtsl_int(sl) 75 | sl = appendToSlice(123, sl) 76 | prtsl_int(sl) 77 | sl = appendToSlice(456, sl) 78 | prtsl_int(sl) 79 | } 80 | -------------------------------------------------------------------------------- /slofsl/.gitignore: -------------------------------------------------------------------------------- 1 | slofsl 2 | slofsl.exe 3 | -------------------------------------------------------------------------------- /slofsl/slofsl.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate using a slice of slices. 3 | 4 | This example uses an anonymous struct for the demonstration. This is 5 | like table driven tests are frequently accomplished in the go standard library. 6 | */ 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // The data for this demonstration 14 | var sosd = []struct { 15 | flag int // A flag for the test 16 | sos [][]string // The slice of slices 17 | }{ 18 | { 19 | 100, 20 | [][]string{[]string{"a100"}}, 21 | }, 22 | { 23 | 200, 24 | [][]string{[]string{"a200", "b200"}}, 25 | }, 26 | { 27 | 300, 28 | [][]string{[]string{"a300", "b300", "c300"}}, 29 | }, 30 | { 31 | 400, 32 | [][]string{[]string{"a400", "b400", "d300"}, 33 | []string{"x400", "y400", "z300"}}, 34 | }, 35 | } 36 | 37 | var ( 38 | sl = "===========================================================" 39 | sa = "--------------------------" 40 | ) 41 | 42 | func main() { 43 | fmt.Println("start") 44 | fmt.Println(sl) 45 | 46 | // Process the slices of the anonymous struct 47 | for oi, ov := range sosd { 48 | fmt.Println() 49 | fmt.Println(wrap("outer")) 50 | fmt.Printf("oi:%d ov%q\n", oi, ov) 51 | fmt.Printf("struct flag:%d\n", ov.flag) 52 | 53 | // Process the slice of slices of strings 54 | for mi, mv := range ov.sos { 55 | fmt.Println(wrap("middle")) 56 | fmt.Printf("\tmi:%d mv%q\n", mi, mv) 57 | 58 | // Process the innermost slice 59 | for ii, iv := range mv { 60 | fmt.Println(wrap("inner")) 61 | fmt.Printf("\t\tii:%d iv:%q\n", ii, iv) 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | fmt.Println(sl) 69 | fmt.Println("end") 70 | } 71 | 72 | func wrap(s string) string { 73 | return sa + " " + s + " " + sa 74 | } 75 | -------------------------------------------------------------------------------- /slofsl2/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | slofsl2 3 | slofsl2.exe 4 | -------------------------------------------------------------------------------- /slofsl2/slofsl2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | Another experiment with a slice of slices, as well 5 | as a template experiment. 6 | */ 7 | import ( 8 | "fmt" 9 | "html/template" 10 | "os" 11 | ) 12 | 13 | // table data 14 | type tdata struct { 15 | Colh []string 16 | Rdata [][]string 17 | } 18 | 19 | // template to generate HTML table 20 | // this template uses the trick: 21 | // {{/* 22 | // */}}... 23 | // 24 | // to eliminate empty lines. Ugly, but it works. 25 | var tp = ` 26 | 27 | {{/* 28 | */}}{{range .Colh}} 29 | {{/* 30 | */}}{{end}} 31 | {{/* 32 | */}}{{range .Rdata}} 33 | {{/* 34 | */}}{{range .}} 35 | {{/* 36 | */}}{{end}} 37 | {{/* 38 | */}}{{end}} 39 |
{{.}}
{{.}}
40 | ` 41 | 42 | // generate an HTML table from the data 43 | func tbgen(tdv tdata) { 44 | t := template.Must(template.New("").Parse(tp)) 45 | t.Execute(os.Stdout, tdv) 46 | } 47 | 48 | // build the data 49 | func exdata() tdata { 50 | tdv := tdata{} 51 | tdv.Colh = make([]string, 0) 52 | tdv.Rdata = make([][]string, 0) 53 | // 54 | tdv.Colh = append(tdv.Colh, "Cha", "Chb", "Chc") 55 | // 56 | ws := make([]string, 0) 57 | ws = append(ws, "A", "B", "C") 58 | tdv.Rdata = append(tdv.Rdata, ws) 59 | // 60 | ws = make([]string, 0) 61 | ws = append(ws, "D", "E", "F") 62 | tdv.Rdata = append(tdv.Rdata, ws) 63 | // 64 | ws = make([]string, 0) 65 | ws = append(ws, "G", "H", "I") 66 | tdv.Rdata = append(tdv.Rdata, ws) 67 | return tdv 68 | } 69 | 70 | // basic data dump 71 | func dumptd(tdv tdata) { 72 | // 73 | for i, d := range tdv.Colh { 74 | fmt.Printf("Col: %d header is: %s\n", i, d) 75 | } 76 | fmt.Println() 77 | for i, d := range tdv.Rdata { 78 | fmt.Printf("Row: %d is: %s\n", i, d) 79 | for j, sd := range d { 80 | fmt.Printf("\tCol: %d is: %s\n", j, sd) 81 | } 82 | } 83 | } 84 | 85 | func main() { 86 | fmt.Println("hi") 87 | rhd := exdata() 88 | fmt.Printf("rhd: %v\n", rhd) 89 | dumptd(rhd) 90 | tbgen(rhd) 91 | // 92 | } 93 | -------------------------------------------------------------------------------- /sltricks/.gitignore: -------------------------------------------------------------------------------- 1 | sltricks 2 | sltricks.exe 3 | -------------------------------------------------------------------------------- /sortex/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | sortex 3 | sortex.exe 4 | 5 | -------------------------------------------------------------------------------- /sortex/sortex.go: -------------------------------------------------------------------------------- 1 | /* 2 | An example of using sort. 3 | */ 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "sort" 10 | ) 11 | 12 | type tt struct { 13 | tk int 14 | td string 15 | } 16 | 17 | var tvs = []tt{ 18 | tt{6, "xyz1"}, 19 | tt{2, "xyz4"}, 20 | tt{19, "xyz7"}, 21 | tt{19, "xyz3"}, 22 | tt{7, "xyz2"}, 23 | } 24 | 25 | var ( 26 | sv = tvs 27 | ) 28 | 29 | // Type Stringer 30 | func (v tt) String() string { 31 | return fmt.Sprintf("%d->%s", v.tk, v.td) 32 | } 33 | 34 | // ByTK stuff. 35 | type ByTK []tt 36 | 37 | func (t ByTK) Len() int { 38 | return len(t) 39 | } 40 | 41 | func (t ByTK) Swap(i, j int) { 42 | t[i], t[j] = t[j], t[i] 43 | } 44 | 45 | func (t ByTK) Less(i, j int) bool { 46 | return t[i].tk < t[j].tk 47 | } 48 | 49 | // ByTD stuff. 50 | type ByTD []tt 51 | 52 | func (t ByTD) Len() int { 53 | return len(t) 54 | } 55 | 56 | func (t ByTD) Swap(i, j int) { 57 | t[i], t[j] = t[j], t[i] 58 | } 59 | 60 | func (t ByTD) Less(i, j int) bool { 61 | return t[i].td < t[j].td 62 | } 63 | 64 | func main() { 65 | s := "======================================================" 66 | // 67 | fmt.Println() 68 | fmt.Println(s) 69 | fmt.Println("Original") 70 | fmt.Println(tvs) 71 | // 72 | fmt.Println() 73 | fmt.Println(s) 74 | sort.Sort(ByTK(tvs)) 75 | fmt.Println("By Key") 76 | fmt.Println(tvs) 77 | // 78 | fmt.Println() 79 | fmt.Println(s) 80 | sort.Sort(ByTD(tvs)) 81 | fmt.Println("By Data") 82 | fmt.Println(tvs) 83 | // 84 | fmt.Println() 85 | fmt.Println(s) 86 | fmt.Println("Orig:", sv) 87 | sort.Slice(sv, func(i, j int) bool { 88 | return sv[i].tk > sv[j].tk // Note: > ==> Descending 89 | }) 90 | fmt.Println("Desc By Key:", sv) 91 | } 92 | -------------------------------------------------------------------------------- /sqlex/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | sqlex 3 | sqlex.exe 4 | 5 | -------------------------------------------------------------------------------- /sqlex/foo.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/sqlex/foo.db -------------------------------------------------------------------------------- /sqlex/sqlex.go: -------------------------------------------------------------------------------- 1 | /* 2 | A contrived SQL DB example. 3 | */ 4 | package main 5 | 6 | import ( 7 | "database/sql" 8 | "fmt" 9 | 10 | _ "github.com/mattn/go-sqlite3" 11 | ) 12 | 13 | func main() { 14 | // DB Open 15 | db, err := sql.Open("sqlite3", "./foo.db") 16 | testError("DBOPEN", err) 17 | 18 | // Insert 19 | stmt, err := db.Prepare("INSERT INTO memos(text, priority) values(?,?)") 20 | testError("Prepare", err) 21 | res, err := stmt.Exec("memo data", 15) 22 | testError("Exec", err) 23 | fmt.Println(res) 24 | 25 | // Query 26 | rows, err := db.Query("SELECT * FROM memos") 27 | testError("Query", err) 28 | var text string 29 | var priority int 30 | // Scan all rows returned 31 | for rows.Next() { 32 | err = rows.Scan(&text, &priority) 33 | testError("Scan", err) 34 | fmt.Println(text) 35 | fmt.Println(priority) 36 | } 37 | rows.Close() 38 | 39 | // DB Close 40 | db.Close() 41 | 42 | } 43 | 44 | func testError(id string, err error) { 45 | if err != nil { 46 | panic(id + " " + err.Error()) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ssl/.gitignore: -------------------------------------------------------------------------------- 1 | ssl 2 | -------------------------------------------------------------------------------- /ssl/README.mdown: -------------------------------------------------------------------------------- 1 | SSL Examples 2 | ============ 3 | 4 | This directory and subdirectories contain data and code that demonstrate the 5 | use of SSL when connecting to a server. 6 | 7 | Subdirectories 8 | -------------- 9 | 10 | * certinfo - Load a certificate and key into an tls.Certificate instance 11 | * certs - all SSL certificates which were used in these examples 12 | * client1 - demonstrate SSL use case 1 13 | * client2 - demonstrate SSL use case 2 14 | * client3 - demonstrate SSL use case 3 15 | * client4 - demonstrate SSL use case 4 16 | * pemload - Load a certificate into an x509.Certificate instance 17 | 18 | SSL Use Case 1 19 | -------------- 20 | 21 | * Server does not authenticate client 22 | * Client does not authenticate server 23 | 24 | SSL Use Case 2 25 | -------------- 26 | 27 | * Server does not authenticate client 28 | * Client does authenticate server 29 | 30 | SSL Use Case 3 31 | -------------- 32 | 33 | * Server does authenticate client 34 | * Client does not authenticate server 35 | 36 | SSL Use Case 4 37 | -------------- 38 | 39 | This is two-way or mutual authentication. 40 | 41 | * Server does authenticate client 42 | * Client does authenticate server 43 | 44 | Notes 45 | ----- 46 | 47 | It is usually possible to configure a server in one of two ways: 48 | 49 | * Client MAY send a certificate to the server 50 | * Client MUST send a certificate to the server 51 | 52 | The behavior of the use cases will vary depending on this configuration 53 | setting. See comments in the code for each use case. 54 | 55 | All certificates and keys were generated using openssl. 56 | 57 | The .store file(s) included are Java keystores, of type JKS. These were created 58 | by using keytool to import PKCS12 format certificates. 59 | 60 | All passwords are the word password. 61 | -------------------------------------------------------------------------------- /ssl/certinfo/.gitignore: -------------------------------------------------------------------------------- 1 | certinfo 2 | certinfo.exe 3 | -------------------------------------------------------------------------------- /ssl/certinfo/certinfo.go: -------------------------------------------------------------------------------- 1 | /* 2 | Display some information about an SSL certificate. 3 | */ 4 | package main 5 | 6 | import ( 7 | "crypto/tls" 8 | "crypto/x509" 9 | "encoding/hex" 10 | "log" 11 | ) 12 | 13 | type certFileData struct { 14 | cert string 15 | key string 16 | } 17 | 18 | var certFiles = []certFileData{ 19 | {"../certs/client/client.crt", "../certs/client/client.key"}, 20 | } 21 | 22 | func showX509Cert(c *x509.Certificate) { 23 | log.Println("RAW Length:", len(c.Raw)) 24 | rds := hex.Dump(c.Raw) 25 | log.Printf("Rawdata:\n%s\n", rds) 26 | } 27 | 28 | func showTLSCert(c tls.Certificate) { 29 | log.Println("===============================================================") 30 | log.Println("Chain Length:", len(c.Certificate)) 31 | for n, cx := range c.Certificate { 32 | log.Println("Cert Element: ", n+1, "Length:", len(cx)) 33 | log.Printf("%s\n", hex.Dump(cx)) 34 | } 35 | log.Println("OCSPStaple Length:", len(c.OCSPStaple)) 36 | if c.Leaf == nil { 37 | log.Println("Leaf pointer is nil") 38 | } else { 39 | showX509Cert(c.Leaf) 40 | } 41 | } 42 | 43 | func main() { 44 | for n, cf := range certFiles { 45 | log.Println("Cert number:", n+1) 46 | log.Println("Cert File:", cf.cert) 47 | log.Println("Key File:", cf.key) 48 | // 49 | c, e := tls.LoadX509KeyPair(cf.cert, cf.key) 50 | if e != nil { 51 | log.Fatalln("Error: ", e) 52 | } 53 | showTLSCert(c) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ssl/certs/.gitignore: -------------------------------------------------------------------------------- 1 | certs 2 | certs.exe 3 | -------------------------------------------------------------------------------- /ssl/certs/ca/ca.pks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/ssl/certs/ca/ca.pks -------------------------------------------------------------------------------- /ssl/certs/ca/ca.store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/ssl/certs/ca/ca.store -------------------------------------------------------------------------------- /ssl/certs/client/client.pks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/ssl/certs/client/client.pks -------------------------------------------------------------------------------- /ssl/certs/client/client.store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/ssl/certs/client/client.store -------------------------------------------------------------------------------- /ssl/certs/server/server.pks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/ssl/certs/server/server.pks -------------------------------------------------------------------------------- /ssl/certs/server/server.store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/ssl/certs/server/server.store -------------------------------------------------------------------------------- /ssl/client1/.gitignore: -------------------------------------------------------------------------------- 1 | client1 2 | client1.exe 3 | -------------------------------------------------------------------------------- /ssl/client1/client1.go: -------------------------------------------------------------------------------- 1 | /* 2 | SSL Use Case 1. 3 | */ 4 | package main 5 | 6 | import ( 7 | "crypto/tls" 8 | "fmt" 9 | "log" 10 | ) 11 | 12 | var ( 13 | testConfig *tls.Config 14 | hapnocl = "localhost:61611" // ActiveMQ (needClientAuth="false") 15 | ) 16 | 17 | func dumpState(s tls.ConnectionState) { 18 | log.Printf("Version: %d(0x%04x)\n", s.Version, s.Version) 19 | log.Printf("HandshakeComplete: %t\n", s.HandshakeComplete) 20 | log.Printf("DidResume: %t\n", s.DidResume) 21 | log.Printf("CipherSuite: %d(0x%04x)\n", s.CipherSuite, s.CipherSuite) 22 | log.Printf("NegotiagedProtocol: %s\n", s.NegotiatedProtocol) 23 | log.Printf("NegotiagedProtocolIsMutual: %t\n", s.NegotiatedProtocolIsMutual) 24 | log.Printf("Server Name: %s\n", s.ServerName) 25 | log.Printf("Length PeerCertificates: %d(0x%04x)\n", len(s.PeerCertificates), 26 | len(s.PeerCertificates)) 27 | log.Printf("Length VerifiedChains: %d(0x%04x)\n", len(s.VerifiedChains), 28 | len(s.VerifiedChains)) 29 | log.Printf("Length SignedCertificateTimestamps: %d(0x%04x)\n", len(s.SignedCertificateTimestamps), 30 | len(s.SignedCertificateTimestamps)) 31 | log.Printf("Length OCSPResponse: %d(0x%04x)\n", len(s.OCSPResponse), 32 | len(s.OCSPResponse)) 33 | } 34 | 35 | // 36 | // SSL Use Case 1 - server does *not* authenticate client, client does *not* authenticate server 37 | // 38 | // Subcase 1.A - Server configuration does *not* require client authentication 39 | // 40 | // - Expect connection success 41 | // 42 | // Subcase 1.B - Server configuration *does* require client authentication 43 | // 44 | // - Expect connection failure (server must be sent a valid client certificate) 45 | // 46 | 47 | func main() { 48 | fmt.Println("start......") 49 | testConfig = new(tls.Config) 50 | testConfig.InsecureSkipVerify = true // Do *not* check the server's certificate 51 | c, e := tls.Dial("tcp", hapnocl, testConfig) // Server does not require a cert 52 | // from us. 53 | if e != nil { 54 | log.Fatalln("Dial Error::", e.Error()) 55 | } 56 | // 57 | log.Println("Dial complete") 58 | log.Println("Connection State Reference:") 59 | s := c.ConnectionState() 60 | dumpState(s) 61 | if !s.HandshakeComplete { 62 | e = c.Handshake() 63 | if e != nil { 64 | log.Fatalln("Handskake Not Complete! Handshake Error:", e.Error()) 65 | } 66 | } 67 | log.Println("Handshake Complete OK") 68 | // 69 | e = c.Close() 70 | if e != nil { 71 | log.Fatalln("Close Error::", e) 72 | } 73 | // Check e 74 | fmt.Println("done......") 75 | } 76 | -------------------------------------------------------------------------------- /ssl/client2/.gitignore: -------------------------------------------------------------------------------- 1 | client2 2 | client2.exe 3 | -------------------------------------------------------------------------------- /ssl/client3/.gitignore: -------------------------------------------------------------------------------- 1 | client3 2 | client3.exe 3 | -------------------------------------------------------------------------------- /ssl/client4/.gitignore: -------------------------------------------------------------------------------- 1 | client4 2 | client4.exe 3 | -------------------------------------------------------------------------------- /ssl/pemload/.gitignore: -------------------------------------------------------------------------------- 1 | pemload 2 | pemload.exe 3 | -------------------------------------------------------------------------------- /ssl/pemload/pemload.go: -------------------------------------------------------------------------------- 1 | /* 2 | Display PEM file information. 3 | */ 4 | package main 5 | 6 | import ( 7 | "crypto/x509" 8 | "encoding/hex" 9 | "encoding/pem" 10 | "fmt" 11 | "io" 12 | "log" 13 | "os" 14 | ) 15 | 16 | var file_name = "../certs/server/server.crt" 17 | 18 | func main() { 19 | fmt.Println("start.....") 20 | fi, e := os.Lstat(file_name) 21 | if e != nil { 22 | log.Fatalln("Lstat Error::", e.Error()) 23 | } 24 | fmt.Printf("File Size:\t%d\n", fi.Size()) 25 | // 26 | buff := make([]byte, fi.Size()) 27 | // 28 | f, e := os.OpenFile(file_name, os.O_RDONLY, 0644) 29 | if e != nil { 30 | log.Fatalln("Open Error::", e.Error()) 31 | } 32 | // 33 | n, e := f.Read(buff) 34 | if e != nil && e != io.EOF { 35 | log.Fatalln("Read Error::", e.Error()) 36 | } 37 | // 38 | fmt.Printf("File %s read, byte count %d\n", file_name, n) 39 | // 40 | if e = f.Close(); e != nil { 41 | log.Fatalln("Close Error::", e.Error()) 42 | } 43 | // 44 | b, _ := pem.Decode(buff) 45 | fmt.Printf("Block Type is %s\n", b.Type) 46 | fmt.Printf("Block Size is %d(0x%x)\n", len(b.Bytes), len(b.Bytes)) 47 | fmt.Printf("Block Type is %s\n", b.Type) 48 | fmt.Printf("Block Headers are\n%q\n", b.Headers) 49 | fmt.Printf("Block:\n%s\n", hex.Dump(b.Bytes)) 50 | // 51 | c, e := x509.ParseCertificate(b.Bytes) 52 | if e != nil { 53 | log.Fatalln("Parse Error::", e.Error()) 54 | } 55 | // 56 | fmt.Printf("Cert Version: %d(0x%04x)\n", c.Version, c.Version) 57 | fmt.Printf("Cert Serial Number: %d(0x%x)\n", c.SerialNumber, c.SerialNumber) 58 | fmt.Printf("Cert Basic Constraints Valid: %v\n", c.BasicConstraintsValid) 59 | fmt.Printf("Cert IsCA: %v\n", c.IsCA) 60 | fmt.Printf("Cert Subject:\n%s\n", hex.Dump(c.RawSubject)) 61 | // 62 | fmt.Println("done.....") 63 | } 64 | -------------------------------------------------------------------------------- /stacktrace/.gitignore: -------------------------------------------------------------------------------- 1 | stacktrace 2 | stacktrace.exe 3 | 4 | -------------------------------------------------------------------------------- /stacktrace/stacktrace.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demo stack trace(s).package stacktrace 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "runtime/debug" 9 | "strings" 10 | ) 11 | 12 | func showStackTrace() { 13 | // Not very pretty, but ..... pretty useful at times. 14 | debug.PrintStack() 15 | } 16 | 17 | func showStackTrace2(sup int) { 18 | // Sligtly more pretty, but most of the time just as useful. 19 | // This could be embellished of course. 20 | s := string(debug.Stack()) 21 | ls := strings.SplitN(s, "\n", -1) 22 | for i := sup; i < len(ls); i++ { 23 | fmt.Printf("%s\n", strings.Trim(ls[i], " \t")) 24 | } 25 | } 26 | 27 | func sublevelb() { 28 | fmt.Println("sublevelb starts") 29 | fmt.Println("===============================================") 30 | showStackTrace() // One way 31 | fmt.Println("===============================================") 32 | // 5 seems like a good suppress number (from minimal experimentation) 33 | showStackTrace2(5) // Or another 34 | fmt.Println("sublevelb ends") 35 | } 36 | 37 | func sublevela() { 38 | fmt.Println("sublevela starts") 39 | sublevelb() 40 | fmt.Println("sublevela ends") 41 | } 42 | 43 | func main() { 44 | fmt.Println("hi") 45 | sublevela() 46 | fmt.Println("bye") 47 | } 48 | -------------------------------------------------------------------------------- /stomptest/.gitignore: -------------------------------------------------------------------------------- 1 | stomptest 2 | stomptest.exe 3 | -------------------------------------------------------------------------------- /stomptest/receiver1/.gitignore: -------------------------------------------------------------------------------- 1 | receiver1 2 | -------------------------------------------------------------------------------- /stomptest/receivernid/.gitignore: -------------------------------------------------------------------------------- 1 | receivernid 2 | -------------------------------------------------------------------------------- /stomptest/sender/.gitignore: -------------------------------------------------------------------------------- 1 | sender 2 | -------------------------------------------------------------------------------- /stomptest/sender/sender.go: -------------------------------------------------------------------------------- 1 | /* 2 | Send STOMP messages using https://github.com/gmallard/stompngo and a STOMP 3 | 1.1 broker. 4 | */ 5 | package main 6 | 7 | import ( 8 | "fmt" // 9 | "log" 10 | "net" 11 | "os" 12 | "runtime" 13 | "strconv" 14 | "sync" 15 | "time" 16 | 17 | "github.com/gmallard/stompngo" 18 | ) 19 | 20 | var wg sync.WaitGroup 21 | var printMsgs bool = true 22 | var nmsgs = 10 23 | var qname = "/queue/stompngo.srpub" 24 | var mq = 2 25 | var host = "localhost" 26 | var hap = host + ":" 27 | 28 | func sendMessages(c *stompngo.Connection, q string, n int, k int) { 29 | 30 | var error error 31 | 32 | // Send 33 | eh := stompngo.Headers{"destination", q} // Extra headers 34 | for i := 1; i <= n; i++ { 35 | m := q + " gostomp message #" + strconv.Itoa(i) 36 | if printMsgs { 37 | fmt.Println("msg:", m) 38 | } 39 | error = c.Send(eh, m) 40 | if error != nil { 41 | log.Fatal("send error: ", error) 42 | } 43 | // 44 | time.Sleep(1e9 / 100) // Simulate message build 45 | } 46 | 47 | error = c.Send(eh, "***EOF*** "+q) 48 | if error != nil { 49 | log.Fatal("send error: ", error) 50 | } 51 | wg.Done() 52 | 53 | } 54 | 55 | func main() { 56 | fmt.Println("Start...") 57 | 58 | // 59 | p := os.Getenv("STOMP_PORT") 60 | if p == "" { 61 | p = "61613" 62 | } 63 | nc, error := net.Dial("tcp", hap+p) 64 | if error != nil { 65 | log.Fatal(error) 66 | } 67 | 68 | // Connectionect 69 | ch := stompngo.Headers{"login", "putter", "passcode", "send1234", 70 | "accept-version", "1.2", "host", host} 71 | 72 | c, error := stompngo.Connect(nc, ch) 73 | if error != nil { 74 | log.Fatal(error) 75 | } 76 | 77 | for i := 1; i <= mq; i++ { 78 | qn := fmt.Sprintf("%d", i) 79 | wg.Add(1) 80 | go sendMessages(c, qname+qn, nmsgs, i) 81 | 82 | } 83 | wg.Wait() 84 | fmt.Println("done with wait") 85 | 86 | // Disconnect 87 | nh := stompngo.Headers{} 88 | error = c.Disconnect(nh) 89 | if error != nil { 90 | log.Fatal(error) 91 | } 92 | 93 | fmt.Println("done disconnect, start nc.Close()") 94 | nc.Close() 95 | 96 | fmt.Println("done nc.Close()") 97 | 98 | ngor := runtime.NumGoroutine() 99 | fmt.Printf("egor: %v\n", ngor) 100 | 101 | select { 102 | case v := <-c.MessageData: 103 | fmt.Printf("frame2: %v\n", v) 104 | default: 105 | fmt.Println("Nothing to show") 106 | } 107 | fmt.Println("End... mq:", mq, " nmsgs:", nmsgs) 108 | } 109 | -------------------------------------------------------------------------------- /stomptest/sendernid/.gitignore: -------------------------------------------------------------------------------- 1 | sendernid 2 | -------------------------------------------------------------------------------- /stomptest/sendrcv/.gitignore: -------------------------------------------------------------------------------- 1 | sendrcv 2 | -------------------------------------------------------------------------------- /stomptest/subrecv_examp/.gitignore: -------------------------------------------------------------------------------- 1 | subrecv_examp 2 | -------------------------------------------------------------------------------- /stringlens/.gitignore: -------------------------------------------------------------------------------- 1 | stringlens 2 | stringlens.exe 3 | -------------------------------------------------------------------------------- /stringlens/stringlens.go: -------------------------------------------------------------------------------- 1 | /* 2 | Experiment with string lengths and character sequences. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | 8 | func main() { 9 | fmt.Println("Start....") 10 | // 11 | astring := "A\n\u00ffÇ\u754c" // Some UTF-8 12 | fmt.Printf("AstringLen: %d\n", len(astring)) 13 | // 14 | b1 := astring[1] // a byte 15 | fmt.Printf("b1val: %v\n", b1) 16 | // 17 | for char_index, char := range astring { // All characters 18 | cstring := string(char) // Convert a character to a string 19 | fmt.Printf("CstringLen: %d\n", len(cstring)) // len = 1..4 bytes 20 | var cbytes = []uint8(cstring) // get the bytes 21 | // Info 22 | fmt.Printf("%d:%c: Byte Count=%d\n", char_index, char, len(cbytes)) 23 | } 24 | // 25 | fmt.Println() 26 | fmt.Println("End....") 27 | } 28 | -------------------------------------------------------------------------------- /strings_utils/.gitignore: -------------------------------------------------------------------------------- 1 | strings_utils 2 | strings_utils.exe 3 | -------------------------------------------------------------------------------- /strings_utils/strings_utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Experiments with utilities from package strings. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "strings" 9 | ) 10 | 11 | func showSplits() { 12 | astr := "abcd|def|ghij" 13 | fmt.Printf("Data: %s\n", astr) 14 | sseps := strings.Split(astr, "|") 15 | fmt.Printf("Seps Len: %d\n", len(sseps)) 16 | for _, sep_line := range sseps { 17 | fmt.Printf("SepLine: $%s$\n", sep_line) 18 | } 19 | fmt.Println() 20 | // 21 | astr = "abcd|def|ghij|" 22 | fmt.Printf("Data: $%s$\n", astr) 23 | sseps = strings.Split(astr, "|") 24 | fmt.Printf("Seps Len: %d\n", len(sseps)) 25 | for _, sep_line := range sseps { 26 | fmt.Printf("SepLine: $%s$\n", sep_line) 27 | } 28 | fmt.Println() 29 | // 30 | astr = "abcd|def|ghij" 31 | fmt.Printf("Data: $%s$\n", astr) 32 | sseps = strings.SplitAfter(astr, "|") 33 | fmt.Printf("Seps Len: %d\n", len(sseps)) 34 | for _, sep_line := range sseps { 35 | fmt.Printf("SepLine: $%s$\n", sep_line) 36 | } 37 | fmt.Println() 38 | // 39 | astr = "abcd|def|ghij|" 40 | fmt.Printf("Data: $%s$\n", astr) 41 | sseps = strings.SplitAfter(astr, "|") 42 | fmt.Printf("Seps Len: %d\n", len(sseps)) 43 | for _, sep_line := range sseps { 44 | fmt.Printf("SepLine: $%s$\n", sep_line) 45 | } 46 | fmt.Println() 47 | // 48 | astr = "abcd\ndef\nghij\n\ndata" 49 | fmt.Printf("Data: $%s$\n", astr) 50 | sseps = strings.Split(astr, "\n\n") 51 | fmt.Printf("Seps Len: %d\n", len(sseps)) 52 | for _, sep_line := range sseps { 53 | fmt.Printf("SepLine: $%s$\n", sep_line) 54 | } 55 | fmt.Println() 56 | } 57 | 58 | func main() { 59 | fmt.Println("Start....") 60 | // 61 | showSplits() 62 | // 63 | fmt.Println("End....") 64 | } 65 | -------------------------------------------------------------------------------- /struct/.gitignore: -------------------------------------------------------------------------------- 1 | struct 2 | struct.exe 3 | -------------------------------------------------------------------------------- /switch_demo/.gitignore: -------------------------------------------------------------------------------- 1 | switch_demo 2 | switch_demo.exe 3 | -------------------------------------------------------------------------------- /switch_demo/switch_demo.go: -------------------------------------------------------------------------------- 1 | /* 2 | A basic demonstration of the switch statement. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | ) 9 | 10 | func main() { 11 | fmt.Println("Start...") 12 | i := []int{1, 2, 3, 4, 42} 13 | for _, v := range i { 14 | switch v { 15 | case 1: 16 | fmt.Println("Is 1") 17 | case 2, 3: 18 | fmt.Println("Is 2 or 3") 19 | case 4: 20 | fmt.Println("Is 4") 21 | default: 22 | fmt.Println("Default", v) 23 | } 24 | } 25 | fmt.Println("End...") 26 | } 27 | -------------------------------------------------------------------------------- /symlshow/.gitignore: -------------------------------------------------------------------------------- 1 | symlshow 2 | symlshow.exe 3 | -------------------------------------------------------------------------------- /symlshow/symlshow.go: -------------------------------------------------------------------------------- 1 | /* 2 | Test if a path is a symbolic link. 3 | */ 4 | package main 5 | 6 | // Show if a given path is actually a symbolic link 7 | 8 | import ( 9 | "fmt" 10 | "os" 11 | "path/filepath" 12 | ) 13 | 14 | func main() { 15 | fmt.Println(os.Args[1]) 16 | p, e := filepath.EvalSymlinks(os.Args[1]) 17 | if e != nil { 18 | fmt.Println("Error:", e) 19 | os.Exit(2) 20 | } 21 | fmt.Println(p) 22 | fmt.Printf("SYMBOLIC=%v\n", os.Args[1] != p) 23 | } 24 | -------------------------------------------------------------------------------- /symltest/.gitignore: -------------------------------------------------------------------------------- 1 | symltest 2 | symltest.exe 3 | -------------------------------------------------------------------------------- /symltest/symltest.go: -------------------------------------------------------------------------------- 1 | /* 2 | More symbolic link fun. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "os" // 9 | ) 10 | 11 | // Symbolic link gotcha's 12 | 13 | func main() { 14 | fmt.Println("Start...") 15 | goroot := os.Getenv("GOROOT") 16 | // In my environment: 17 | // GOROOT=/home/gmallard/hext/go 18 | // The 'hext' part is actually a symbolic link -> /ad2/gma/home_ext 19 | fmt.Printf("GOROOT=%s\n", goroot) 20 | if err := os.Chdir(goroot); err != nil { 21 | fmt.Println("chdir error", err) 22 | os.Exit(1) 23 | } 24 | // Note: Getwd documentation says if path is reachable multiple ways, 25 | // _any_ of the ways could be returned. Try it. 26 | cwd, err := os.Getwd() 27 | if err != nil { 28 | fmt.Println("getwd error", err) 29 | os.Exit(1) 30 | } 31 | // And in my particular case, this shows: 32 | // CWD=/ad2/gma/home_ext/go 33 | fmt.Printf("CWD=%s\n", cwd) 34 | fmt.Println("End...") 35 | } 36 | -------------------------------------------------------------------------------- /tcp01/.gitignore: -------------------------------------------------------------------------------- 1 | tcp01 2 | tcp01.exe 3 | -------------------------------------------------------------------------------- /tcp02/.gitignore: -------------------------------------------------------------------------------- 1 | tcp02 2 | tcp02.exe 3 | -------------------------------------------------------------------------------- /tcp02/tcp02.go: -------------------------------------------------------------------------------- 1 | /* 2 | A simple TCP reader server, with system controlled read timeout. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "net" 9 | ) 10 | 11 | // This example will timeout only after a TCP default amount of time: system 12 | // dependent. To stop, kill with ^C. 13 | // 'Tested' using 'telnet localhost 45678' 14 | func main() { 15 | fmt.Println("Start .....") 16 | // 17 | // Get a TCP Address 18 | // 19 | tcpAddress, err := net.ResolveTCPAddr("", "localhost:45678") 20 | if err != nil { 21 | fmt.Printf("Error = %v\n", err) 22 | panic("wtf01") 23 | } 24 | fmt.Printf("tcpAddress = %v\n", tcpAddress) 25 | // 26 | // Get a TCP Listener 27 | // 28 | listener, err := net.ListenTCP("tcp", tcpAddress) 29 | if err != nil { 30 | fmt.Printf("Error = %v\n", err) 31 | panic("wtf02") 32 | } 33 | fmt.Printf("listener = %v\n", listener) 34 | // 35 | // Accept a connection. 36 | // 37 | tcpConn, err := listener.AcceptTCP() 38 | if err != nil { 39 | fmt.Printf("Error = %v\n", err) 40 | panic("wtf03") 41 | } 42 | fmt.Printf("connection = %v\n", tcpConn) 43 | // 44 | for { 45 | var buffer = make([]byte, 256) 46 | bytesRead, err := tcpConn.Read(buffer) 47 | if err != nil { 48 | fmt.Printf("Error = %v\n", err) 49 | break 50 | } 51 | // 52 | fmt.Println("Bytes Read", bytesRead) 53 | bufData := buffer[0:bytesRead] 54 | fmt.Println("Buffer", bufData) 55 | var data = string(bufData) 56 | fmt.Println("Data Read", data) 57 | } 58 | // 59 | err = tcpConn.Close() 60 | if err != nil { 61 | fmt.Printf("Error = %v\n", err) 62 | panic("wtf05") 63 | } 64 | // 65 | err = listener.Close() 66 | if err != nil { 67 | fmt.Printf("Error = %v\n", err) 68 | panic("wtf06") 69 | } 70 | // 71 | fmt.Println("End .....") 72 | } 73 | -------------------------------------------------------------------------------- /tcp03/.gitignore: -------------------------------------------------------------------------------- 1 | tcp03 2 | tcp03.exe 3 | -------------------------------------------------------------------------------- /tcp03/tcp03.go: -------------------------------------------------------------------------------- 1 | /* 2 | A simple TCP reader, with shutdown capability. 3 | */ 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "net" 10 | "strings" 11 | ) 12 | 13 | // Demo reading from a goroutine, and waiting on completion. 14 | // 'Tested' using 'telnet localhost 45678' 15 | func getData(tcpConn *net.TCPConn, done chan bool) { 16 | for { 17 | var buffer = make([]byte, 256) 18 | bytesRead, err := tcpConn.Read(buffer) 19 | if err != nil { 20 | fmt.Printf("Error = %v\n", err) 21 | break 22 | } 23 | // 24 | fmt.Println("Bytes Read", bytesRead) 25 | bufData := buffer[0:bytesRead] 26 | fmt.Println("Buffer", bufData) 27 | var data = string(bufData) 28 | fmt.Println("Data Read", data) 29 | // 30 | if strings.HasPrefix(data, "quit") { 31 | break 32 | } 33 | } 34 | // 35 | err := tcpConn.Close() 36 | if err != nil { 37 | fmt.Printf("Error = %v\n", err) 38 | panic("wtf05") 39 | } 40 | // 41 | done <- true 42 | } 43 | 44 | func main() { 45 | fmt.Println("Start .....") 46 | // 47 | // Get a TCP Address 48 | // 49 | tcpAddress, err := net.ResolveTCPAddr("", "localhost:45678") 50 | if err != nil { 51 | fmt.Printf("Error = %v\n", err) 52 | panic("wtf01") 53 | } 54 | fmt.Printf("tcpAddress = %v\n", tcpAddress) 55 | // 56 | // Get a TCP Listener 57 | // 58 | listener, err := net.ListenTCP("tcp", tcpAddress) 59 | if err != nil { 60 | fmt.Printf("Error = %v\n", err) 61 | panic("wtf02") 62 | } 63 | fmt.Printf("listener = %v\n", listener) 64 | // 65 | // Accept a connection. 66 | // 67 | tcpConn, err := listener.AcceptTCP() 68 | if err != nil { 69 | fmt.Printf("Error = %v\n", err) 70 | panic("wtf03") 71 | } 72 | fmt.Printf("connection = %v\n", tcpConn) 73 | waitFor := make(chan bool) 74 | go getData(tcpConn, waitFor) 75 | <-waitFor 76 | // 77 | err = listener.Close() 78 | if err != nil { 79 | fmt.Printf("Error = %v\n", err) 80 | panic("wtf06") 81 | } 82 | // 83 | fmt.Println("End .....") 84 | } 85 | -------------------------------------------------------------------------------- /tcp04/.gitignore: -------------------------------------------------------------------------------- 1 | tcp04 2 | tcp04.exe 3 | -------------------------------------------------------------------------------- /tcp04/tcp04.go: -------------------------------------------------------------------------------- 1 | /* 2 | How not to use go routines for reading. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "net" 9 | "strings" 10 | ) 11 | 12 | // Demo goroutine start, but main goroutine exit, which kills the connection. 13 | // Not useful, but indicates how connections work. 14 | // 'Tested' using 'telnet localhost 45678' 15 | func getData(tcpConn *net.TCPConn, done chan bool) { 16 | for { 17 | var buffer = make([]byte, 256) 18 | fmt.Println("Starting Read ...") 19 | bytesRead, err := tcpConn.Read(buffer) 20 | if err != nil { 21 | fmt.Printf("Error = %v\n", err) 22 | break 23 | } 24 | // 25 | fmt.Println("Bytes Read", tcpConn, bytesRead) 26 | bufData := buffer[0:bytesRead] 27 | fmt.Println("Buffer", tcpConn, bufData) 28 | var data = string(bufData) 29 | fmt.Println("Data Read", tcpConn, data) 30 | // 31 | if strings.HasPrefix(data, "quit") { 32 | break 33 | } 34 | } 35 | // 36 | fmt.Println("Starting Close() 1") 37 | err := tcpConn.Close() 38 | if err != nil { 39 | fmt.Printf("Error = %v\n", err) 40 | panic("wtf05") 41 | } 42 | // 43 | done <- true 44 | } 45 | 46 | func main() { 47 | fmt.Println("Start .....") 48 | // 49 | // Get a TCP Address 50 | // 51 | tcpAddress, err := net.ResolveTCPAddr("", "localhost:45678") 52 | if err != nil { 53 | fmt.Printf("Error = %v\n", err) 54 | panic("wtf01") 55 | } 56 | fmt.Printf("tcpAddress = %v\n", tcpAddress) 57 | // 58 | // Get a TCP Listener 59 | // 60 | listener, err := net.ListenTCP("tcp", tcpAddress) 61 | if err != nil { 62 | fmt.Printf("Error = %v\n", err) 63 | panic("wtf02") 64 | } 65 | fmt.Printf("listener = %v\n", listener) 66 | // 67 | // Accept connections. 68 | // 69 | tcpConn, err := listener.AcceptTCP() 70 | if err != nil { 71 | fmt.Printf("Error = %v\n", err) 72 | panic("wtf03") 73 | } 74 | fmt.Printf("connection = %v\n", tcpConn) 75 | waitFor := make(chan bool) 76 | go getData(tcpConn, waitFor) 77 | // Do not wait ...... 78 | // <- waitFor 79 | // 80 | fmt.Println("Starting Close() 2") 81 | err = listener.Close() 82 | if err != nil { 83 | fmt.Printf("Error = %v\n", err) 84 | panic("wtf06") 85 | } 86 | // 87 | fmt.Println("End .....") 88 | } 89 | -------------------------------------------------------------------------------- /tcp05/.gitignore: -------------------------------------------------------------------------------- 1 | tcp05 2 | tcp05.exe 3 | -------------------------------------------------------------------------------- /tcp05/tcp05.go: -------------------------------------------------------------------------------- 1 | /* 2 | TCP demonstration, multiple clients using go routines. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "net" 9 | "strings" 10 | ) 11 | 12 | // Demo multiple echo clients. 13 | // 'Test' using 'telnet localhost 45678' from multiple open terminals. 14 | func getData(c *net.TCPConn) { 15 | var buffer = make([]byte, 4096) 16 | for { 17 | fmt.Println(c, "Starting Read ...") 18 | bytesRead, err := c.Read(buffer) 19 | if err != nil { 20 | fmt.Printf("Error = %v\n", err) 21 | break 22 | } 23 | // 24 | fmt.Println(c, "Bytes Read", bytesRead) 25 | bufData := buffer[0:bytesRead] 26 | fmt.Println(c, "Raw Buffer", bufData) 27 | var data = string(bufData) 28 | fmt.Println(c, "Data Read", data) 29 | // 30 | s := "Echo: " + data 31 | if _, err := c.Write([]byte(s)); err != nil { 32 | fmt.Printf("Error = %v\n", err) 33 | panic("wtfwr01") 34 | } 35 | // 36 | if strings.HasPrefix(data, "quit") { 37 | break 38 | } 39 | } 40 | // 41 | fmt.Println(c, "Starting Close() 1") 42 | err := c.Close() 43 | if err != nil { 44 | fmt.Printf("Error = %v\n", err) 45 | panic("wtf05") 46 | } 47 | // 48 | } 49 | 50 | func main() { 51 | fmt.Println("Start .....") 52 | // 53 | // Get a TCP Address 54 | // 55 | a, err := net.ResolveTCPAddr("", "localhost:45678") 56 | if err != nil { 57 | fmt.Printf("Error = %v\n", err) 58 | panic("wtf01") 59 | } 60 | fmt.Printf("a = %v\n", a) 61 | // 62 | // Get a TCP Listener 63 | // 64 | l, err := net.ListenTCP("tcp", a) 65 | if err != nil { 66 | fmt.Printf("Error = %v\n", err) 67 | panic("wtf02") 68 | } 69 | fmt.Printf("l = %v\n", l) 70 | // 71 | // Accept any number of connections. 72 | // 73 | for { 74 | c, err := l.AcceptTCP() 75 | if err != nil { 76 | fmt.Printf("Error = %v\n", err) 77 | panic("wtf03") 78 | } 79 | fmt.Printf("New Connection = %v\n", c) 80 | go getData(c) 81 | } 82 | // 83 | fmt.Println("Starting Close() 2") 84 | err = l.Close() 85 | if err != nil { 86 | fmt.Printf("Error = %v\n", err) 87 | panic("wtf06") 88 | } 89 | // 90 | fmt.Println("End .....") 91 | } 92 | -------------------------------------------------------------------------------- /tcp06/.gitignore: -------------------------------------------------------------------------------- 1 | tcp06 2 | tcp06.exe 3 | -------------------------------------------------------------------------------- /testgreek/.gitignore: -------------------------------------------------------------------------------- 1 | testgreek 2 | testgreek.exe 3 | -------------------------------------------------------------------------------- /testgreek/testgreek.go: -------------------------------------------------------------------------------- 1 | /* 2 | Show using UTF-8 in source code. 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | func main() { 11 | Π := 25.14159 12 | fmt.Println("Π is *NOW*", Π, "the universe is changing") 13 | } 14 | -------------------------------------------------------------------------------- /testppack/.gitignore: -------------------------------------------------------------------------------- 1 | testppack 2 | testppack.exe 3 | -------------------------------------------------------------------------------- /testppack/testppack.go: -------------------------------------------------------------------------------- 1 | /* 2 | Test using the numbers package. 3 | */ 4 | package main 5 | 6 | // 7 | import ( 8 | "fmt" 9 | "github.com/gmallard/go-samp/numbers" 10 | ) 11 | 12 | /* 13 | Note: numbers is a locally built package, not part of the 'go' 14 | distribution. 15 | */ 16 | func main() { 17 | v := numbers.Double(6) 18 | fmt.Printf("6 doubled: %d\n", v) 19 | } 20 | -------------------------------------------------------------------------------- /type_String/.gitignore: -------------------------------------------------------------------------------- 1 | type_String 2 | type_String.exe 3 | -------------------------------------------------------------------------------- /type_String/type_String.go: -------------------------------------------------------------------------------- 1 | /* 2 | An interesting demo of types and methods. 3 | */ 4 | package main 5 | 6 | // 7 | // Methods are not just for structs. They can be 8 | // defined for any (non-pointer) type. 9 | // 10 | // The type must be defined in your package though. 11 | // 12 | // You can't write a method for int but you can 13 | // declare a new int type and give it methods. 14 | // 15 | // fmt.Print?? responds to String() 16 | // 17 | import "fmt" 18 | 19 | type Day int 20 | 21 | var dayName = []string{ 22 | "Sunday", "Monday", "Tuesday", "Wednesday", 23 | "Thursday", "Friday", "Saturday", 24 | } 25 | 26 | func (day Day) String() string { 27 | return dayName[day] 28 | } 29 | 30 | const ( 31 | Sunday Day = iota 32 | Monday 33 | Tuesday 34 | Wednesday 35 | Thursday 36 | Friday 37 | Saturday 38 | ) 39 | 40 | func main() { 41 | fmt.Println("Start .....") 42 | // 43 | var day = Tuesday 44 | fmt.Print(day.String()) 45 | fmt.Println() 46 | fmt.Println(0, Sunday, 1, Monday) 47 | fmt.Println("End .....") 48 | } 49 | -------------------------------------------------------------------------------- /unicloup/.gitignore: -------------------------------------------------------------------------------- 1 | unicloup 2 | unicloup.exe 3 | -------------------------------------------------------------------------------- /unicloup/unicloup.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate UTF-8 oddities with characters "σ" and "ς". 3 | */ 4 | package main 5 | 6 | import ( 7 | "fmt" // 8 | "strings" 9 | ) 10 | 11 | // 12 | // An interesting exercise with UTF-8 and the concepts of upper/lower case. 13 | // Triggered by this discussion: 14 | // http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/#6163129 15 | // 16 | // I also experimented with this using Ruby 1.9.3, the current tip of trunk. 17 | // Ruby seems to handle this even less gracefully than go does, although 18 | // the Ruby documentation clearly says: String#upcase and String#downcase 19 | // operate on the 'ASCII range' only. Thus, the code: 20 | // "σ".upcase 21 | // does absolutely nothing. 22 | // 23 | // There is an interesting presentation on Unicode work by the PHP development 24 | // team here: 25 | // http://www.slideshare.net/andreizm/the-good-the-bad-and-the-ugly-what-happened-to-unicode-and-php-6 26 | // One of the interesting slides is number 53 where an example showing "Σ" 27 | // being 'lower case' converted to either "σ" or "ς". The example shown is: 28 | // $str = strtolower("ΣΕΛΛΑΣ") // result is: σελλάς 29 | // Two questions are triggered: 30 | // a) Why is lower case alpha with oxia chosen instead of merely lower case alpha? 31 | // b) For lower case of Σ, how is the distinction between σ and ς made? 32 | // The general conclusions of the slide deck are however, discouraging: the 33 | // PHP Unicode project has apparently been abandoned. 34 | // 35 | func main() { 36 | fmt.Println("Start...") 37 | 38 | // Lower case sigma 39 | lowsig := "σ" 40 | fmt.Printf("Low Sig: %s\n", lowsig) 41 | 42 | // Lower case C with cedilla 43 | lowceeced := "ς" 44 | fmt.Printf("Low Cee Ced: %s\n", lowceeced) 45 | 46 | // Upper case sigma 47 | hisig := "Σ" 48 | fmt.Printf("High Sig: %s\n", hisig) 49 | 50 | // Lower case sigma to upper 51 | fmt.Printf("Toupper Sig: %s\n", strings.ToUpper(lowsig)) 52 | 53 | // Lower case C cedilla to upper 54 | fmt.Printf("Toupper Cee Ced: %s\n", strings.ToUpper(lowceeced)) 55 | 56 | // Upper case sigma to lower 57 | fmt.Printf("Tolower Cee: %s\n", strings.ToLower(hisig)) 58 | 59 | // The PHP example: 60 | forgrins := "ΣΕΛΛΑΣ" 61 | fmt.Printf("forgrins upper: %s forgrins lower %s\n", forgrins, strings.ToLower(forgrins)) 62 | 63 | fmt.Println("End...") 64 | } 65 | -------------------------------------------------------------------------------- /unicode_what/.gitignore: -------------------------------------------------------------------------------- 1 | unicode_what 2 | unicode_what.exe 3 | -------------------------------------------------------------------------------- /unicode_what/unicode_what.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demonstrate UTF-8 oddities with characters "σ" and "ς". 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | import "strings" 8 | 9 | func main() { 10 | // The Greek Alphabet in Upper Case 11 | g := "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ" 12 | fmt.Println(g) 13 | fmt.Println() 14 | fmt.Println(strings.ToLower(g)) 15 | fmt.Println() 16 | 17 | // But what about the ς versus σ thing? 18 | v := "ς" 19 | fmt.Println("c-cedilla", v) 20 | fmt.Println("c-cedilla UPPER", strings.ToUpper(v)) 21 | fmt.Println("c-cedilla flip", strings.ToLower(strings.ToUpper(v))) 22 | // 23 | v = "σ" 24 | fmt.Println("sigma", v) 25 | fmt.Println("sigma UPPER", strings.ToUpper(v)) 26 | fmt.Println("sigma flip", strings.ToLower(strings.ToUpper(v))) 27 | 28 | fmt.Println() 29 | 30 | // But what about the Ç versus σ thing? 31 | // Is Ç really like ς ???? 32 | v = "Ç" 33 | fmt.Println("c-cedillau", v) 34 | fmt.Println("c-cedillau UPPER", strings.ToUpper(v)) 35 | fmt.Println("c-cedillau flip", strings.ToLower(strings.ToUpper(v))) 36 | // 37 | v = "σ" 38 | fmt.Println("sigmau", v) 39 | fmt.Println("sigmau UPPER", strings.ToUpper(v)) 40 | fmt.Println("sigmau flip", strings.ToLower(strings.ToUpper(v))) 41 | 42 | } 43 | -------------------------------------------------------------------------------- /uniques/.gitignore: -------------------------------------------------------------------------------- 1 | uniques 2 | uniques.exe 3 | -------------------------------------------------------------------------------- /uniques/uniques.go: -------------------------------------------------------------------------------- 1 | /* 2 | Generate long sequences of unique values. 3 | */ 4 | package main 5 | 6 | import ( 7 | "crypto/sha1" 8 | "fmt" // 9 | "math/rand" 10 | "net" 11 | "time" 12 | ) 13 | 14 | func getAllMacs() (result string, error error) { 15 | result = "" 16 | error = nil 17 | // 18 | ifaces, error := net.Interfaces() 19 | if error != nil { 20 | return 21 | } 22 | for _, face := range ifaces { 23 | // 24 | result += (face.HardwareAddr.String() + "~") 25 | } 26 | // 27 | return 28 | } 29 | 30 | func main() { 31 | // fmt.Println("Start...") 32 | a, e := getAllMacs() 33 | if e != nil { 34 | panic("allmacs error") 35 | } 36 | // fmt.Printf("%s\n", a) 37 | 38 | // Test with: 39 | // ./uniques | sort | uniq | wc -l 40 | 41 | maxi := 1000000 // one million 42 | maxi *= 100 // one hundread million, this will run for a while ...... 43 | 44 | for i := 1; i <= maxi; i++ { 45 | n := fmt.Sprintf("%d", time.Now().UnixNano()) 46 | r := fmt.Sprintf("%d", rand.Int63()) 47 | s := sha1.New() 48 | t := a + "|" + n + "|" + r 49 | s.Write([]byte(t)) 50 | v := fmt.Sprintf("%x", s.Sum(nil)) 51 | // 52 | fmt.Printf("%s\n", v) 53 | } 54 | // fmt.Println("End...") 55 | } 56 | -------------------------------------------------------------------------------- /urlshow/.gitignore: -------------------------------------------------------------------------------- 1 | urlshow 2 | urlshow.exe 3 | -------------------------------------------------------------------------------- /utfconv/.gitignore: -------------------------------------------------------------------------------- 1 | utfconv 2 | utfconv.exe 3 | -------------------------------------------------------------------------------- /utfconv/utfconv.go: -------------------------------------------------------------------------------- 1 | /* 2 | Convert ISO-8859-15 to UTF-8. 3 | */ 4 | package main 5 | 6 | // This came from: 7 | // 8 | // http://groups.google.com/group/golang-nuts/browse_thread/thread/9e42a38620625a26 9 | // 10 | // as a way to convert ISO-8859-15 to UTF-8, ..... 11 | // 12 | import "fmt" 13 | 14 | // ISO-8859-15 to UTF-8 15 | func ISO885915ToUTF8(c []byte) string { 16 | 17 | // http://unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT 03-Mar-2004 14:06 18 | 19 | u := make([]rune, len(c)) 20 | for i := 0; i < len(u); i++ { 21 | r := rune(c[i]) 22 | if r >= 0x80 { 23 | switch r { 24 | case 0xA4: 25 | r = 0x20AC // EURO SIGN 26 | case 0xA6: 27 | r = 0x0160 // LATIN CAPITAL LETTER S WITH CARON 28 | case 0xA8: 29 | r = 0x0161 // LATIN SMALL LETTER S WITH CARON 30 | case 0xB4: 31 | r = 0x017D // LATIN CAPITAL LETTER Z WITH CARON 32 | case 0xB8: 33 | r = 0x017E // LATIN SMALL LETTER Z WITH CARON 34 | case 0xBC: 35 | r = 0x0152 // LATIN CAPITAL LIGATURE OE 36 | case 0xBD: 37 | r = 0x0153 // LATIN SMALL LIGATURE OE 38 | case 0xBE: 39 | r = 0x0178 // LATIN CAPITAL LETTER Y WITH DIAERESIS 40 | } 41 | } 42 | u[i] = r 43 | } 44 | return string(u) 45 | 46 | } 47 | 48 | func main() { 49 | c := []byte{'0', 'A', 'a', 0xA4, 0xA6, 0xA8, 0xB4, 0xB8, 0xBC, 0xBD, 0xBE} 50 | s := ISO885915ToUTF8(c) 51 | fmt.Println(s) 52 | for _, cv := range s { 53 | fmt.Printf("%x ", cv) 54 | } 55 | fmt.Println() 56 | // 57 | fmt.Printf("%s\n", string(0xC0)) // Sanity check. Is this really valid UTF-8? 58 | } 59 | -------------------------------------------------------------------------------- /walker/.gitignore: -------------------------------------------------------------------------------- 1 | walker 2 | walker.exe 3 | -------------------------------------------------------------------------------- /walker/walker.go: -------------------------------------------------------------------------------- 1 | /* 2 | Demo filepath Walk 3 | */ 4 | 5 | package main 6 | 7 | import ( 8 | "log" 9 | "os" 10 | "path/filepath" 11 | ) 12 | 13 | var ( 14 | fc = 0 15 | dc = 0 16 | ) 17 | 18 | func main() { 19 | walkbase := os.Getenv("WALKDIR") // Supply your own start subdirectoy here 20 | e := os.Chdir(walkbase) 21 | if e != nil { 22 | log.Fatalln("Chdir error:", e) 23 | } 24 | fdn, e := os.Getwd() 25 | if e != nil { 26 | log.Fatalln("Getwd error:", e) 27 | } 28 | log.Printf("Top Fitrvtory:%s\n", fdn) 29 | err := filepath.Walk(fdn, myWalker) 30 | if err != nil { 31 | log.Fatalln("MAIN ERROR:", err) 32 | } 33 | log.Println("Dir Count", dc) 34 | log.Println("File Count", fc) 35 | } 36 | 37 | /* 38 | Using *this* technique from the standard library, it does not seem 39 | possible to walk a directory structure looking for full path names. 40 | I can not figure out how to push/pop subdirectory names using 41 | this technique. 42 | */ 43 | func myWalker(path string, info os.FileInfo, err error) error { 44 | if err != nil { 45 | log.Printf("%s %v\n", "Walker Error: ", err) 46 | return nil 47 | } 48 | // 49 | if info.IsDir() { 50 | log.Println("Directory:", info.Name()) 51 | dc++ 52 | } else { 53 | log.Println("File:", info.Name()) 54 | fc++ 55 | } 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /xmlshow01/.gitignore: -------------------------------------------------------------------------------- 1 | xmlshow01 2 | xmlshow01.exe 3 | -------------------------------------------------------------------------------- /xmlshow01/data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Where are we? 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /xmlshow01/data2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Is not at home. 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /xmlshow01/xmlshow01.go: -------------------------------------------------------------------------------- 1 | /* 2 | Reading XML. An initial demonstration. 3 | */ 4 | package main 5 | 6 | import ( 7 | "bufio" 8 | "encoding/xml" 9 | "flag" 10 | "fmt" 11 | "io/ioutil" 12 | "os" 13 | "strings" 14 | ) 15 | 16 | // Flags 17 | var ( 18 | fileName string 19 | ) 20 | 21 | type Area51 struct { 22 | Location string `xml:"location,attr"` 23 | Password string `xml:"password,attr"` 24 | Data string `xml:",chardata"` 25 | } 26 | 27 | type Configs struct { 28 | XMLName xml.Name `xml:"configs"` 29 | Car54 string `xml:"car54"` 30 | Area51 Area51 `xml:"area51"` 31 | } 32 | 33 | var buff []byte // File data 34 | 35 | // Main initialization, a convenient place to set flags up 36 | func init() { 37 | flag.StringVar(&fileName, "fileName", "./data.xml", "xml file name") // This example uses the default 38 | } 39 | 40 | /* 41 | Loads file contents to the 'buff' slice. 42 | */ 43 | func loadFile() { 44 | f, err := os.OpenFile(fileName, os.O_RDONLY, 0644) 45 | if err != nil { 46 | fmt.Printf("\nOpen Error => %s\n\n", err) 47 | os.Exit(1) 48 | } 49 | 50 | // Load the entire file to the 'buff' slice 51 | reader := bufio.NewReader(f) // Buffered reader 52 | buff, err = ioutil.ReadAll(reader) 53 | if err != nil { 54 | fmt.Printf("\nReadAll Error => %s\n\n", err) 55 | os.Exit(1) 56 | } 57 | 58 | // Close 59 | err = f.Close() 60 | if err != nil { 61 | fmt.Printf("\nClose Error => %s\n\n", err) 62 | os.Exit(1) 63 | } 64 | } 65 | 66 | func showXml() { 67 | ctx := Configs{} 68 | err := xml.Unmarshal(buff, &ctx) 69 | if err != nil { 70 | fmt.Printf("error: %v", err) 71 | return 72 | } 73 | fmt.Printf("Configs: %+v\n", ctx) 74 | // The main element name 75 | fmt.Printf("XMLName: %#v\n", ctx.XMLName) 76 | // Trim, because there will usually be leading and maybe trailing whitespace 77 | fmt.Printf("Car54: %q\n", strings.TrimSpace(ctx.Car54)) 78 | fmt.Printf("Location: %q\n", ctx.Area51.Location) 79 | fmt.Printf("Password: %q\n", ctx.Area51.Password) 80 | fmt.Printf("Area51: %q\n", strings.TrimSpace(ctx.Area51.Data)) 81 | } 82 | 83 | func main() { 84 | // Hi! 85 | fmt.Println("Start...") 86 | // Flag handling. 87 | flag.Parse() // Parse all flags 88 | fmt.Println("fileName", fileName) 89 | 90 | // Load the entire file 91 | loadFile() 92 | 93 | // Display struct values from the XML 94 | showXml() 95 | 96 | // Bye! 97 | fmt.Println("End...") 98 | } 99 | -------------------------------------------------------------------------------- /xmlshow02/.gitignore: -------------------------------------------------------------------------------- 1 | xmlshow02 2 | xmlshow02.exe 3 | -------------------------------------------------------------------------------- /xmlshow02/xmlshow02.go: -------------------------------------------------------------------------------- 1 | /* 2 | Reading XML. A second demonstration. 3 | */ 4 | package main 5 | 6 | import ( 7 | "encoding/xml" 8 | "fmt" 9 | "time" 10 | ) 11 | 12 | // Superficially similar to the problem described at the link below: 13 | // 14 | // http://code.google.com/p/go/issues/detail?id=3688 15 | // 16 | 17 | type Bookings struct { 18 | From time.Time `xml:"from,attr"` 19 | Location string `xml:"location,attr"` 20 | } 21 | 22 | type Configs struct { 23 | XMLName xml.Name `xml:"root"` 24 | Login string `xml:"login"` 25 | Password string `xml:"password"` 26 | Bookings Bookings `xml:"getBookings"` 27 | } 28 | 29 | var buff []byte // File data 30 | 31 | var Xdata = ` 32 | 33 | test 34 | password 35 | 36 | ` 37 | 38 | func showXml() { 39 | ctx := Configs{} 40 | err := xml.Unmarshal(buff, &ctx) 41 | if err != nil { 42 | fmt.Printf("unmarshal error: %v", err) 43 | return 44 | } 45 | fmt.Printf("Configs: %+v\n", ctx) 46 | // 47 | m, err := xml.MarshalIndent(ctx, "", "\t") 48 | if err != nil { 49 | fmt.Printf("marshal error: %v", err) 50 | return 51 | } 52 | fmt.Println() 53 | fmt.Println("same?", string(m) == string(buff)) 54 | fmt.Println() 55 | fmt.Println("strdatam:", string(m)) 56 | fmt.Println() 57 | fmt.Println("bytedatam:", m, "len:", len(m)) 58 | fmt.Println() 59 | fmt.Println("strdatab:", string(buff)) 60 | fmt.Println() 61 | fmt.Println("bytedatab:", buff, "len:", len(buff)) 62 | } 63 | 64 | func main() { 65 | 66 | buff = []byte(Xdata) 67 | showXml() 68 | 69 | } 70 | -------------------------------------------------------------------------------- /xmlshow03/.gitignore: -------------------------------------------------------------------------------- 1 | xmlshow03 2 | xmlshow03.exe 3 | -------------------------------------------------------------------------------- /xmlshow03/data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ford 5 | 6 | 7 | Chevy 8 | 9 | 10 | Dodge 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /xmlshow03/xmlshow03.go: -------------------------------------------------------------------------------- 1 | /* 2 | Reading XML. Demonstrate load to a slice. 3 | */ 4 | package main 5 | 6 | import "fmt" 7 | import "encoding/xml" 8 | 9 | var data string = ` 10 | 11 | 12 | tcp://0.0.0.0:1234 13 | 14 | 15 | tls://127.0.0.1:7654?a=b 16 | 17 |
18 | ` 19 | 20 | type Transport struct { 21 | Uri string `xml:"uri"` 22 | } 23 | 24 | type Table struct { 25 | XMLName xml.Name `xml:"table"` 26 | Transports []Transport `xml:"transport"` 27 | } 28 | 29 | func main() { 30 | var table Table 31 | err := xml.Unmarshal([]byte(data), &table) 32 | 33 | if err != nil { 34 | fmt.Println(err) 35 | } 36 | 37 | fmt.Println(table) 38 | fmt.Println("1", table.Transports[0].Uri) 39 | fmt.Println("2", table.Transports[1].Uri) 40 | } 41 | -------------------------------------------------------------------------------- /xmlshow04/.gitignore: -------------------------------------------------------------------------------- 1 | xmlshow04 2 | xmlshow04.exe 3 | -------------------------------------------------------------------------------- /xmlshow04/xmlshow04.go: -------------------------------------------------------------------------------- 1 | /* 2 | Reading XML. Demonstrate recursive elements. 3 | */ 4 | package main 5 | 6 | import ( 7 | "encoding/xml" 8 | "fmt" 9 | "log" 10 | ) 11 | 12 | var data string = ` 13 | 14 | 0 15 | 0 16 | 4 17 | 18 | Inside One 19 | 2 20 | 0 21 | 2 22 | 23 | Inside Two 24 | 1 25 | 0 26 | 1 27 | 28 | 29 | 30 | ` 31 | 32 | type Circle struct { 33 | XMLName xml.Name `xml:"circle"` 34 | Comment string `xml:"comment"` 35 | Xcoord int `xml:"xcoord"` 36 | Ycoord int `xml:"ycoord"` 37 | Radius int `xml:"radius"` 38 | Circle *Circle 39 | } 40 | 41 | func main() { 42 | var circle Circle 43 | err := xml.Unmarshal([]byte(data), &circle) 44 | if err != nil { 45 | log.Fatalf("Unmarshal ERROR: [%v]\n", err) 46 | } 47 | // fmt.Printf("Circle Data: [%q]\n", circle) 48 | fmt.Println("=============================") 49 | dumpData(&circle, "The Outside Circle") 50 | } 51 | 52 | func dumpData(c *Circle, id string) { 53 | fmt.Printf("A Circle (%s):\n", id) 54 | if c.Comment != "" { 55 | fmt.Printf("\tComment: %s\n", c.Comment) 56 | } 57 | fmt.Printf("\tX coordinate: %d\n", c.Xcoord) 58 | fmt.Printf("\tY coordinate: %d\n", c.Ycoord) 59 | fmt.Printf("\tRadius: %d\n", c.Radius) 60 | // 61 | if c.Circle != nil { 62 | dumpData(c.Circle, "Next Inner Circle") 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /zip_test/.gitignore: -------------------------------------------------------------------------------- 1 | zip_test 2 | zip_test.exe 3 | -------------------------------------------------------------------------------- /zip_test/testdata/testa.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/zip_test/testdata/testa.jar -------------------------------------------------------------------------------- /zip_test/testdata/testfile.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gmallard/go-samp/cc56c4e1cc41f91fc3c99e5a06c735e097339c10/zip_test/testdata/testfile.zip -------------------------------------------------------------------------------- /zip_test/ziptest.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "archive/zip" 5 | "os" 6 | // "fmt" 7 | "log" 8 | "time" 9 | ) 10 | 11 | var ( 12 | pref = "zip_test " 13 | zfl = []string{"testdata/testfile.zip", 14 | "testdata/testa.jar", 15 | } 16 | 17 | alog *log.Logger 18 | ) 19 | 20 | func init() { 21 | alog = log.New(os.Stdout, "ZFLG ", log.Ldate|log.Lmicroseconds|log.Lshortfile) 22 | } 23 | 24 | func main() { 25 | // Open a zip archive for reading. 26 | for _, zfn := range zfl { 27 | r, err := zip.OpenReader(zfn) 28 | if err != nil { 29 | alog.Fatal(err) 30 | } 31 | defer r.Close() 32 | alog.Println(pref, "Starts", "Compressed File:", zfn) 33 | alog.Println() 34 | // Iterate through the files in the archive, 35 | // printing some of their contents. 36 | for _, f := range r.File { 37 | alog.Println(pref, "======Next File/Directory======") 38 | fi := (&f.FileHeader).FileInfo() 39 | dumpFileData(f, fi) 40 | } 41 | // Done with a particular file 42 | alog.Println() 43 | alog.Println(pref, "Done", "Compressed File:", zfn) 44 | alog.Println() 45 | } 46 | } 47 | 48 | func dumpFileData(zf *zip.File, zi os.FileInfo) { 49 | alog.Println(pref, "Name:", zf.Name, "Type:", ftype(zi.IsDir())) 50 | // alog.Println(pref, "Size:", zi.Size(), "(bytes),", "Modtime:", 51 | // zi.ModTime().Format(time.RFC3339)) 52 | // alog.Println(pref, "Mode:", zi.Mode()) 53 | alog.Println(pref, "Mode:", zi.Mode(), "Size:", zi.Size(), "(bytes),", 54 | "Modtime:", zi.ModTime().Format(time.RFC3339)) 55 | } 56 | 57 | func ftype(b bool) string { 58 | if b { 59 | return "directory" 60 | } 61 | return "file" 62 | } 63 | --------------------------------------------------------------------------------