--- /dev/null
+
+package main
+
+import "fmt"
+import "sync"
+import "time"
+
+// What is Go closure?
+/*func main() {
+ go sayHello()
+ time.Sleep(100 * time.Millisecond)
+}*/
+
+var wg = sync.WaitGroup{}
+var counter = 0
+var counter2 = 0
+var m = sync.RWMutex{}
+
+func main() {
+
+ /*
+ for i := 0; i < 5; i++ {
+ wg.Add(2)
+ go sayHello(i)
+ go increment(i)
+ }
+ wg.Wait()
+ */
+
+ for i := 0; i < 5; i++ {
+ wg.Add(2)
+ go sayHelloM(i)
+ go incrementM(i)
+ }
+ wg.Wait()
+
+}
+
+func sayHello(i int) {
+ //m.RLock()
+ fmt.Printf("Hello (%v) #%v #%v\n", i, counter, counter2)
+ //m.RUnlock()
+ wg.Done()
+}
+
+func increment(i int) {
+ //m.Lock()
+ fmt.Printf("Counter (%v) start\n", i)
+ counter2++
+
+ time.Sleep(100 * time.Millisecond)
+ counter++
+ fmt.Printf("Counter (%v) #%v #%v\n", i, counter, counter2)
+ //m.Unlock()
+ wg.Done()
+}
+
+func sayHelloM(i int) {
+ c2 := counter2
+ if i < 3 {
+ time.Sleep(100 * time.Millisecond)
+ }
+ fmt.Printf("Hello (%v) #%v\n", i, c2)
+
+ m.RLock()
+ fmt.Printf("Hello (%v) #%v\n", i, counter)
+ m.RUnlock()
+ wg.Done()
+}
+
+func incrementM(i int) {
+ fmt.Printf("Counter (%v) start\n", i)
+ counter2++
+
+ m.Lock()
+ counter++
+ fmt.Printf("Counter (%v) #%v #%v\n", i, counter, counter2)
+ m.Unlock()
+ wg.Done()
+}
+
--- /dev/null
+
+package main
+
+import "fmt"
+import "sync"
+import "time"
+
+// What is Go closure?
+/*func main() {
+ go sayHello()
+ time.Sleep(100 * time.Millisecond)
+}*/
+
+var wg = sync.WaitGroup{}
+var counter = 0
+var counter2 = 0
+var m = sync.RWMutex{}
+
+func main() {
+
+ for i := 0; i < 5; i++ {
+ wg.Add(2)
+ go sayHello(i)
+ go increment(i)
+ }
+ wg.Wait()
+}
+
+func sayHello(i int) {
+ c2 := counter2
+ if i < 3 {
+ time.Sleep(100 * time.Millisecond)
+ }
+ fmt.Printf("Hello (%v) #%v\n", i, c2)
+
+ m.RLock()
+ fmt.Printf("Hello (%v) #%v\n", i, counter)
+ m.RUnlock()
+ wg.Done()
+}
+
+func increment(i int) {
+ counter2++
+ fmt.Printf("Counter (%v) start #%v\n", i, counter2)
+ if i < 3 {
+ time.Sleep(10 * time.Millisecond)
+ }
+
+ m.Lock()
+ counter++
+ fmt.Printf("Counter (%v) #%v\n", i, counter)
+ m.Unlock()
+ wg.Done()
+}
+
--- /dev/null
+
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ var w Writer = FileWriter{}
+ f(w)
+}
+
+func f (w Writer) {
+ w.Write([]byte("Hello go!"))
+}
+
+type Writer interface {
+ Write([]byte) (int, error)
+}
+
+type ConsoleWriter struct {}
+
+func (cw ConsoleWriter) Write(data []byte) (int, error) {
+ n, err := fmt.Println(string(data))
+ return n, err
+}
+
+type FileWriter struct {}
+
+func (fw FileWriter) Write(data []byte) (int, error) {
+ n, err := fmt.Println("write to file: ", string(data))
+ return n, err
+}
+
--- /dev/null
+
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ myInt := IntCounter(0)
+ var inc Incrementer = &myInt
+ f(inc)
+}
+
+func f(inc Incrementer) {
+ for i := 0; i < 10; {
+ i = inc.Increment()
+ fmt.Println(i)
+ }
+}
+
+type Incrementer interface {
+ Increment() int
+}
+
+type IntCounter int
+
+func (ic *IntCounter) Increment() int {
+ *ic++
+ return int(*ic)
+}
+
+func f2(inc Incrementer2) {
+ for i := 0; i < 10; {
+ inc = inc.Increment2()
+ fmt.Println(inc)
+ }
+}
+
+type Incrementer2 interface {
+ Increment2() Incrementer2
+}
+
+type IntCounter2 int
+
+func (ic IntCounter2) Increment2() Incrementer2 {
+ ic++
+ return ic
+}
+
--- /dev/null
+package main
+
+import (
+ "fmt"
+)
+
+type myStruct struct {
+ foo int
+}
+
+func main() {
+ /*
+ statePop := map[string]int{
+ "Cal": 392,
+ "Tex": 278,
+ "Flo": 206,
+ "New": 197,
+ "Pen": 128,
+ "Ill": 128,
+ "Ohi": 116,
+ }
+ */
+
+ var w Writer = ConsoleWriter{i: 3}
+ //var w ConsoleWriter = ConsoleWriter{i: 3}
+ // Write(w :: ConsoleWriter, ...)
+ w.Write([]byte("Hello go!"))
+ fmt.Printf("%v %T\n", w, w)
+
+ myInt := IntCounter(0)
+ // data Incrementer = forall a. Incrementer a => Incrementer a
+ // inc :: Incrementer
+ // inc = Incrementer myInt
+ var inc Incrementer = &myInt
+ for myInt < 10 {
+ fmt.Println(inc.Increment())
+ }
+}
+
+// class Writer a
+// Write(..)
+type Writer interface {
+ Write([]byte) (int, error)
+}
+
+// instance Writer ConsoleWriter
+type ConsoleWriter struct {
+ i int
+}
+
+// Write = ...
+func (cw ConsoleWriter) Write(data []byte) (int, error) {
+ n, err := fmt.Println(string(data))
+ cw.i = 7
+ return n, err
+}
+
+type Incrementer interface {
+ Increment() int
+}
+
+// newtype IntCounter = IntCounter Int
+type IntCounter int
+
+func (ic *IntCounter) Increment() int {
+ *ic++
+ return int(*ic)
+}
--- /dev/null
+package main
+
+import (
+ "fmt"
+)
+
+type myStruct struct {
+ foo int
+}
+
+func main() {
+ /*
+ statePop := map[string]int{
+ "Cal": 392,
+ "Tex": 278,
+ "Flo": 206,
+ "New": 197,
+ "Pen": 128,
+ "Ill": 128,
+ "Ohi": 116,
+ }
+ */
+
+ var wc WriterCloser = ConsoleWriter{i: 3}
+ //var w ConsoleWriter = ConsoleWriter{i: 3}
+ // Write(w :: ConsoleWriter, ...)
+ w.Write([]byte("Hello go!"))
+ fmt.Printf("%v %T\n", w, w)
+
+ myInt := IntCounter(0)
+ // data Incrementer = forall a. Incrementer a => Incrementer a
+ // inc :: Incrementer
+ // inc = Incrementer myInt
+ var inc Incrementer = &myInt
+ for myInt < 10 {
+ fmt.Println(inc.Increment())
+ }
+}
+
+// class Writer a
+// Write(..)
+type Writer interface {
+ Write([]byte) (int, error)
+}
+
+type Closer interface {
+ Close() error
+}
+
+type WriterCloser interface {
+ Writer
+ Closer
+}
+
+type BufferedWriterCloser struct {
+ buffer *bytes.Buffer
+}
+
+func (bwc *BufferedWriterCloser) Write(data []byte) (int, error) {
+ n, err := bwc.buffer.Write(data)
+ if err != nil {
+ return 0, err
+ }
+ v := make([]byte, 8)
+ for bwc.buffer.Len() > 8 {
+ _, err := bwc.buffer.Read(v)
+ if err != nil {
+ return 0, err
+ }
+ _, err = fmt.Println(string(v))
+ if err != nil {
+ return 0, err
+ }
+ }
+ return n, nil
+}
+
+func (bwc *BufferedWriterCloser) Close() error {
+ for bwc.buffer.Len() > 0 {
+ data := bwc.buffer.Next(8)
+ _, err := fmt.Println(string(data))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func NewBufferedWriterCloser() *BufferedWriterCloser {
+ return &BufferedWriterCloser{
+ buffer: bytes.NewBuffer([]bytes{}),
+ }
+}
+