diff --git a/eBook/examples/chapter_10/embed_func1.go b/eBook/examples/chapter_10/embed_func1.go new file mode 100644 index 0000000..ed92f27 --- /dev/null +++ b/eBook/examples/chapter_10/embed_func1.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" +) + +type Log struct { + msg string +} + +type Customer struct { + Name string + log *Log +} + +func main() { + // c := new(Customer) + // c.Name = "Barak Obama" + // c.log = new(Log) + // c.log.msg = "1 - Yes we can!" + // shorter: + c := &Customer{"Barak Obama", &Log{"1 - Yes we can!"}} + // fmt.Println(c) // &{Barak Obama 1 - Yes we can!} + c.Log().Add("2 - After me the world will be a better place!") + //fmt.Println(c.log) + fmt.Println(c.Log()) +} + +func (l *Log) Add(s string) { + l.msg += "\n" + s +} + +func (l *Log) String() string { + return l.msg +} + +func (c *Customer) Log() *Log { + return c.log +} +/* Output: +1 - Yes we can! +2 - After me the world will be a better place! +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/embed_func2.go b/eBook/examples/chapter_10/embed_func2.go new file mode 100644 index 0000000..f26b7e4 --- /dev/null +++ b/eBook/examples/chapter_10/embed_func2.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" +) + +type Log struct { + msg string +} + +type Customer struct { + Name string + Log +} + +func main() { + c := &Customer{"Barak Obama", Log{"1 - Yes we can!"}} + c.Add("2 - After me the world will be a better place!") + fmt.Println(c) +} + +func (l *Log) Add(s string) { + l.msg += "\n" + s +} + +func (c *Customer) String() string { + return c.Name + "\nLog:" + fmt.Sprintln(c.Log) +} + +func (l *Log) String() string { + return l.msg +} + +/* Output: +Barak Obama +Log:{1 - Yes we can! +2 - After me the world will be a better place!} +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/embedd_struct.go b/eBook/examples/chapter_10/embedd_struct.go new file mode 100644 index 0000000..bb24088 --- /dev/null +++ b/eBook/examples/chapter_10/embedd_struct.go @@ -0,0 +1,18 @@ +package main + +import "fmt" + +type A struct { + ax, ay int +} + +type B struct { + A + bx, by float32 +} + +func main() { + b := B{A{1, 2}, 3.0, 4.0} + fmt.Println(b.ax, b.ay, b.bx, b.by) + fmt.Println(b.A) +} diff --git a/eBook/examples/chapter_10/main.go b/eBook/examples/chapter_10/main.go new file mode 100644 index 0000000..8fecd16 --- /dev/null +++ b/eBook/examples/chapter_10/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "./struct_pack/structPack" +) + +func main() { + struct1 := new(structPack.ExpStruct) + struct1.Mi1 = 10 + struct1.Mf1 = 16. + fmt.Printf("Mi1 = %d\n", struct1.Mi1) + fmt.Printf("Mf1 = %f\n", struct1.Mf1) +} +// Mi1 = 10 +// Mf1 = 16.000000 \ No newline at end of file diff --git a/eBook/examples/chapter_10/method1.go b/eBook/examples/chapter_10/method1.go new file mode 100644 index 0000000..35280f0 --- /dev/null +++ b/eBook/examples/chapter_10/method1.go @@ -0,0 +1,29 @@ +package main + +import "fmt" + +type TwoInts struct { + a int + b int +} + +func main() { + two1 := new(TwoInts) + two1.a = 12 + two1.b = 10 + + fmt.Printf("The sum is: %d\n", two1.AddThem()) + fmt.Printf("Add them to the param: %d\n", two1.AddToParam(20)) + + // literal: + two2 := TwoInts{3, 4} + fmt.Printf("The sum is: %d\n", two2.AddThem()) +} + +func (tn *TwoInts) AddThem() int { + return tn.a + tn.b +} + +func (tn *TwoInts) AddToParam(param int) int { + return tn.a + tn.b + param +} diff --git a/eBook/examples/chapter_10/method2.go b/eBook/examples/chapter_10/method2.go new file mode 100644 index 0000000..f6fc530 --- /dev/null +++ b/eBook/examples/chapter_10/method2.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +type IntVector []int + +func (v IntVector) Sum() (s int) { + for _, x := range v { + s += x + } + return +} + +func main() { + fmt.Println(IntVector{1, 2, 3}.Sum()) // Output: 6 +} diff --git a/eBook/examples/chapter_10/method3.go b/eBook/examples/chapter_10/method3.go new file mode 100644 index 0000000..a5b11d6 --- /dev/null +++ b/eBook/examples/chapter_10/method3.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + x, y float64 +} + +func (p *Point) Abs() float64 { + return math.Sqrt(p.x*p.x + p.y*p.y) +} + +type NamedPoint struct { + Point + name string +} + +func main() { + n := &NamedPoint{Point{3, 4}, "Pythagoras"} + fmt.Println(n.Abs()) // prints 5 +} diff --git a/eBook/examples/chapter_10/method4.go b/eBook/examples/chapter_10/method4.go new file mode 100644 index 0000000..7d8b55a --- /dev/null +++ b/eBook/examples/chapter_10/method4.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + x, y float64 +} + +func (p *Point) Abs() float64 { + return math.Sqrt(p.x*p.x + p.y*p.y) +} + +type NamedPoint struct { + Point + name string +} + +func (n *NamedPoint) Abs() float64 { + return n.Point.Abs() * 100. +} + +func main() { + n := &NamedPoint{Point{3, 4}, "Pythagoras"} + fmt.Println(n.Abs()) // prints 500 +} diff --git a/eBook/examples/chapter_10/method_on_time.go b/eBook/examples/chapter_10/method_on_time.go new file mode 100644 index 0000000..ee422ae --- /dev/null +++ b/eBook/examples/chapter_10/method_on_time.go @@ -0,0 +1,25 @@ +// method_on_time.go +package main + +import ( + "fmt" + "time" +) + +type myTime struct { + time.Time //anonymous field +} + +func (t myTime) first3Chars() string { + return t.Time.String()[0:3] +} + +func main() { + m := myTime{time.Now()} + fmt.Println("Full time now:", m.String()) //calling existing String method on anonymous Time field + fmt.Println("First 3 chars:", m.first3Chars()) //calling myTime.first3Chars +} +/* Output: +Full time now: Mon Oct 24 15:34:54 Romance Daylight Time 2011 +First 3 chars: Mon +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/method_string.go b/eBook/examples/chapter_10/method_string.go new file mode 100644 index 0000000..0213139 --- /dev/null +++ b/eBook/examples/chapter_10/method_string.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "strconv" +) + +type TwoInts struct { + a int + b int +} + +func main() { + two1 := new(TwoInts) + two1.a = 12 + two1.b = 10 + fmt.Printf("two1 is: %v\n", two1) + fmt.Println("two1 is:", two1) + fmt.Printf("two1 is: %T\n", two1) + fmt.Printf("two1 is: %#v\n", two1) +} + +func (tn *TwoInts) String() string { + return "(" + strconv.Itoa(tn.a) + " / " + strconv.Itoa(tn.b) + ")" +} + + diff --git a/eBook/examples/chapter_10/methodset1.go b/eBook/examples/chapter_10/methodset1.go new file mode 100644 index 0000000..c8d8c6d --- /dev/null +++ b/eBook/examples/chapter_10/methodset1.go @@ -0,0 +1,22 @@ +// methodset1.go +package main + +import ( + "fmt" +) + +type List []int +func (l List) Len() int { return len(l) } +func (l *List) Append(val int) { *l = append(*l, val) } + +func main() { + // A bare value + var lst List + lst.Append(1) + fmt.Printf("%v (len: %d)\n", lst, lst.Len()) // [1] (len: 1) + + // A pointer value + plst := new(List) + plst.Append(2) + fmt.Printf("%v (len: %d)\n", plst, lst.Len()) // &[2] (len: 1) +} diff --git a/eBook/examples/chapter_10/mult_inheritance.go b/eBook/examples/chapter_10/mult_inheritance.go new file mode 100644 index 0000000..79d1ece --- /dev/null +++ b/eBook/examples/chapter_10/mult_inheritance.go @@ -0,0 +1,34 @@ +// mult_inheritance.go +package main + +import "fmt" + +type Camera struct { } + +func (c *Camera) TakeAPicture() string { + return "Click" +} + +type Phone struct { } + +func (p *Phone ) Call() string { + return "Ring Ring" +} + +// multiple inheritance +type CameraPhone struct { + Camera + Phone +} + +func main() { + cp := new(CameraPhone) + fmt.Println("Our new CameraPhone exhibits multiple behaviors ...") + fmt.Println("It exhibits behavior of a Camera: ", cp.TakeAPicture()) + fmt.Println("It works like a Phone too: ", cp.Call()) +} +/* Output: +Our new CameraPhone exhibits multiple behaviors ... +It exhibits behavior of a Camera: Click +It works like a Phone too: Ring Ring +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/new_make.go b/eBook/examples/chapter_10/new_make.go new file mode 100644 index 0000000..27ed57b --- /dev/null +++ b/eBook/examples/chapter_10/new_make.go @@ -0,0 +1,27 @@ +// annoy1.go +package main + +type Foo map[string]string +type Bar struct { + thingOne string + thingTwo int +} + +func main() { + // OK: + y := new(Bar) + (*y).thingOne = "hello" + (*y).thingTwo = 1 + // not OK: + z := make(Bar) // compile error: cannot make type Bar + z.thingOne = "hello" + z.thingTwo = 1 + // OK: + x := make(Foo) + x["x"] = "goodbye" + x["y"] = "world" + // not OK: + u := new(Foo) + (*u)["x"] = "goodbye" // !! panic !!: runtime error: assignment to entry in nil map + (*u)["y"] = "world" +} diff --git a/eBook/examples/chapter_10/person.go b/eBook/examples/chapter_10/person.go new file mode 100644 index 0000000..4f60cfb --- /dev/null +++ b/eBook/examples/chapter_10/person.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "strings" +) + +type Person struct { + firstName string + lastName string +} + +func upPerson (p *Person) { + p.firstName = strings.ToUpper(p.firstName) + p.lastName = strings.ToUpper(p.lastName) +} + +func main() { +// 1- struct as a value type: + var pers1 Person + pers1.firstName = "Chris" + pers1.lastName = "Woodward" + upPerson(&pers1) + fmt.Printf("The name of the person is %s %s\n", pers1.firstName, pers1.lastName) +// 2 - struct as a pointer: + pers2 := new(Person) + pers2.firstName = "Chris" + pers2.lastName = "Woodward" + (*pers2).lastName = "Woodward" + upPerson(pers2) + fmt.Printf("The name of the person is %s %s\n", pers2.firstName, pers2.lastName) +// 3 - struct as a literal: + pers3 := &Person{"Chris","Woodward"} + upPerson(pers3) + fmt.Printf("The name of the person is %s %s\n", pers3.firstName, pers3.lastName) +} +/* Output: +The name of the person is CHRIS WOODWARD +The name of the person is CHRIS WOODWARD +The name of the person is CHRIS WOODWARD +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/person2.go b/eBook/examples/chapter_10/person2.go new file mode 100644 index 0000000..c58c015 --- /dev/null +++ b/eBook/examples/chapter_10/person2.go @@ -0,0 +1,17 @@ +package person + +type Person struct { + firstName string + lastName string +} + +func (p *Person) FirstName() string { + return p.firstName +} + +func (p *Person) SetFirstName(newName string) { + p.firstName = newName +} + + + diff --git a/eBook/examples/chapter_10/pointer_value.go b/eBook/examples/chapter_10/pointer_value.go new file mode 100644 index 0000000..253a099 --- /dev/null +++ b/eBook/examples/chapter_10/pointer_value.go @@ -0,0 +1,28 @@ +// pointer_value.go +package main + +import ( + "fmt" +) + +type B struct { + thing int +} + +func (b *B) change() { b.thing = 1 } + +func (b B) write() string { return fmt.Sprint(b) } + +func main() { + var b1 B // b1 is value + b1.change() + fmt.Println(b1.write()) + + b2 := new(B) // b2 is pointer + b2.change() + fmt.Println(b2.write()) +} +/* Output: +{1} +{1} +*/ diff --git a/eBook/examples/chapter_10/struct_conversions.go b/eBook/examples/chapter_10/struct_conversions.go new file mode 100644 index 0000000..59ace66 --- /dev/null +++ b/eBook/examples/chapter_10/struct_conversions.go @@ -0,0 +1,24 @@ +// struct_conversions.go +package main + +import ( + "fmt" +) + +type number struct { + f float32 +} + +type nr number // alias type + +func main() { + a := number{5.0} + b := nr{5.0} + // var i float32 = b // compile-error: cannot use b (type nr) as type float32 in assignment + // var i = float32(b) // compile-error: cannot convert b (type nr) to type float32 + // var c number = b // compile-error: cannot use b (type nr) as type number in assignment + // needs a conversion: + var c = number(b) + fmt.Println(a, b, c) +} +// output: {5} {5} {5} diff --git a/eBook/examples/chapter_10/struct_pack/structPack.go b/eBook/examples/chapter_10/struct_pack/structPack.go new file mode 100644 index 0000000..34fb95c --- /dev/null +++ b/eBook/examples/chapter_10/struct_pack/structPack.go @@ -0,0 +1,6 @@ +package structPack + +type ExpStruct struct { + Mi1 int + Mf1 float32 +} diff --git a/eBook/examples/chapter_10/struct_tag.go b/eBook/examples/chapter_10/struct_tag.go new file mode 100644 index 0000000..d9099d1 --- /dev/null +++ b/eBook/examples/chapter_10/struct_tag.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "reflect" +) + +type TagType struct { // tags + field1 bool "An important answer" + field2 string "The name of the thing" + field3 int "How much there are" +} + +func main() { + tt := TagType{true, "Barak Obama", 1} + for i:= 0; i < 3; i++ { + refTag(tt, i) + } +} + +func refTag(tt TagType, ix int) { + ttType := reflect.TypeOf(tt) + ixField := ttType.Field(ix) + fmt.Printf("%v\n", ixField.Tag) +} +/* Output: +An important answer +The name of the thing +How much there are +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/structs_anonymous_fields.go b/eBook/examples/chapter_10/structs_anonymous_fields.go new file mode 100644 index 0000000..a6a13b2 --- /dev/null +++ b/eBook/examples/chapter_10/structs_anonymous_fields.go @@ -0,0 +1,34 @@ +package main + +import "fmt" + +type innerS struct { + in1 int + in2 int +} + +type outerS struct { + b int + c float32 + int // anonymous field + innerS // anonymous field +} + +func main() { + outer := new(outerS) + outer.b = 6 + outer.c = 7.5 + outer.int = 60 + outer.in1 = 5 + outer.in2 = 10 + + fmt.Printf("outer.b is: %d\n", outer.b) + fmt.Printf("outer.c is: %f\n", outer.c) + fmt.Printf("outer.int is: %d\n", outer.int) + fmt.Printf("outer.in1 is: %d\n", outer.in1) + fmt.Printf("outer.in2 is: %d\n", outer.in2) + // with a struct-literal: + outer2 := outerS{6, 7.5, 60, innerS{5, 10}} + fmt.Println("outer2 is: ", outer2) + +} diff --git a/eBook/examples/chapter_10/structs_fields.go b/eBook/examples/chapter_10/structs_fields.go new file mode 100644 index 0000000..56d97f3 --- /dev/null +++ b/eBook/examples/chapter_10/structs_fields.go @@ -0,0 +1,23 @@ +package main + +import "fmt" + +type struct1 struct { + i1 int + f1 float32 + str string +} + +func main() { + // var ms *struct1 = new(struct1) + // better: + ms := new(struct1) + ms.i1 = 10 + ms.f1 = 15.5 + ms.str = "Chris" + // ms := &struct1{10, 15.5, "Chris"} + fmt.Printf("The int is: %d\n", ms.i1) + fmt.Printf("The float is: %f\n", ms.f1) + fmt.Printf("The string is: %s\n", ms.str) + fmt.Println(ms) // output: &{10 15.5 Chris} +} diff --git a/eBook/examples/chapter_10/use_person2.go b/eBook/examples/chapter_10/use_person2.go new file mode 100644 index 0000000..14447d1 --- /dev/null +++ b/eBook/examples/chapter_10/use_person2.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "./person" +) + +func main() { + p := new(person.Person) + // error: p.firstName undefined (cannot refer to unexported field or method firstName) + // p.firstName = "Eric" + p.SetFirstName("Eric") + fmt.Println(p.FirstName()) // Output: Eric +} \ No newline at end of file diff --git a/eBook/examples/chapter_10/vcard.json b/eBook/examples/chapter_10/vcard.json new file mode 100644 index 0000000..91d0da3 --- /dev/null +++ b/eBook/examples/chapter_10/vcard.json @@ -0,0 +1 @@ +{"FirstName":"Jan","LastName":"Kersschot","Addresses":[{"Type":"private","City":"Aartselaar","Country":"Belgium"},{"Type":"work","City":"Boom","Country":"Belgium"}],"Remark":"none"} diff --git a/eBook/examples/chapter_11/cars.go b/eBook/examples/chapter_11/cars.go new file mode 100644 index 0000000..82a56aa --- /dev/null +++ b/eBook/examples/chapter_11/cars.go @@ -0,0 +1,95 @@ +// cars.go +package main + +import ( + "fmt" +) + + +type Any interface{} +type Car struct { + Model string + Manufacturer string + BuildYear int + // ... +} +type Cars []*Car + +func main() { + // make some cars: + ford := &Car{"Fiesta","Ford", 2008} + bmw := &Car{"XL 450", "BMW", 2011} + merc := &Car{"D600", "Mercedes", 2009} + bmw2 := &Car{"X 800", "BMW", 2008} + // query: + allCars := Cars([]*Car{ford, bmw, merc, bmw2}) + allNewBMWs := allCars.FindAll(func(car *Car) bool { + return (car.Manufacturer == "BMW") && (car.BuildYear > 2010) + }) + fmt.Println("AllCars: ", allCars) + fmt.Println("New BMWs: ", allNewBMWs) + // + manufacturers := []string{"Ford", "Aston Martin", "Land Rover", "BMW", "Jaguar"} + sortedAppender, sortedCars := MakeSortedAppender(manufacturers) + allCars.Process(sortedAppender) + fmt.Println("Map sortedCars: ", sortedCars) + BMWCount := len(sortedCars["BMW"]) + fmt.Println("We have ", BMWCount, " BMWs") +} + +// Process all cars with the given function f: +func (cs Cars) Process(f func(car *Car)) { + for _, c := range cs { + f(c) + } +} + +// Find all cars matching a given criteria. +func (cs Cars) FindAll(f func(car *Car) bool) Cars { + cars := make([]*Car, 0) + + cs.Process(func(c *Car) { + if f(c) { + cars = append(cars, c) + } + }) + return cars +} + +// Process cars and create new data. +func (cs Cars) Map(f func(car *Car) Any) []Any { + result := make([]Any, 0) + ix := 0 + cs.Process(func(c *Car) { + result[ix] = f(c) + ix++ + }) + return result +} + +func MakeSortedAppender(manufacturers []string) (func(car *Car), map[string]Cars) { + // Prepare maps of sorted cars. + sortedCars := make(map[string]Cars) + + for _, m := range manufacturers { + sortedCars[m] = make([]*Car, 0) + } + sortedCars["Default"] = make([]*Car, 0) + + // Prepare appender function: + appender := func(c *Car) { + if _, ok := sortedCars[c.Manufacturer]; ok { + sortedCars[c.Manufacturer] = append(sortedCars[c.Manufacturer], c) + } else { + sortedCars["Default"] = append(sortedCars["Default"], c) + } + } + return appender, sortedCars +} + +/* Output: +AllCars: [0xf8400038a0 0xf840003bd0 0xf840003ba0 0xf840003b70] +New BMWs: [0xf840003bd0] +Map sortedCars: map[Default:[0xf840003ba0] Jaguar:[] Land Rover:[] BMW:[0xf840003bd0 0xf840003b70] Aston Martin:[] Ford:[0xf8400038a0]] +We have 2 BMWs +*/ diff --git a/eBook/examples/chapter_11/duck_dance.go b/eBook/examples/chapter_11/duck_dance.go new file mode 100644 index 0000000..43d938e --- /dev/null +++ b/eBook/examples/chapter_11/duck_dance.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +type IDuck interface { + Quack() + Walk() +} + +func DuckDance(duck IDuck) { + for i := 1; i <= 3; i++ { + duck.Quack() + duck.Walk() + } +} + +type Bird struct { + // ... +} + +func (b *Bird) Quack() { + fmt.Println("I am quacking!") +} + +func (b *Bird) Walk() { + fmt.Println("I am walking!") +} + +func main() { + b := new(Bird) + DuckDance(b) +} diff --git a/eBook/examples/chapter_11/empty_interface.go b/eBook/examples/chapter_11/empty_interface.go new file mode 100644 index 0000000..6e9358c --- /dev/null +++ b/eBook/examples/chapter_11/empty_interface.go @@ -0,0 +1,38 @@ +package main + +import "fmt" + +var i = 5 +var str = "ABC" + +type Person struct { + name string + age int +} + +type Any interface{} + +func main() { + var val Any + val = 5 + fmt.Printf("val has the value: %v\n", val) + val = str + fmt.Printf("val has the value: %v\n", val) + pers1 := new(Person) + pers1.name = "Rob Pike" + pers1.age = 55 + val = pers1 + fmt.Printf("val has the value: %v\n", val) + switch t := val.(type) { + case int: + fmt.Printf("Type int %T\n", t) + case string: + fmt.Printf("Type string %T\n", t) + case bool: + fmt.Printf("Type boolean %T\n", t) + case *Person: + fmt.Printf("Type pointer to Person %T\n", *t) + default: + fmt.Printf("Unexpected type %T", t) + } +} diff --git a/eBook/examples/chapter_11/emptyint_switch.go b/eBook/examples/chapter_11/emptyint_switch.go new file mode 100644 index 0000000..d034dad --- /dev/null +++ b/eBook/examples/chapter_11/emptyint_switch.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +type specialString string + +var whatIsThis specialString = "hello" + +func TypeSwitch() { + testFunc := func(any interface{}) { + switch v := any.(type) { + case bool: + fmt.Printf("any %v is a bool type", v) + case int: + fmt.Printf("any %v is an int type", v) + case float32: + fmt.Printf("any %v is a float32 type", v) + case string: + fmt.Printf("any %v is a string type", v) + case specialString: + fmt.Printf("any %v is a special String!", v) + default: + fmt.Println("unknown type!") + } + } + testFunc(whatIsThis) +} + +func main() { + TypeSwitch() +} +// Output: any hello is a special String! diff --git a/eBook/examples/chapter_11/interfaces.go b/eBook/examples/chapter_11/interfaces.go new file mode 100644 index 0000000..5c15bd3 --- /dev/null +++ b/eBook/examples/chapter_11/interfaces.go @@ -0,0 +1,30 @@ +package main + +import "fmt" + +type Shaper interface { + Area() float32 + // Perimeter() float32 +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func main() { + sq1 := new(Square) + sq1.side = 5 + + // var areaIntf Shaper + // areaIntf = sq1 + // shorter, without separate declaration: + // areaIntf := Shaper(sq1) + // or even: + areaIntf := sq1 + fmt.Printf("The square has area: %f\n", areaIntf.Area()) +} +// The square has area: 25.000000 diff --git a/eBook/examples/chapter_11/interfaces_poly.go b/eBook/examples/chapter_11/interfaces_poly.go new file mode 100644 index 0000000..80efb4c --- /dev/null +++ b/eBook/examples/chapter_11/interfaces_poly.go @@ -0,0 +1,45 @@ +// interfaces_poly.go +package main + +import "fmt" + +type Shaper interface { + Area() float32 +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +type Rectangle struct { + length, width float32 +} + +func (r Rectangle) Area() float32 { + return r.length * r.width +} + +func main() { + r := Rectangle{5, 3} // Area() of Rectangle needs a value + q := &Square{5} // Area() of Square needs a pointer + shapes := []Shaper{r, q} + fmt.Println("Looping through shapes for area ...") + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +*/ + + + diff --git a/eBook/examples/chapter_11/methodset2.go b/eBook/examples/chapter_11/methodset2.go new file mode 100644 index 0000000..886c687 --- /dev/null +++ b/eBook/examples/chapter_11/methodset2.go @@ -0,0 +1,48 @@ +// methodset2.go +package main + +import ( + "fmt" +) + +type List []int +func (l List) Len() int { return len(l) } +func (l *List) Append(val int) { *l = append(*l, val) } + +type Appender interface { + Append(int) +} + +func CountInto(a Appender, start, end int) { + for i := start; i <= end; i++ { + a.Append(i) + } +} + +type Lener interface { + Len() int +} + +func LongEnough(l Lener) bool { + return l.Len()*10 > 42 +} + +func main() { + // A bare value + var lst List + // compiler error: + // cannot use lst (type List) as type Appender in function argument: + // List does not implement Appender (Append method requires pointer receiver) + // CountInto(lst, 1, 10) // INVALID: Append has a pointer receiver + + if LongEnough(lst) { // VALID: Identical receiver type + fmt.Printf(" - lst is long enough") + } + + // A pointer value + plst := new(List) + CountInto(plst, 1, 10) // VALID: Identical receiver type + if LongEnough(plst) { // VALID: a *List can be dereferenced for the receiver + fmt.Printf(" - plst is long enough") // - plst is long enoug + } +} diff --git a/eBook/examples/chapter_11/multi_interfaces_poly.go b/eBook/examples/chapter_11/multi_interfaces_poly.go new file mode 100644 index 0000000..d98db8c --- /dev/null +++ b/eBook/examples/chapter_11/multi_interfaces_poly.go @@ -0,0 +1,65 @@ +//multi_interfaces_poly.go +package main + +import "fmt" + +type Shaper interface { + Area() float32 +} + +type TopologicalGenus interface { + Rank() int +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func (sq *Square) Rank() int { + return 1 +} + +type Rectangle struct { + length, width float32 +} + +func (r Rectangle) Area() float32 { + return r.length * r.width +} + +func (r Rectangle) Rank() int { + return 2 +} + +func main() { + r := Rectangle{5, 3} // Area() of Rectangle needs a value + q := &Square{5} // Area() of Square needs a pointer + shapes := []Shaper{r, q} + fmt.Println("Looping through shapes for area ...") + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } + topgen := []TopologicalGenus{r, q} + fmt.Println("Looping through topgen for rank ...") + for n, _ := range topgen { + fmt.Println("Shape details: ", topgen[n]) + fmt.Println("Topological Genus of this shape is: ", topgen[n].Rank()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +Looping through topgen for rank ... +Shape details: {5 3} +Topological Genus of this shape is: 2 +Shape details: &{5} +Topological Genus of this shape is: 1 +*/ diff --git a/eBook/examples/chapter_11/node_structures.go b/eBook/examples/chapter_11/node_structures.go new file mode 100644 index 0000000..f729d39 --- /dev/null +++ b/eBook/examples/chapter_11/node_structures.go @@ -0,0 +1,31 @@ +// node_structures.go +package main + +import "fmt" + +type Node struct { + le *Node + data interface{} + ri *Node +} + +func NewNode(left, right *Node) *Node { + return &Node{left, nil, right} +} + +func (n *Node) SetData(data interface{}) { + n.data = data +} + +func main() { + root := NewNode(nil,nil) + root.SetData("root node") + // make child (leaf) nodes: + a := NewNode(nil,nil) + a.SetData("left node") + b := NewNode(nil,nil) + b.SetData("right node") + root.le = a + root.ri = b + fmt.Printf("%v\n", root) // Output: &{0x125275f0 root node 0x125275e0} +} diff --git a/eBook/examples/chapter_11/print.go b/eBook/examples/chapter_11/print.go new file mode 100644 index 0000000..a394902 --- /dev/null +++ b/eBook/examples/chapter_11/print.go @@ -0,0 +1,43 @@ +// print.go +package main + +import ( + "os" + "strconv" +) + +type Stringer interface { + String() string +} + +type Celsius float64 + +func (c Celsius) String() string { + return strconv.FormatFloat(float64(c),'f', 1, 64) + " °C" +} + +type Day int + +var dayName = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"} + +func (day Day) String() string { + return dayName[day] +} + +func print(args ...interface{}) { + for i, arg := range args { + if i > 0 {os.Stdout.WriteString(" ")} + switch a := arg.(type) { // type switch + case Stringer: os.Stdout.WriteString(a.String()) + case int: os.Stdout.WriteString(strconv.Itoa(a)) + case string: os.Stdout.WriteString(a) + // more types + default: os.Stdout.WriteString("???") + } + } +} + +func main() { + print(Day(1), "was", Celsius(18.36)) // Tuesday was 18.4 °C +} +// Tuesday was 18.4 °C \ No newline at end of file diff --git a/eBook/examples/chapter_11/reflect1.go b/eBook/examples/chapter_11/reflect1.go new file mode 100644 index 0000000..7e0526b --- /dev/null +++ b/eBook/examples/chapter_11/reflect1.go @@ -0,0 +1,32 @@ +// reflect1.go +// blog: Laws of Reflection +package main + +import ( + "fmt" + "reflect" +) + +func main() { + var x float64 = 3.4 + fmt.Println("type:", reflect.TypeOf(x)) + v := reflect.ValueOf(x) + fmt.Println("value:", v) + fmt.Println("type:", v.Type()) + fmt.Println("kind:", v.Kind()) + fmt.Println("value:", v.Float()) + fmt.Println(v.Interface()) + fmt.Printf("value is %5.2e\n", v.Interface()) + y := v.Interface().(float64) + fmt.Println(y) +} +/* output: +type: float64 +value: +type: float64 +kind: float64 +value: 3.4 +3.4 +value is 3.40e+00 +3.4 +*/ diff --git a/eBook/examples/chapter_11/reflect2.go b/eBook/examples/chapter_11/reflect2.go new file mode 100644 index 0000000..7780228 --- /dev/null +++ b/eBook/examples/chapter_11/reflect2.go @@ -0,0 +1,33 @@ +// reflect2.go +package main + +import ( + "fmt" + "reflect" +) + +func main() { + var x float64 = 3.4 + v := reflect.ValueOf(x) + // setting a value: + // v.SetFloat(3.1415) // Error: will panic: reflect.Value.SetFloat using unaddressable value + fmt.Println("settability of v:", v.CanSet()) + v = reflect.ValueOf(&x) // Note: take the address of x. + fmt.Println("type of v:", v.Type()) + fmt.Println("settability of v:", v.CanSet()) + v = v.Elem() + fmt.Println("The Elem of v is: ", v) + fmt.Println("settability of v:", v.CanSet()) + v.SetFloat(3.1415) // this works! + fmt.Println(v.Interface()) + fmt.Println(v) +} +/* Output: +settability of v: false +type of v: *float64 +settability of v: false +The Elem of v is: +settability of v: true +3.1415 + +*/ diff --git a/eBook/examples/chapter_11/reflect_struct.go b/eBook/examples/chapter_11/reflect_struct.go new file mode 100644 index 0000000..2d95a25 --- /dev/null +++ b/eBook/examples/chapter_11/reflect_struct.go @@ -0,0 +1,47 @@ +// reflect.go +package main + +import ( + "fmt" + "reflect" +) + +type NotknownType struct { + s1, s2, s3 string +} + +func (n NotknownType) String() string { + return n.s1 + " - " + n.s2 + " - " + n.s3 +} + +// variable to investigate: +var secret interface {} = NotknownType{"Ada", "Go", "Oberon"} + +func main() { + value := reflect.ValueOf(secret) // + typ := reflect.TypeOf(secret) // main.NotknownType + // alternative: + //typ := value.Type() // main.NotknownType + fmt.Println(typ) + knd := value.Kind() // struct + fmt.Println(knd) + + // iterate through the fields of the struct: + for i:= 0; i < value.NumField(); i++ { + fmt.Printf("Field %d: %v\n", i, value.Field(i)) + // error: panic: reflect.Value.SetString using value obtained using unexported field + //value.Field(i).SetString("C#") + } + + // call the first method, which is String(): + results := value.Method(0).Call(nil) + fmt.Println(results) // [Ada - Go - Oberon] +} +/* Output: +main.NotknownType +struct +Field 0: Ada +Field 1: Go +Field 2: Oberon +[Ada - Go - Oberon] +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_11/reflect_struct2.go b/eBook/examples/chapter_11/reflect_struct2.go new file mode 100644 index 0000000..2c0c915 --- /dev/null +++ b/eBook/examples/chapter_11/reflect_struct2.go @@ -0,0 +1,31 @@ +// reflect_struct2.go +package main + +import ( + "fmt" + "reflect" +) + +type T struct { + A int + B string +} + +func main() { + t := T{23, "skidoo"} + s := reflect.ValueOf(&t).Elem() + typeOfT := s.Type() + for i := 0; i < s.NumField(); i++ { + f := s.Field(i) + fmt.Printf("%d: %s %s = %v\n", i, + typeOfT.Field(i).Name, f.Type(), f.Interface()) + } + s.Field(0).SetInt(77) + s.Field(1).SetString("Sunset Strip") + fmt.Println("t is now", t) +} +/* Output: +0: A int = 23 +1: B string = skidoo +t is now {77 Sunset Strip} +*/ diff --git a/eBook/examples/chapter_11/sort/sort.go b/eBook/examples/chapter_11/sort/sort.go new file mode 100644 index 0000000..00f618d --- /dev/null +++ b/eBook/examples/chapter_11/sort/sort.go @@ -0,0 +1,58 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Sorting using a general interface +package sort + +// Sorting interface +type Interface interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +// General sort function +func Sort(data Interface) { + for i := 1; i < data.Len(); i++ { + for j := i; j > 0 && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Test if data is sorted +func IsSorted(data Interface) bool { + n := data.Len() + for i := n - 1; i > 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +// Convenience types for common cases: IntArray +type IntArray []int + +func (p IntArray) Len() int { return len(p) } +func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } +func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type Float64Array []float64 +func (p Float64Array) Len() int { return len(p) } +func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] } +func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type StringArray []string +func (p StringArray) Len() int { return len(p) } +func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } +func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Convenience wrappers for common cases +func SortInts(a []int) { Sort(IntArray(a)) } +func SortFloat64s(a []float64) { Sort(Float64Array(a)) } +func SortStrings(a []string) { Sort(StringArray(a)) } + +func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } +func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Array(a)) } +func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } \ No newline at end of file diff --git a/eBook/examples/chapter_11/sortmain.go b/eBook/examples/chapter_11/sortmain.go new file mode 100644 index 0000000..da63508 --- /dev/null +++ b/eBook/examples/chapter_11/sortmain.go @@ -0,0 +1,82 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package gives an example of how to use a custom package with interfaces +package main + +import ( + "fmt" + "./sort" +) + +// sorting of slice of integers +func ints() { + data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} + a := sort.IntArray(data) //conversion to type IntArray + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// sorting of slice of strings +func strings() { + data := []string{"monday", "friday", "tuesday", "wednesday", "sunday","thursday", "", "saturday"} + a := sort.StringArray(data) + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// a type which describes a day of the week +type day struct { + num int + shortName string + longName string +} + +type dayArray struct { + data []*day +} + +func (p *dayArray) Len() int { return len(p.data) } +func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num } +func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] } + +// sorting of custom type day +func days() { + Sunday := day{0, "SUN", "Sunday"} + Monday := day{1, "MON", "Monday"} + Tuesday := day{2, "TUE", "Tuesday"} + Wednesday := day{3, "WED", "Wednesday"} + Thursday := day{4, "THU", "Thursday"} + Friday := day{5, "FRI", "Friday"} + Saturday := day{6, "SAT", "Saturday"} + data := []*day{&Tuesday, &Thursday, &Wednesday, &Sunday, &Monday, &Friday, &Saturday} + a := dayArray{data} + sort.Sort(&a) + if !sort.IsSorted(&a) { + panic("fail") + } + for _, d := range data { + fmt.Printf("%s ", d.longName) + } + fmt.Printf("\n") +} + + +func main() { + ints() + strings() + days() +} + +/* Output: +The sorted array is: [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845] +The sorted array is: [ friday monday saturday sunday thursday tuesday wednesday] +Sunday Monday Tuesday Wednesday Thursday Friday Saturday +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_11/static.go b/eBook/examples/chapter_11/static.go new file mode 100644 index 0000000..032ba04 --- /dev/null +++ b/eBook/examples/chapter_11/static.go @@ -0,0 +1,23 @@ +// static.go +package main + +import ( + "io" + "os" + "bufio" + "bytes" + "fmt" +) + +var r io.Reader + +func main() { + r = os.Stdin + r = bufio.NewReader(r) + r = new(bytes.Buffer) + f, _ := os.Open("test.txt") + r = bufio.NewReader(f) + var s *bytes.Buffer = new(bytes.Buffer) + r = s + fmt.Println(s) +} diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/00changelog.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/00changelog.i new file mode 100644 index 0000000..d3a8311 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/00changelog.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branch b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branch new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branch @@ -0,0 +1 @@ +default diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branchheads.cache b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branchheads.cache new file mode 100644 index 0000000..e2899cb --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branchheads.cache @@ -0,0 +1,2 @@ +0e0559350cc3c90b3a51dd98ac3ba577db027317 95 +0e0559350cc3c90b3a51dd98ac3ba577db027317 default diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/dirstate b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/dirstate new file mode 100644 index 0000000..a42db2e Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/dirstate differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/hgrc b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/hgrc new file mode 100644 index 0000000..55f5e08 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/hgrc @@ -0,0 +1,2 @@ +[paths] +default = https://tideland-cgl.googlecode.com/hg diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/requires b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/requires new file mode 100644 index 0000000..ca69271 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/requires @@ -0,0 +1,4 @@ +revlogv1 +store +fncache +dotencode diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00changelog.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00changelog.i new file mode 100644 index 0000000..1697e39 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00changelog.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00manifest.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00manifest.i new file mode 100644 index 0000000..52e2669 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00manifest.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i new file mode 100644 index 0000000..e4f64d3 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_makefile.i new file mode 100644 index 0000000..9162367 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl.go.i new file mode 100644 index 0000000..f2ebe14 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl__test.go.i new file mode 100644 index 0000000..a6698c8 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb.go.i new file mode 100644 index 0000000..a20625e Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/_makefile.i new file mode 100644 index 0000000..703f65f Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb.go.i new file mode 100644 index 0000000..d2535e3 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb__test.go.i new file mode 100644 index 0000000..ff6f157 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgldoc/_l_i_c_e_n_s_e.txt.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgldoc/_l_i_c_e_n_s_e.txt.i new file mode 100644 index 0000000..a63c1e8 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgldoc/_l_i_c_e_n_s_e.txt.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/_makefile.i new file mode 100644 index 0000000..7f8b992 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca.go.i new file mode 100644 index 0000000..0e45d8f Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca__test.go.i new file mode 100644 index 0000000..4a33e6d Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecaucb.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecaucb.go.i new file mode 100644 index 0000000..9ec11d1 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecaucb.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecauep.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecauep.go.i new file mode 100644 index 0000000..6138197 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecauep.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecautl.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecautl.go.i new file mode 100644 index 0000000..ffd2afb Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecautl.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm.go.i new file mode 100644 index 0000000..ed031df Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/_makefile.i new file mode 100644 index 0000000..8d38eee Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm.go.i new file mode 100644 index 0000000..a7ad1e9 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm__test.go.i new file mode 100644 index 0000000..a1cdebc Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon.go.i new file mode 100644 index 0000000..278fb90 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/_makefile.i new file mode 100644 index 0000000..c25c756 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon.go.i new file mode 100644 index 0000000..ae5a274 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon__test.go.i new file mode 100644 index 0000000..4e7260a Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonetm.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonetm.go.i new file mode 100644 index 0000000..83eda89 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonetm.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonssi.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonssi.go.i new file mode 100644 index 0000000..6af519b Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonssi.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmrp.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmrp.go.i new file mode 100644 index 0000000..29b6a67 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmrp.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum.go.i new file mode 100644 index 0000000..edd73a0 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/_makefile.i new file mode 100644 index 0000000..d32941a Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum.go.i new file mode 100644 index 0000000..ca656cb Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum__test.go.i new file mode 100644 index 0000000..26bfb4b Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumgra.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumgra.go.i new file mode 100644 index 0000000..478f92f Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumgra.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumsta.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumsta.go.i new file mode 100644 index 0000000..ace3ab4 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumsta.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/_makefile.i new file mode 100644 index 0000000..c863749 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred.go.i new file mode 100644 index 0000000..8087a5d Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred__test.go.i new file mode 100644 index 0000000..2ae3a71 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredcmd.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredcmd.go.i new file mode 100644 index 0000000..d4235af Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredcmd.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredres.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredres.go.i new file mode 100644 index 0000000..caa98fd Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredres.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredurp.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredurp.go.i new file mode 100644 index 0000000..bdac1e2 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredurp.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml.go.i new file mode 100644 index 0000000..942447e Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/_makefile.i new file mode 100644 index 0000000..7cf27e3 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml.go.i new file mode 100644 index 0000000..a4339b8 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml__test.go.i new file mode 100644 index 0000000..23447a8 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsmlpap.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsmlpap.go.i new file mode 100644 index 0000000..d8ae5bf Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsmlpap.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsmr.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsmr.go.i new file mode 100644 index 0000000..0b5c061 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsmr.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsrt.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsrt.go.i new file mode 100644 index 0000000..11fc060 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsrt.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup.go.i new file mode 100644 index 0000000..ef42aa4 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/_makefile.i new file mode 100644 index 0000000..3148a14 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup.go.i new file mode 100644 index 0000000..b083cae Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup__test.go.i new file mode 100644 index 0000000..aae4793 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgltim.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgltim.go.i new file mode 100644 index 0000000..df70cf9 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgltim.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/_makefile.i new file mode 100644 index 0000000..7d0581f Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/_makefile.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl.go.i new file mode 100644 index 0000000..c10483a Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl__test.go.i new file mode 100644 index 0000000..71df63f Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl__test.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlmrp.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlmrp.go.i new file mode 100644 index 0000000..f8b1923 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlmrp.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlrre.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlrre.go.i new file mode 100644 index 0000000..1bbef82 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlrre.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsrt.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsrt.go.i new file mode 100644 index 0000000..e819beb Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsrt.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsup.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsup.go.i new file mode 100644 index 0000000..21a9aa4 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsup.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutltim.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutltim.go.i new file mode 100644 index 0000000..fa83716 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutltim.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutluid.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutluid.go.i new file mode 100644 index 0000000..363e7db Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutluid.go.i differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/fncache b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/fncache new file mode 100644 index 0000000..6b090a7 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/fncache @@ -0,0 +1,60 @@ +data/cgldoc/LICENSE.txt.i +data/cgl_test.go.i +data/cglfsm/cglfsm.go.i +data/cglnum/Makefile.i +data/cglfsm.go.i +data/cglsup.go.i +data/Makefile.i +data/cglctb/cglctb_test.go.i +data/cglmrp.go.i +data/cglsup/cglsup_test.go.i +data/cglutl/cglutluid.go.i +data/cglsml/cglsml.go.i +data/cglred/cglred.go.i +data/cglmon/Makefile.i +data/cglsup/cglsup.go.i +data/cglmon/cglmon_test.go.i +data/cglmon/cglmonssi.go.i +data/LICENSE.txt.i +data/cglmon/cglmon.go.i +data/cglutl/cglutlmrp.go.i +data/cglsrt.go.i +data/cglutl/cglutlsup.go.i +data/cglred/cglred_test.go.i +data/cgleca/cglecauep.go.i +data/.hgtags.i +data/cglnum/cglnum_test.go.i +data/cgleca/cglecaucb.go.i +data/cglsml/cglsmlpap.go.i +data/cglutl/cglutltim.go.i +data/cgleca/Makefile.i +data/cglred/Makefile.i +data/cglred/cglredres.go.i +data/cglmon/cglmonetm.go.i +data/cglutl/cglutl.go.i +data/cgleca/cglecautl.go.i +data/cglnum/cglnumsta.go.i +data/cglnum.go.i +data/cglsml/Makefile.i +data/cglctb/cglctb.go.i +data/cglnum/cglnumgra.go.i +data/cglutl/Makefile.i +data/cglctb.go.i +data/cglsmr.go.i +data/cglutl/cglutl_test.go.i +data/cglfsm/cglfsm_test.go.i +data/cgl.go.i +data/cglutl/cglutlrre.go.i +data/cglred/cglredcmd.go.i +data/cglutl/cglutlsrt.go.i +data/cglmon.go.i +data/cglctb/Makefile.i +data/cglfsm/Makefile.i +data/cglsml/cglsml_test.go.i +data/cgltim.go.i +data/cgleca/cgleca_test.go.i +data/cgleca/cgleca.go.i +data/cglnum/cglnum.go.i +data/cglsup/Makefile.i +data/cglred/cglredurp.go.i +data/cglsml.go.i diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/undo b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/undo new file mode 100644 index 0000000..a532d54 Binary files /dev/null and b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/undo differ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache new file mode 100644 index 0000000..7f2cacb --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache @@ -0,0 +1,6 @@ +95 0e0559350cc3c90b3a51dd98ac3ba577db027317 d11eb24f9c4089a5d83f315625407b7bf1811bb4 + +23ee9664f914f12079d78fdb6e8d5745387b0394 release +440721520a9cc613e0999c70c40e8e2bb7c70cfb release.2011-06-23 +5353419f1ba694ba7a425e6a6fcd45ea97884560 release.2011-07-28 +23ee9664f914f12079d78fdb6e8d5745387b0394 release.2011-08-02 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch new file mode 100644 index 0000000..331d858 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch @@ -0,0 +1 @@ +default \ No newline at end of file diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc new file mode 100644 index 0000000..e96d029 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc @@ -0,0 +1,3 @@ +0 +pull +https://tideland-cgl.googlecode.com/hg diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.dirstate b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.dirstate new file mode 100644 index 0000000..e69de29 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags new file mode 100644 index 0000000..e7727eb --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags @@ -0,0 +1,5 @@ +440721520a9cc613e0999c70c40e8e2bb7c70cfb release.2011-06-23 +440721520a9cc613e0999c70c40e8e2bb7c70cfb release +5353419f1ba694ba7a425e6a6fcd45ea97884560 release.2011-07-28 +440721520a9cc613e0999c70c40e8e2bb7c70cfb release +5353419f1ba694ba7a425e6a6fcd45ea97884560 release diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt new file mode 100644 index 0000000..360008e --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt @@ -0,0 +1,28 @@ +Tideland Common Go Library + +Redistribution and use in source and binary forms, with or +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +Neither the name of Tideland nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile new file mode 100644 index 0000000..fe8deda --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile @@ -0,0 +1,31 @@ +# Tideland Common Go Library +# +# Copyright 2009-2011 Frank Mueller / Oldenburg / Germany. +# +# All rights reserved. Use of this source code is +# governed by a BSD-style license that can be found +# in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=tideland-cgl.googlecode.com/hg +GOFMT=gofmt -w -tabindent -tabwidth=8 + +GOFILES=\ + cgl.go\ + cglsup.go\ + cglfsm.go\ + cglmon.go\ + cglsmr.go\ + cgltim.go\ + cglsml.go\ + +include $(GOROOT)/src/Make.pkg + +format: + ${GOFMT} ${GOFILES} + ${GOFMT} cgl_test.go + +# +# EOF +# diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go new file mode 100644 index 0000000..295e4c7 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go @@ -0,0 +1,288 @@ +/* + Tideland Common Go Library + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// The package 'cgl' contains a lot of helpful stuff for many kinds of software. Those +// are a map/reduce, sorting, time handling, UUIDs, lazy evaluation, chronological jobs, +// state machines, monitoring, suervision, a simple markup language and much more. +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "bytes" + "crypto/rand" + "fmt" + "encoding/hex" + "io" + "log" + "reflect" + "runtime" + "strings" + "unicode" +) + +//-------------------- +// CONST +//-------------------- + +const RELEASE = "Tideland Common Go Library Release 2011-08-02" + +//-------------------- +// DEBUGGING +//-------------------- + +// Debug prints a debug information to the log with file and line. +func Debug(format string, a ...interface{}) { + _, file, line, _ := runtime.Caller(1) + info := fmt.Sprintf(format, a...) + + log.Printf("[cgl] debug %s:%d %v", file, line, info) +} + +//-------------------- +// UUID +//-------------------- + +// UUID represent a universal identifier with 16 bytes. +type UUID []byte + +// NewUUID generates a new UUID based on version 4. +func NewUUID() UUID { + uuid := make([]byte, 16) + + _, err := io.ReadFull(rand.Reader, uuid) + + if err != nil { + log.Fatal(err) + } + + // Set version (4) and variant (2). + + var version byte = 4 << 4 + var variant byte = 2 << 4 + + uuid[6] = version | (uuid[6] & 15) + uuid[8] = variant | (uuid[8] & 15) + + return uuid +} + +// Raw returns a copy of the UUID bytes. +func (uuid UUID) Raw() []byte { + raw := make([]byte, 16) + + copy(raw, uuid[0:16]) + + return raw +} + +// String returns a hexadecimal string representation with +// standardized separators. +func (uuid UUID) String() string { + base := hex.EncodeToString(uuid.Raw()) + + return base[0:8] + "-" + base[8:12] + "-" + base[12:16] + "-" + base[16:20] + "-" + base[20:32] +} + +//-------------------- +// MORE ID FUNCTIONS +//-------------------- + +// LimitedSepIdentifier builds an identifier out of multiple parts, +// all as lowercase strings and concatenated with the separator +// Non letters and digits are exchanged with dashes and +// reduced to a maximum of one each. If limit is true only +// 'a' to 'z' and '0' to '9' are allowed. +func LimitedSepIdentifier(sep string, limit bool, parts ...interface{}) string { + iparts := make([]string, 0) + + for _, p := range parts { + tmp := strings.Map(func(r int) int { + // Check letter and digit. + if unicode.IsLetter(r) || unicode.IsDigit(r) { + lcr := unicode.ToLower(r) + + if limit { + // Only 'a' to 'z' and '0' to '9'. + if lcr <= unicode.MaxASCII { + return lcr + } else { + return ' ' + } + } else { + // Every char is allowed. + return lcr + } + } + + return ' ' + }, fmt.Sprintf("%v", p)) + + // Only use non-empty identifier parts. + if ipart := strings.Join(strings.Fields(tmp), "-"); len(ipart) > 0 { + iparts = append(iparts, ipart) + } + } + + return strings.Join(iparts, sep) +} + +// SepIdentifier builds an identifier out of multiple parts, all +// as lowercase strings and concatenated with the separator +// Non letters and digits are exchanged with dashes and +// reduced to a maximum of one each. +func SepIdentifier(sep string, parts ...interface{}) string { + return LimitedSepIdentifier(sep, false, parts...) +} + +// Identifier works like SepIdentifier but the seperator +// is set to be a colon. +func Identifier(parts ...interface{}) string { + return SepIdentifier(":", parts...) +} + +// TypeAsIdentifierPart transforms the name of the arguments type into +// a part for identifiers. It's splitted at each uppercase char, +// concatenated with dashes and transferred to lowercase. +func TypeAsIdentifierPart(i interface{}) string { + var buf bytes.Buffer + + fullTypeName := reflect.TypeOf(i).String() + lastDot := strings.LastIndex(fullTypeName, ".") + typeName := fullTypeName[lastDot+1:] + + for i, r := range typeName { + if unicode.IsUpper(r) { + if i > 0 { + buf.WriteRune('-') + } + } + + buf.WriteRune(r) + } + + return strings.ToLower(buf.String()) +} + +//-------------------- +// METHOD DISPATCHING +//-------------------- + +// Dispatch a string to a method of a type. +func Dispatch(variable interface{}, name string, args ...interface{}) ([]interface{}, bool) { + numArgs := len(args) + value := reflect.ValueOf(variable) + valueType := value.Type() + numMethods := valueType.NumMethod() + + for i := 0; i < numMethods; i++ { + method := valueType.Method(i) + + if (method.PkgPath == "") && (method.Type.NumIn() == numArgs+1) { + + if method.Name == name { + // Prepare all args with variable and args. + + callArgs := make([]reflect.Value, numArgs+1) + + callArgs[0] = value + + for i, a := range args { + callArgs[i+1] = reflect.ValueOf(a) + } + + // Make the function call. + + results := method.Func.Call(callArgs) + + // Transfer results into slice of interfaces. + + allResults := make([]interface{}, len(results)) + + for i, v := range results { + allResults[i] = v.Interface() + } + + return allResults, true + } + } + } + + return nil, false +} + +//-------------------- +// LAZY EVALUATOR BUILDERS +//-------------------- + +// Function to evaluate. +type EvalFunc func(interface{}) (interface{}, interface{}) + +// Generic builder for lazy evaluators. +func BuildLazyEvaluator(evalFunc EvalFunc, initState interface{}) func() interface{} { + retValChan := make(chan interface{}) + + loopFunc := func() { + var actState interface{} = initState + var retVal interface{} + + for { + retVal, actState = evalFunc(actState) + + retValChan <- retVal + } + } + + retFunc := func() interface{} { + return <-retValChan + } + + go loopFunc() + + return retFunc +} + +// Builder for lazy evaluators with ints as result. +func BuildLazyIntEvaluator(evalFunc EvalFunc, initState interface{}) func() int { + ef := BuildLazyEvaluator(evalFunc, initState) + + return func() int { + return ef().(int) + } +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go new file mode 100644 index 0000000..1d713f8 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go @@ -0,0 +1,972 @@ +/* + Tideland Common Go Library - Unit Tests + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "bytes" + "fmt" + "log" + "rand" + "sort" + "strconv" + "strings" + "testing" + "time" +) + +//-------------------- +// TESTS +//-------------------- + +// Test single recovering. +func TestSingleRecovering(t *testing.T) { + s := NewSupervisor(nil) + ra := NewRecoverableAction(s) + + pos := ra.Action(PositiveAction) + + if pos == "OK" { + t.Logf("Single recovering (a) OK.") + } else { + t.Errorf("Single recovering (a) failed! Reply is '%v'.", pos) + } + + neg := ra.Action(FailAction) + + if neg == "Recovered" { + t.Logf("Single recovering (b) OK.") + } else { + t.Errorf("Single recovering (b) failed! Reply is '%v.", neg) + } +} + +// Test multiple recovering. +func TestMultipleRecovering(t *testing.T) { + s := NewSupervisor(nil) + raa := NewRecoverableAction(s) + rab := NewRecoverableAction(s) + rac := NewRecoverableAction(s) + + s.AddRecoverable("A", raa) + s.AddRecoverable("B", rab) + s.AddRecoverable("C", rac) + + t.Logf("(A) is '%v'.", raa.Action(FailAction)) + t.Logf("(B) is '%v'.", rab.Action(PositiveAction)) + t.Logf("(C) is '%v'.", rac.Action(PositiveAction)) +} + +// Test single heartbeat timeout. +func TestSingleHeartbeatTimeout(t *testing.T) { + ra := NewRecoverableAction(nil) + reply := ra.Action(TimeConsumingAction) + + if reply == "Recovered" { + t.Logf("Heartbeat timeout recovering OK.") + } else { + t.Errorf("Heartbeat timeout recovering failed! Reply is '%v.", reply) + } +} + +// Test multiple heartbeat timeout. +func TestMultipleHeartbeatTimeout(t *testing.T) { + s := NewSupervisor(nil) + raa := NewRecoverableAction(s) + rab := NewRecoverableAction(s) + rac := NewRecoverableAction(s) + + s.AddRecoverable("A", raa) + s.AddRecoverable("B", rab) + s.AddRecoverable("C", rac) + + t.Logf("(A) is '%v'.", raa.Action(TimeConsumingAction)) + t.Logf("(B) is '%v'.", rab.Action(PositiveAction)) + t.Logf("(C) is '%v'.", rac.Action(PositiveAction)) +} + +// Test the finite state machine successfully. +func TestFsmSuccess(t *testing.T) { + fsm := NewFSM(NewLoginHandler(), -1) + + fsm.Send(&LoginPayload{"yadda"}) + fsm.Send(&PreparePayload{"foo", "bar"}) + fsm.Send(&LoginPayload{"yaddaA"}) + fsm.Send(&LoginPayload{"yaddaB"}) + fsm.Send(&LoginPayload{"yaddaC"}) + fsm.Send(&LoginPayload{"yaddaD"}) + fsm.Send(&UnlockPayload{}) + fsm.Send(&LoginPayload{"bar"}) + + time.Sleep(1e7) + + t.Logf("Status: '%v'.", fsm.State()) +} + +// Test the finite state machine with timeout. +func TestFsmTimeout(t *testing.T) { + fsm := NewFSM(NewLoginHandler(), 1e5) + + fsm.Send(&LoginPayload{"yadda"}) + fsm.Send(&PreparePayload{"foo", "bar"}) + fsm.Send(&LoginPayload{"yaddaA"}) + fsm.Send(&LoginPayload{"yaddaB"}) + + time.Sleep(1e8) + + fsm.Send(&LoginPayload{"yaddaC"}) + fsm.Send(&LoginPayload{"yaddaD"}) + fsm.Send(&UnlockPayload{}) + fsm.Send(&LoginPayload{"bar"}) + + time.Sleep(1e7) + + t.Logf("Status: '%v'.", fsm.State()) +} + +// Test dispatching. +func TestDispatching(t *testing.T) { + tt := new(TT) + + v1, ok1 := Dispatch(tt, "Add", 4, 5) + v2, ok2 := Dispatch(tt, "Add", 4, 5, 6) + v3, ok3 := Dispatch(tt, "Mul", 4, 5, 6) + v4, ok4 := Dispatch(tt, "Mul", 4, 5, 6, 7, 8) + + t.Logf("Add 1: %v / %v\n", v1, ok1) + t.Logf("Add 2: %v / %v\n", v2, ok2) + t.Logf("Mul 1: %v / %v\n", v3, ok3) + t.Logf("Mul 2: %v / %v\n", v4, ok4) +} + +// Test debug statement. +func TestDebug(t *testing.T) { + Debug("Hello, I'm debugging %v!", "here") +} + +// Test nanoseconds calculation. +func TestNanoseconds(t *testing.T) { + t.Logf("Microseconds: %v\n", NsMicroseconds(4711)) + t.Logf("Milliseconds: %v\n", NsMilliseconds(4711)) + t.Logf("Seconds : %v\n", NsSeconds(4711)) + t.Logf("Minutes : %v\n", NsMinutes(4711)) + t.Logf("Hours : %v\n", NsHours(4711)) + t.Logf("Days : %v\n", NsDays(4711)) + t.Logf("Weeks : %v\n", NsWeeks(4711)) +} + +// Test time containments. +func TestTimeContainments(t *testing.T) { + now := time.UTC() + years := []int64{2008, 2009, 2010} + months := []int{3, 6, 9, 12} + days := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + hours := []int{20, 21, 22, 23} + minutes := []int{5, 10, 15, 20, 25, 30} + seconds := []int{0, 15, 30, 45} + weekdays := []int{time.Saturday, time.Sunday} + + t.Logf("Time is %s\n", now.Format(time.RFC822)) + t.Logf("Year in list : %t\n", YearInList(now, years)) + t.Logf("Year in range : %t\n", YearInRange(now, 2000, 2005)) + t.Logf("Month in list : %t\n", MonthInList(now, months)) + t.Logf("Month in range : %t\n", MonthInRange(now, 1, 6)) + t.Logf("Day in list : %t\n", DayInList(now, days)) + t.Logf("Day in range : %t\n", DayInRange(now, 15, 25)) + t.Logf("Hour in list : %t\n", HourInList(now, hours)) + t.Logf("Hour in range : %t\n", HourInRange(now, 9, 17)) + t.Logf("Minute in list : %t\n", MinuteInList(now, minutes)) + t.Logf("Minute in range : %t\n", MinuteInRange(now, 0, 29)) + t.Logf("Second in list : %t\n", SecondInList(now, seconds)) + t.Logf("Second in range : %t\n", SecondInRange(now, 30, 59)) + t.Logf("Weekday in list : %t\n", WeekdayInList(now, weekdays)) + t.Logf("Weekday in range: %t\n", WeekdayInRange(now, time.Monday, time.Friday)) +} + +// Test the UUID. +func TestUuid(t *testing.T) { + uuids := make(map[string]bool) + + t.Logf("Start generating UUIDs ...") + + for i := 0; i < 1000000; i++ { + uuid := NewUUID().String() + + if uuids[uuid] { + t.Fatalf("UUID collision") + } + + uuids[uuid] = true + } + + t.Logf("Done generating UUIDs!") +} + +// Test the creation of an identifier. +func TestIdentifier(t *testing.T) { + // Type as identifier. + var kvlf KeyValueLessFunc + + idp := TypeAsIdentifierPart(kvlf) + + if idp != "key-value-less-func" { + t.Errorf("Identifier part for KeyValueLessFunc is wrong, returned '%v'!", idp) + } + + idp = TypeAsIdentifierPart(NewUUID()) + + if idp != "u-u-i-d" { + t.Errorf("Identifier part for UUID is wrong, returned '%v'!", idp) + } + + // Identifier. + id := Identifier("One", 2, "three four") + + if id != "one:2:three-four" { + t.Errorf("First identifier is wrong! Id: %v", id) + } + + id = Identifier(2011, 6, 22, "One, two, or three things.") + + if id != "2011:6:22:one-two-or-three-things" { + t.Errorf("Second identifier is wrong! Id: %v", id) + } + + id = SepIdentifier("+", 1, "oNe", 2, "TWO", "3", "ÄÖÜ") + + if id != "1+one+2+two+3+äöü" { + t.Errorf("Third identifier is wrong! Id: %v", id) + } + + id = LimitedSepIdentifier("+", true, " ", 1, "oNe", 2, "TWO", "3", "ÄÖÜ", "Four", "+#-:,") + + if id != "1+one+2+two+3+four" { + t.Errorf("Fourth identifier is wrong! Id: %v", id) + } +} + +// Test the integer generator. +func TestLazyIntEvaluator(t *testing.T) { + fibFunc := func(s interface{}) (interface{}, interface{}) { + os := s.([]int) + v1 := os[0] + v2 := os[1] + ns := []int{v2, v1 + v2} + + return v1, ns + } + + fib := BuildLazyIntEvaluator(fibFunc, []int{0, 1}) + + var fibs [25]int + + for i := 0; i < 25; i++ { + fibs[i] = fib() + } + + t.Logf("FIBS: %v", fibs) +} + +// Test pivot. +func TestPivot(t *testing.T) { + a := make(sort.IntSlice, 15) + + for i := 0; i < len(a); i++ { + a[i] = rand.Intn(99) + } + + plo, phi := partition(a, 0, len(a)-1) + + t.Logf("PLO : %v", plo) + t.Logf("PHI : %v", phi) + t.Logf("PDATA: %v", a[phi-1]) + t.Logf("PIVOT: %v", a) +} + +// Test sort shootout. +func TestSort(t *testing.T) { + ola := generateTestOrdersList(25000) + olb := generateTestOrdersList(25000) + olc := generateTestOrdersList(25000) + old := generateTestOrdersList(25000) + + ta := time.Nanoseconds() + Sort(ola) + tb := time.Nanoseconds() + sort.Sort(olb) + tc := time.Nanoseconds() + insertionSort(olc, 0, len(olc)-1) + td := time.Nanoseconds() + sequentialQuickSort(old, 0, len(olc)-1) + te := time.Nanoseconds() + + t.Logf("PQS: %v", tb-ta) + t.Logf(" QS: %v", tc-tb) + t.Logf(" IS: %v", td-tc) + t.Logf("SQS: %v", te-td) +} + +// Test the parallel quicksort function. +func TestParallelQuickSort(t *testing.T) { + ol := generateTestOrdersList(10000) + + Sort(ol) + + cn := 0 + + for _, o := range ol { + if cn > o.CustomerNo { + t.Errorf("Customer No %v in wrong order!", o.CustomerNo) + + cn = o.CustomerNo + } else { + cn = o.CustomerNo + } + } +} + +// Test the MapReduce function. +func TestMapReduce(t *testing.T) { + // Start data producer. + + orderChan := generateTestOrders(2000) + + // Define map and reduce functions. + + mapFunc := func(in *KeyValue, mapEmitChan KeyValueChan) { + o := in.Value.(*Order) + + // Emit analysis data for each item. + + for _, i := range o.Items { + unitDiscount := (i.UnitPrice / 100.0) * i.DiscountPerc + totalDiscount := unitDiscount * float64(i.Count) + totalAmount := (i.UnitPrice - unitDiscount) * float64(i.Count) + analysis := &OrderItemAnalysis{i.ArticleNo, i.Count, totalAmount, totalDiscount} + articleNo := strconv.Itoa(i.ArticleNo) + + mapEmitChan <- &KeyValue{articleNo, analysis} + } + } + + reduceFunc := func(inChan KeyValueChan, reduceEmitChan KeyValueChan) { + memory := make(map[string]*OrderItemAnalysis) + + // Collect emitted analysis data. + + for kv := range inChan { + analysis := kv.Value.(*OrderItemAnalysis) + + if existing, ok := memory[kv.Key]; ok { + existing.Quantity += analysis.Quantity + existing.Amount += analysis.Amount + existing.Discount += analysis.Discount + } else { + memory[kv.Key] = analysis + } + } + + // Emit it to map/reduce caller. + + for articleNo, analysis := range memory { + reduceEmitChan <- &KeyValue{articleNo, analysis} + } + } + + // Now call MapReduce. + + for result := range SortedMapReduce(orderChan, mapFunc, 100, reduceFunc, 20, KeyLessFunc) { + t.Logf("%v\n", result.Value) + } +} + +// Test job. +func TestJob(t *testing.T) { + // Check function. + + cf := func(now *time.Time) (perform, delete bool) { + perform = now.Day == 1 && + now.Hour == 22 && + now.Minute == 0 && + SecondInList(now, []int{0, 10, 20, 30, 40, 50}) + delete = false + + return perform, delete + } + + // Task function. + + tf := func(id string) { t.Logf("Performed job %s\n", id) } + + // Job and time. + + job := NewJob("test-job-a", cf, tf) + time := time.LocalTime() + + // Test with non-matching time. + + time.Second = 1 + + job.checkAndPerform(time) + + // Test with matching time + + time.Day = 1 + time.Hour = 22 + time.Minute = 0 + time.Second = 0 + + job.checkAndPerform(time) +} + +// Test crontab keeping the job. +func TestCrontabKeep(t *testing.T) { + ctb := NewCrontab() + job := createJob(t, "keep", false) + + ctb.AddJob(job) + time.Sleep(10 * 1e9) + ctb.Stop() +} + +// Test crontab deleting the job. +func TestCrontabDelete(t *testing.T) { + ctb := NewCrontab() + job := createJob(t, "delete", true) + + ctb.AddJob(job) + time.Sleep(10 * 1e9) + ctb.Stop() +} + +// Test creating. +func TestSmlCreating(t *testing.T) { + root := createSmlStructure() + + t.Logf("Root: %v", root) +} + +// Test SML writer processing. +func TestSmlWriterProcessing(t *testing.T) { + root := createSmlStructure() + bufA := bytes.NewBufferString("") + bufB := bytes.NewBufferString("") + sppA := NewSmlWriterProcessor(bufA, true) + sppB := NewSmlWriterProcessor(bufB, false) + + root.ProcessWith(sppA) + root.ProcessWith(sppB) + + t.Logf("Print A: %v", bufA) + t.Logf("Print B: %v", bufB) +} + +// Test positive reading. +func TestSmlPositiveReading(t *testing.T) { + sml := "Before! {foo {bar:1:first Yadda ^{Test^} 1} {inbetween} {bar:2:last Yadda {Test ^^} 2}} After!" + reader := NewSmlReader(strings.NewReader(sml)) + + root, err := reader.RootTagNode() + + if err == nil { + t.Logf("Root:%v", root) + } else { + t.Errorf("Error: %v", err) + } +} + +// Test negative reading. +func TestSmlNegativeReading(t *testing.T) { + sml := "{Foo {bar:1 Yadda {test} {} 1} {bar:2 Yadda 2}}" + reader := NewSmlReader(strings.NewReader(sml)) + + root, err := reader.RootTagNode() + + if err == nil { + t.Errorf("Root: %v", root) + } else { + t.Logf("Error: %v", err) + } +} + +// Test of the ETM monitor. +func TestEtmMonitor(t *testing.T) { + mon := Monitor() + + // Generate measurings. + for i := 0; i < 500; i++ { + n := rand.Intn(10) + id := fmt.Sprintf("Work %d", n) + m := mon.BeginMeasuring(id) + + work(n * 5000) + + m.EndMeasuring() + } + + // Print, process with error, and print again. + mon.MeasuringPointsPrintAll() + + mon.MeasuringPointsDo(func(mp *MeasuringPoint) { + if mp.Count >= 25 { + // Divide by zero. + mp.Count = mp.Count / (mp.Count - mp.Count) + } + }) + + mon.MeasuringPointsPrintAll() +} + +// Test of the SSI monitor. +func TestSsiMonitor(t *testing.T) { + mon := Monitor() + + // Generate values. + for i := 0; i < 500; i++ { + n := rand.Intn(10) + id := fmt.Sprintf("Work %d", n) + + mon.SetValue(id, rand.Int63n(2001)-1000) + } + + // Print, process with error, and print again. + mon.StaySetVariablesPrintAll() + + mon.StaySetVariablesDo(func(ssv *StaySetVariable) { + if ssv.Count >= 25 { + // Divide by zero. + ssv.Count = ssv.Count / (ssv.Count - ssv.Count) + } + }) + + mon.StaySetVariablesPrintAll() +} + +// Test of the DSR monitor. +func TestDsrMonitor(t *testing.T) { + mon := Monitor() + + mon.Register("monitor:dsr:a", func() string { return "A" }) + mon.Register("monitor:dsr:b", func() string { return "4711" }) + mon.Register("monitor:dsr:c", func() string { return "2011-05-07" }) + + mon.DynamicStatusValuesPrintAll() +} + +//-------------------- +// HELPERS +//-------------------- + +// Test type. +type TT struct{} + +func (tt *TT) Add(a, b int) int { return a + b } + +func (tt *TT) Mul(a, b, c, d, e int) int { return a * b * c * d * e } + +// Order item type. +type OrderItem struct { + ArticleNo int + Count int + UnitPrice float64 + DiscountPerc float64 +} + +// Order type. +type Order struct { + OrderNo UUID + CustomerNo int + Items []*OrderItem +} + +func (o *Order) String() string { + msg := "ON: %v / CN: %4v / I: %v" + + return fmt.Sprintf(msg, o.OrderNo, o.CustomerNo, len(o.Items)) +} + +// Order item analysis type. +type OrderItemAnalysis struct { + ArticleNo int + Quantity int + Amount float64 + Discount float64 +} + +func (oia *OrderItemAnalysis) String() string { + msg := "AN: %5v / Q: %4v / A: %10.2f € / D: %10.2f €" + + return fmt.Sprintf(msg, oia.ArticleNo, oia.Quantity, oia.Amount, oia.Discount) +} + +// Order list. +type OrderList []*Order + +func (l OrderList) Len() int { + return len(l) +} + +func (l OrderList) Less(i, j int) bool { + return l[i].CustomerNo < l[j].CustomerNo +} + +func (l OrderList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +// Action function. +type Action func() string + +// A positive action. +func PositiveAction() string { + log.Printf("Perform positive action.") + + return "OK" +} + +// A failing action. +func FailAction() string { + log.Printf("Perform failing action!") + + panic("Fail!") + + return "Fail!" +} + +// A time consuming action. +func TimeConsumingAction() string { + log.Printf("Perform time consuming action!") + + time.Sleep(3e8) + + return "Time consumed" +} + +// Recoverable action type. +type RecoverableAction struct { + actionChan chan Action + replyChan chan string + supervisor *Supervisor + heartbeat *Heartbeat +} + +// Create a new recoverable action. +func NewRecoverableAction(supervisor *Supervisor) *RecoverableAction { + ra := &RecoverableAction{ + actionChan: make(chan Action), + replyChan: make(chan string, 5), + supervisor: supervisor, + } + + ra.heartbeat = NewHeartbeat(ra, 1e8) + + go ra.backend() + + return ra +} + +// Send an action to perform. +func (ra *RecoverableAction) Action(action Action) string { + ra.actionChan <- action + + return <-ra.replyChan +} + +// Implement Supervisor() of the recoverable interface. +func (ra *RecoverableAction) Supervisor() *Supervisor { + return ra.supervisor +} + +// Implement Recover() of the recoverable interface. +func (ra *RecoverableAction) Recover(r Recoverable, err interface{}) { + if ra == r { + log.Printf("Recovering error '%v'!", err) + + ra.replyChan <- "Recovered" + + go ra.backend() + } +} + +// Backend of the recoverable action. +func (ra *RecoverableAction) backend() { + defer func() { + HelpIfNeeded(ra, recover()) + }() + + for { + select { + case action := <-ra.actionChan: + ra.replyChan <- action() + case h := <-ra.heartbeat.HeartbeatChan: + ImAlive(h) + } + } +} + +// Generate a test order. +func generateTestOrders(count int) KeyValueChan { + articleMaxNo := 9999 + unitPrices := make([]float64, articleMaxNo+1) + + for i := 0; i < articleMaxNo+1; i++ { + unitPrices[i] = rand.Float64() * 100.0 + } + + kvc := make(KeyValueChan) + + go func() { + for i := 0; i < count; i++ { + order := new(Order) + + order.OrderNo = NewUUID() + order.CustomerNo = rand.Intn(999) + 1 + order.Items = make([]*OrderItem, rand.Intn(9)+1) + + for j := 0; j < len(order.Items); j++ { + articleNo := rand.Intn(articleMaxNo) + + order.Items[j] = &OrderItem{ + ArticleNo: articleNo, + Count: rand.Intn(9) + 1, + UnitPrice: unitPrices[articleNo], + DiscountPerc: rand.Float64() * 4.0, + } + } + + kvc <- &KeyValue{order.OrderNo.String(), order} + } + + close(kvc) + }() + + return kvc +} + +// Generate a list with test orders. +func generateTestOrdersList(count int) OrderList { + l := make(OrderList, count) + idx := 0 + + for kv := range generateTestOrders(count) { + l[idx] = kv.Value.(*Order) + + idx++ + } + + return l +} + +// Create a job that leads to a an event every 2 seconds. +func createJob(t *testing.T, descr string, delete bool) *Job { + cf := func(now *time.Time) (bool, bool) { return now.Seconds()%2 == 0, delete } + tf := func(id string) { t.Logf("Performed job %s\n", id) } + + return NewJob("test-server-"+descr, cf, tf) +} + +// Create a SML structure. +func createSmlStructure() *TagNode { + root := NewTagNode("root") + + root.AppendText("Text A") + root.AppendText("Text B") + + root.AppendTaggedText("comment", "A first comment.") + + subA := root.AppendTag("sub-a:1st:important") + + subA.AppendText("Text A.A") + + root.AppendTaggedText("comment", "A second comment.") + + subB := root.AppendTag("sub-b:2nd") + + subB.AppendText("Text B.A") + subB.AppendTaggedText("raw", "Any raw text with {, }, and ^.") + + return root +} + +// Do some work. +func work(n int) int { + if n < 0 { + return 0 + } + + return n * work(n-1) +} + +//-------------------- +// TEST LOGIN EVENT HANDLER +//-------------------- + +// Prepare payload. +type PreparePayload struct { + userId string + password string +} + +// Login payload. +type LoginPayload struct { + password string +} + +// Reset payload. +type ResetPayload struct{} + +// Unlock payload. +type UnlockPayload struct{} + +// Login handler tyoe. +type LoginHandler struct { + userId string + password string + illegalLoginCounter int + locked bool +} + +// Create a new login handler. +func NewLoginHandler() *LoginHandler { + return new(LoginHandler) +} + +// Return the initial state. +func (lh *LoginHandler) Init() string { + return "New" +} + +// Terminate the handler. +func (lh *LoginHandler) Terminate(string, interface{}) string { + return "LoggedIn" +} + +// Handler for state: "New". +func (lh *LoginHandler) HandleStateNew(c *Condition) (string, interface{}) { + switch pld := c.Payload.(type) { + case *PreparePayload: + lh.userId = pld.userId + lh.password = pld.password + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' prepared.", lh.userId) + + return "Authenticating", nil + case *LoginPayload: + log.Printf("Illegal login, handler not initialized!") + + return "New", false + case Timeout: + log.Printf("Timeout, terminate handler!") + + return "Terminate", nil + } + + log.Printf("Illegal payload '%v' during state 'new'!", c.Payload) + + return "New", nil +} + +// Handler for state: "Authenticating". +func (lh *LoginHandler) HandleStateAuthenticating(c *Condition) (string, interface{}) { + switch pld := c.Payload.(type) { + case *LoginPayload: + if pld.password == lh.password { + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' logged in.", lh.userId) + + return "Terminate", true + } + + log.Printf("User '%v' used illegal password.", lh.userId) + + lh.illegalLoginCounter++ + + if lh.illegalLoginCounter == 3 { + lh.locked = true + + log.Printf("User '%v' locked!", lh.userId) + + return "Locked", false + } + + return "Authenticating", false + case *UnlockPayload: + log.Printf("No need to unlock user '%v'!", lh.userId) + + return "Authenticating", nil + case *ResetPayload, Timeout: + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' resetted.", lh.userId) + + return "Authenticating", nil + } + + log.Printf("Illegal payload '%v' during state 'authenticating'!", c.Payload) + + return "Authenticating", nil +} + +// Handler for state: "Locked". +func (lh *LoginHandler) HandleStateLocked(c *Condition) (string, interface{}) { + switch pld := c.Payload.(type) { + case *LoginPayload: + log.Printf("User '%v' login rejected, user is locked!", lh.userId) + + return "Locked", false + case *ResetPayload, *UnlockPayload, Timeout: + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' resetted / unlocked.", lh.userId) + + return "Authenticating", nil + } + + log.Printf("Illegal payload '%v' during state 'loacked'!", c.Payload) + + return "Locked", nil +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go new file mode 100644 index 0000000..bf0dc9b --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go @@ -0,0 +1,244 @@ +/* + Tideland Common Go Library - Finite State Machine + + Copyright (C) 2010-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "log" + "reflect" + "strings" + "time" +) + +//-------------------- +// HELPER TYPES +//-------------------- + +// Condition type. +type Condition struct { + Now int64 + Payload interface{} +} + +// Transition type. +type transition struct { + payload interface{} + resultChan chan interface{} +} + +// Timeout type. +type Timeout int64 + +//-------------------- +// FINITE STATE MACHINE +//-------------------- + +// Handler interface. +type Handler interface { + Init() string + Terminate(string, interface{}) string +} + +// State machine type. +type FSM struct { + Handler Handler + handlerValue reflect.Value + handlerFuncs map[string]reflect.Value + state string + transitionChan chan *transition + timeoutChan <-chan int64 +} + +// Create a new finite state machine. +func NewFSM(h Handler, timeout int64) *FSM { + var bufferSize int + + if timeout > 0 { + bufferSize = int(timeout / 1e3) + } else { + bufferSize = 10 + } + + fsm := &FSM{ + Handler: h, + handlerFuncs: make(map[string]reflect.Value), + state: h.Init(), + transitionChan: make(chan *transition, bufferSize), + } + + if timeout > 0 { + fsm.timeoutChan = time.After(timeout) + } + + fsm.analyze() + + go fsm.backend() + + return fsm +} + +// Send a payload to handle and return the result. +func (fsm *FSM) SendWithResult(payload interface{}) interface{} { + t := &transition{payload, make(chan interface{})} + + fsm.transitionChan <- t + + return <-t.resultChan +} + +// Send a payload with no result. +func (fsm *FSM) Send(payload interface{}) { + t := &transition{payload, nil} + + fsm.transitionChan <- t +} + +// Send a payload with no result after a given time. +func (fsm *FSM) SendAfter(payload interface{}, ns int64) { + saf := func() { + time.Sleep(ns) + + fsm.Send(payload) + } + + go saf() +} + +// Return the current state. +func (fsm *FSM) State() string { + return fsm.state +} + +// Return the supervisor. +func (fsm *FSM) Supervisor() *Supervisor { + return GlobalSupervisor() +} + +// Recover after an error. +func (fsm *FSM) Recover(recoverable Recoverable, err interface{}) { + log.Printf("[cgl] recovering finite state machine server backend after error '%v'!", err) + + go fsm.backend() +} + +// Analyze the event handler and prepare the state table. +func (fsm *FSM) analyze() { + prefix := "HandleState" + + fsm.handlerValue = reflect.ValueOf(fsm.Handler) + + num := fsm.handlerValue.Type().NumMethod() + + for i := 0; i < num; i++ { + meth := fsm.handlerValue.Type().Method(i) + + if (meth.PkgPath == "") && (strings.HasPrefix(meth.Name, prefix)) { + if (meth.Type.NumIn() == 2) && (meth.Type.NumOut() == 2) { + state := meth.Name[len(prefix):len(meth.Name)] + + fsm.handlerFuncs[state] = meth.Func + } + } + } +} + +// State machine backend. +func (fsm *FSM) backend() { + defer func() { + HelpIfNeeded(fsm, recover()) + }() + + // Message loop. + + for { + select { + case t := <-fsm.transitionChan: + // Regular transition. + + if nextState, ok := fsm.handle(t); ok { + // Continue. + + fsm.state = nextState + } else { + // Stop processing. + + fsm.state = fsm.Handler.Terminate(fsm.state, nextState) + + return + } + case to := <-fsm.timeoutChan: + // Timeout signal resent to let it be handled. + + t := &transition{Timeout(to), nil} + + fsm.transitionChan <- t + } + } +} + +// Handle a transition. +func (fsm *FSM) handle(t *transition) (string, bool) { + condition := &Condition{time.Nanoseconds(), t.payload} + handlerFunc := fsm.handlerFuncs[fsm.state] + handlerArgs := make([]reflect.Value, 2) + + handlerArgs[0] = fsm.handlerValue + handlerArgs[1] = reflect.ValueOf(condition) + + results := handlerFunc.Call(handlerArgs) + + nextState := results[0].Interface().(string) + result := results[1].Interface() + + // Return a result if wanted. + + if t.resultChan != nil { + t.resultChan <- result + } + + // Check for termination. + + if nextState == "Terminate" { + return nextState, false + } + + return nextState, true +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go new file mode 100644 index 0000000..6747358 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go @@ -0,0 +1,569 @@ +/* + Tideland Common Go Library - Monitoring + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "fmt" + "io" + "log" + "os" + "time" +) + +//-------------------- +// GLOBAL VARIABLES +//-------------------- + +var monitor *SystemMonitor + +//-------------------- +// CONSTANTS +//-------------------- + +const ( + etmTLine = "+------------------------------------------+-----------+-----------+-----------+-----------+---------------+-----------+\n" + etmHeader = "| Name | Count | Min Time | Max Time | Avg Time | Total Time | Op/Sec |\n" + etmFormat = "| %-40s | %9d | %9.3f | %9.3f | %9.3f | %13.3f | %9d |\n" + etmFooter = "| All times in milliseconds. |\n" + etmELine = "+----------------------------------------------------------------------------------------------------------------------+\n" + + ssiTLine = "+------------------------------------------+-----------+---------------+---------------+---------------+---------------+\n" + ssiHeader = "| Name | Count | Act Value | Min Value | Max Value | Avg Value |\n" + ssiFormat = "| %-40s | %9d | %13d | %13d | %13d | %13d |\n" + + dsrTLine = "+------------------------------------------+---------------------------------------------------------------------------+\n" + dsrHeader = "| Name | Value |\n" + dsrFormat = "| %-40s | %-73s |\n" +) + +const ( + cmdMeasuringPointsMap = iota + cmdMeasuringPointsDo + cmdStaySetVariablesMap + cmdStaySetVariablesDo + cmdDynamicStatusRetrieversMap + cmdDynamicStatusRetrieversDo +) + +//-------------------- +// MONITORING +//-------------------- + +// Command encapsulated the data for any command. +type command struct { + opCode int + args interface{} + respChan chan interface{} +} + +// The system monitor type. +type SystemMonitor struct { + etmData map[string]*MeasuringPoint + ssiData map[string]*StaySetVariable + dsrData map[string]DynamicStatusRetriever + measuringChan chan *Measuring + valueChan chan *value + retrieverRegistrationChan chan *retrieverRegistration + commandChan chan *command +} + +// Monitor returns the system monitor if it exists. +// Otherwise it creates it first. +func Monitor() *SystemMonitor { + if monitor == nil { + // Create system monitor. + monitor = &SystemMonitor{ + etmData: make(map[string]*MeasuringPoint), + ssiData: make(map[string]*StaySetVariable), + dsrData: make(map[string]DynamicStatusRetriever), + measuringChan: make(chan *Measuring, 1000), + valueChan: make(chan *value, 1000), + retrieverRegistrationChan: make(chan *retrieverRegistration, 10), + commandChan: make(chan *command), + } + + go monitor.backend() + } + + return monitor +} + +// BeginMeasuring starts a new measuring with a given id. +// All measurings with the same id will be aggregated. +func (sm *SystemMonitor) BeginMeasuring(id string) *Measuring { + return &Measuring{sm, id, time.Nanoseconds(), 0} +} + +// Measure the execution of a function. +func (sm *SystemMonitor) Measure(id string, f func()) { + m := sm.BeginMeasuring(id) + + f() + + m.EndMeasuring() +} + +// MeasuringPointsMap performs the function f for all measuring points +// and returns a slice with the return values of the function that are +// not nil. +func (sm *SystemMonitor) MeasuringPointsMap(f func(*MeasuringPoint) interface{}) []interface{} { + cmd := &command{cmdMeasuringPointsMap, f, make(chan interface{})} + + sm.commandChan <- cmd + + resp := <-cmd.respChan + + return resp.([]interface{}) +} + +// MeasuringPointsDo performs the function f for +// all measuring points. +func (sm *SystemMonitor) MeasuringPointsDo(f func(*MeasuringPoint)) { + cmd := &command{cmdMeasuringPointsDo, f, nil} + + sm.commandChan <- cmd +} + +// MeasuringPointsWrite prints the measuring points for which +// the passed function returns true to the passed writer. +func (sm *SystemMonitor) MeasuringPointsWrite(w io.Writer, ff func(*MeasuringPoint) bool) { + pf := func(t int64) float64 { return float64(t) / 1000000.0 } + + fmt.Fprint(w, etmTLine) + fmt.Fprint(w, etmHeader) + fmt.Fprint(w, etmTLine) + + lines := sm.MeasuringPointsMap(func(mp *MeasuringPoint) interface{} { + if ff(mp) { + ops := 1e9 / mp.AvgTime + + return fmt.Sprintf(etmFormat, mp.Id, mp.Count, pf(mp.MinTime), pf(mp.MaxTime), pf(mp.AvgTime), pf(mp.TtlTime), ops) + } + + return nil + }) + + for _, line := range lines { + fmt.Fprint(w, line) + } + + fmt.Fprint(w, etmTLine) + fmt.Fprint(w, etmFooter) + fmt.Fprint(w, etmELine) +} + +// MeasuringPointsPrintAll prints all measuring points +// to STDOUT. +func (sm *SystemMonitor) MeasuringPointsPrintAll() { + sm.MeasuringPointsWrite(os.Stdout, func(mp *MeasuringPoint) bool { return true }) +} + +// SetValue sets a value of a stay-set variable. +func (sm *SystemMonitor) SetValue(id string, v int64) { + sm.valueChan <- &value{id, v} +} + +// StaySetVariablesMap performs the function f for all variables +// and returns a slice with the return values of the function that are +// not nil. +func (sm *SystemMonitor) StaySetVariablesMap(f func(*StaySetVariable) interface{}) []interface{} { + cmd := &command{cmdStaySetVariablesMap, f, make(chan interface{})} + + sm.commandChan <- cmd + + resp := <-cmd.respChan + + return resp.([]interface{}) +} + +// StaySetVariablesDo performs the function f for all +// variables. +func (sm *SystemMonitor) StaySetVariablesDo(f func(*StaySetVariable)) { + cmd := &command{cmdStaySetVariablesDo, f, nil} + + sm.commandChan <- cmd +} + +// StaySetVariablesWrite prints the stay-set variables for which +// the passed function returns true to the passed writer. +func (sm *SystemMonitor) StaySetVariablesWrite(w io.Writer, ff func(*StaySetVariable) bool) { + fmt.Fprint(w, ssiTLine) + fmt.Fprint(w, ssiHeader) + fmt.Fprint(w, ssiTLine) + + lines := sm.StaySetVariablesMap(func(ssv *StaySetVariable) interface{} { + if ff(ssv) { + return fmt.Sprintf(ssiFormat, ssv.Id, ssv.Count, ssv.ActValue, ssv.MinValue, ssv.MaxValue, ssv.AvgValue) + } + + return nil + }) + + for _, line := range lines { + fmt.Fprint(w, line) + } + + fmt.Fprint(w, ssiTLine) +} + +// StaySetVariablesPrintAll prints all stay-set variables +// to STDOUT. +func (sm *SystemMonitor) StaySetVariablesPrintAll() { + sm.StaySetVariablesWrite(os.Stdout, func(ssv *StaySetVariable) bool { return true }) +} + +// Register registers a new dynamic status retriever function. +func (sm *SystemMonitor) Register(id string, rf DynamicStatusRetriever) { + sm.retrieverRegistrationChan <- &retrieverRegistration{id, rf} +} + +// Unregister unregisters a dynamic status retriever function. +func (sm *SystemMonitor) Unregister(id string) { + sm.retrieverRegistrationChan <- &retrieverRegistration{id, nil} +} + +// DynamicStatusValuesMap performs the function f for all status values +// and returns a slice with the return values of the function that are +// not nil. +func (sm *SystemMonitor) DynamicStatusValuesMap(f func(string, string) interface{}) []interface{} { + cmd := &command{cmdDynamicStatusRetrieversMap, f, make(chan interface{})} + + sm.commandChan <- cmd + + resp := <-cmd.respChan + + return resp.([]interface{}) +} + +// DynamicStatusValuesDo performs the function f for all +// status values. +func (sm *SystemMonitor) DynamicStatusValuesDo(f func(string, string)) { + cmd := &command{cmdDynamicStatusRetrieversDo, f, nil} + + sm.commandChan <- cmd +} + +// DynamicStatusValuesWrite prints the status values for which +// the passed function returns true to the passed writer. +func (sm *SystemMonitor) DynamicStatusValuesWrite(w io.Writer, ff func(string, string) bool) { + fmt.Fprint(w, dsrTLine) + fmt.Fprint(w, dsrHeader) + fmt.Fprint(w, dsrTLine) + + lines := sm.DynamicStatusValuesMap(func(id, dsv string) interface{} { + if ff(id, dsv) { + return fmt.Sprintf(dsrFormat, id, dsv) + } + + return nil + }) + + for _, line := range lines { + fmt.Fprint(w, line) + } + + fmt.Fprint(w, dsrTLine) +} + +// DynamicStatusValuesPrintAll prints all status values to STDOUT. +func (sm *SystemMonitor) DynamicStatusValuesPrintAll() { + sm.DynamicStatusValuesWrite(os.Stdout, func(id, dsv string) bool { return true }) +} + +// Return the supervisor. +func (sm *SystemMonitor) Supervisor() *Supervisor { + return GlobalSupervisor() +} + +// Recover after an error. +func (sm *SystemMonitor) Recover(recoverable Recoverable, err interface{}) { + log.Printf("[cgl] recovering system monitor backend after error '%v'!", err) + + go sm.backend() +} + +// Backend of the system monitor. +func (sm *SystemMonitor) backend() { + defer func() { + HelpIfNeeded(sm, recover()) + }() + + for { + select { + case measuring := <-sm.measuringChan: + // Received a new measuring. + if mp, ok := sm.etmData[measuring.id]; ok { + // Measuring point found. + mp.update(measuring) + } else { + // New measuring point. + sm.etmData[measuring.id] = newMeasuringPoint(measuring) + } + case value := <-sm.valueChan: + // Received a new value. + if ssv, ok := sm.ssiData[value.id]; ok { + // Variable found. + ssv.update(value) + } else { + // New stay-set variable. + sm.ssiData[value.id] = newStaySetVariable(value) + } + case registration := <-sm.retrieverRegistrationChan: + // Received a new retriever for registration. + if registration.dsr != nil { + // Register a new retriever. + sm.dsrData[registration.id] = registration.dsr + } else { + // Deregister a retriever. + if dsr, ok := sm.dsrData[registration.id]; ok { + sm.dsrData[registration.id] = dsr, false + } + } + case cmd := <-sm.commandChan: + // Receivedd a command to process. + sm.processCommand(cmd) + } + } +} + +// Process a command. +func (sm *SystemMonitor) processCommand(cmd *command) { + switch cmd.opCode { + case cmdMeasuringPointsMap: + // Map the measuring points. + var resp []interface{} + + f := cmd.args.(func(*MeasuringPoint) interface{}) + + for _, mp := range sm.etmData { + v := f(mp) + + if v != nil { + resp = append(resp, v) + } + } + + cmd.respChan <- resp + case cmdMeasuringPointsDo: + // Iterate over the measurings. + f := cmd.args.(func(*MeasuringPoint)) + + for _, mp := range sm.etmData { + f(mp) + } + case cmdStaySetVariablesMap: + // Map the stay-set variables. + var resp []interface{} + + f := cmd.args.(func(*StaySetVariable) interface{}) + + for _, ssv := range sm.ssiData { + v := f(ssv) + + if v != nil { + resp = append(resp, v) + } + } + + cmd.respChan <- resp + case cmdStaySetVariablesDo: + // Iterate over the stay-set variables. + f := cmd.args.(func(*StaySetVariable)) + + for _, ssv := range sm.ssiData { + f(ssv) + } + case cmdDynamicStatusRetrieversMap: + // Map the return values of the dynamic status + // retriever functions. + var resp []interface{} + + f := cmd.args.(func(string, string) interface{}) + + for id, dsr := range sm.dsrData { + dsv := dsr() + v := f(id, dsv) + + if v != nil { + resp = append(resp, v) + } + } + + cmd.respChan <- resp + case cmdDynamicStatusRetrieversDo: + // Iterate over the return values of the + // dynamic status retriever functions. + f := cmd.args.(func(string, string)) + + for id, dsr := range sm.dsrData { + dsv := dsr() + + f(id, dsv) + } + } +} + +//-------------------- +// ADDITIONAL MEASURING TYPES +//-------------------- + +// Measuring contains one measuring. +type Measuring struct { + systemMonitor *SystemMonitor + id string + startTime int64 + endTime int64 +} + +// EndMEasuring ends a measuring and passes it to the +// measuring server in the background. +func (m *Measuring) EndMeasuring() int64 { + m.endTime = time.Nanoseconds() + + m.systemMonitor.measuringChan <- m + + return m.endTime - m.startTime +} + +// MeasuringPoint contains the cumulated measuring +// data of one measuring point. +type MeasuringPoint struct { + Id string + Count int64 + MinTime int64 + MaxTime int64 + TtlTime int64 + AvgTime int64 +} + +// Create a new measuring point out of a measuring. +func newMeasuringPoint(m *Measuring) *MeasuringPoint { + time := m.endTime - m.startTime + mp := &MeasuringPoint{ + Id: m.id, + Count: 1, + MinTime: time, + MaxTime: time, + TtlTime: time, + AvgTime: time, + } + + return mp +} + +// Update a measuring point with a measuring. +func (mp *MeasuringPoint) update(m *Measuring) { + time := m.endTime - m.startTime + + mp.Count++ + + if mp.MinTime > time { + mp.MinTime = time + } + + if mp.MaxTime < time { + mp.MaxTime = time + } + + mp.TtlTime += time + mp.AvgTime = mp.TtlTime / mp.Count +} + +// New value for a stay-set variable. +type value struct { + id string + value int64 +} + +// StaySetVariable contains the cumulated values +// for one stay-set variable. +type StaySetVariable struct { + Id string + Count int64 + ActValue int64 + MinValue int64 + MaxValue int64 + AvgValue int64 + total int64 +} + +// Create a new stay-set variable out of a value. +func newStaySetVariable(v *value) *StaySetVariable { + ssv := &StaySetVariable{ + Id: v.id, + Count: 1, + ActValue: v.value, + MinValue: v.value, + MaxValue: v.value, + AvgValue: v.value, + } + + return ssv +} + +// Update a stay-set variable with a value. +func (ssv *StaySetVariable) update(v *value) { + ssv.Count++ + + ssv.ActValue = v.value + ssv.total += v.value + + if ssv.MinValue > ssv.ActValue { + ssv.MinValue = ssv.ActValue + } + + if ssv.MaxValue < ssv.ActValue { + ssv.MaxValue = ssv.ActValue + } + + ssv.AvgValue = ssv.total / ssv.Count +} + +// DynamicStatusRetriever is called by the server and +// returns a current status as string. +type DynamicStatusRetriever func() string + +// New registration of a retriever function. +type retrieverRegistration struct { + id string + dsr DynamicStatusRetriever +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go new file mode 100644 index 0000000..c6e4e01 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go @@ -0,0 +1,490 @@ +/* + Tideland Common Go Library - Simple Markup Language + + Copyright (C) 2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "strings" + "unicode" +) + +//-------------------- +// PROCESSOR +//-------------------- + +// Processor interface. +type Processor interface { + OpenTag(tag []string) + CloseTag(tag []string) + Text(text string) +} + +//-------------------- +// NODE +//-------------------- + +// The node. +type Node interface { + Len() int + ProcessWith(p Processor) +} + +//-------------------- +// TAG NODE +//-------------------- + +// The tag node. +type TagNode struct { + tag []string + children []Node +} + +// Create a new tag node. +func NewTagNode(tag string) *TagNode { + tmp := strings.ToLower(tag) + + if !validIdentifier(tmp) { + return nil + } + + tn := &TagNode{ + tag: strings.Split(tmp, ":"), + children: make([]Node, 0), + } + + return tn +} + +// Append a new tag. +func (tn *TagNode) AppendTag(tag string) *TagNode { + n := NewTagNode(tag) + + if n != nil { + tn.children = append(tn.children, n) + } + + return n +} + +// Append a tag node. +func (tn *TagNode) AppendTagNode(n *TagNode) *TagNode { + tn.children = append(tn.children, n) + + return n +} + +// Append a text node. +func (tn *TagNode) AppendText(text string) *TextNode { + n := NewTextNode(text) + + tn.children = append(tn.children, n) + + return n +} + +// Append a tagged text node. +func (tn *TagNode) AppendTaggedText(tag, text string) *TagNode { + n := NewTagNode(tag) + + if n != nil { + n.AppendText(text) + + tn.children = append(tn.children, n) + } + + return n +} + +// Append a text node. +func (tn *TagNode) AppendTextNode(n *TextNode) *TextNode { + tn.children = append(tn.children, n) + + return n +} + +// Return the len of the tag node (aka number of children). +func (tn *TagNode) Len() int { + return len(tn.children) +} + +// Process the node. +func (tn *TagNode) ProcessWith(p Processor) { + p.OpenTag(tn.tag) + + for _, child := range tn.children { + child.ProcessWith(p) + } + + p.CloseTag(tn.tag) +} + +// Return the node as a string. +func (tn *TagNode) String() string { + buf := bytes.NewBufferString("") + spp := NewSmlWriterProcessor(buf, true) + + tn.ProcessWith(spp) + + return buf.String() +} + +//-------------------- +// TEXT NODE +//-------------------- + +// The text node. +type TextNode struct { + text string +} + +// Create a new text node. +func NewTextNode(text string) *TextNode { + return &TextNode{text} +} + +// Return the len of the text node. +func (tn *TextNode) Len() int { + return len(tn.text) +} + +// Process the node. +func (tn *TextNode) ProcessWith(p Processor) { + p.Text(tn.text) +} + +// Return the node as a string. +func (tn *TextNode) String() string { + return tn.text +} + +//-------------------- +// PRIVATE FUNCTIONS +//-------------------- + +// Check an identifier (tag or id). +func validIdentifier(id string) bool { + for _, c := range id { + if c < 'a' || c > 'z' { + if c < '0' || c > '9' { + if c != '-' && c != ':' { + return false + } + } + } + } + + return true +} + +//-------------------- +// SML READER +//-------------------- + +// Control values. +const ( + ctrlText = iota + ctrlSpace + ctrlOpen + ctrlClose + ctrlEscape + ctrlTag + ctrlEOF + ctrlInvalid +) + +// Node read modes. +const ( + modeInit = iota + modeTag + modeText +) + +// Reader for SML. +type SmlReader struct { + reader *bufio.Reader + index int + root *TagNode + error os.Error +} + +// Create the reader. +func NewSmlReader(reader io.Reader) *SmlReader { + // Init the reader. + + sr := &SmlReader{ + reader: bufio.NewReader(reader), + index: -1, + } + + node, ctrl := sr.readNode() + + switch ctrl { + case ctrlClose: + sr.root = node + sr.error = nil + case ctrlEOF: + msg := fmt.Sprintf("eof too early at index %v", sr.index) + + sr.error = os.NewError(msg) + case ctrlInvalid: + msg := fmt.Sprintf("invalid rune at index %v", sr.index) + + sr.error = os.NewError(msg) + } + + return sr +} + +// Return the root tag node. +func (sr *SmlReader) RootTagNode() (*TagNode, os.Error) { + return sr.root, sr.error +} + +// Read a node. +func (sr *SmlReader) readNode() (*TagNode, int) { + var node *TagNode + var buffer *bytes.Buffer + + mode := modeInit + + for { + rune, ctrl := sr.readRune() + + sr.index++ + + switch mode { + case modeInit: + // Before the first opening bracket. + switch ctrl { + case ctrlEOF: + return nil, ctrlEOF + case ctrlOpen: + mode = modeTag + buffer = bytes.NewBufferString("") + } + case modeTag: + // Reading a tag. + switch ctrl { + case ctrlEOF: + return nil, ctrlEOF + case ctrlTag: + buffer.WriteRune(rune) + case ctrlSpace: + if buffer.Len() == 0 { + return nil, ctrlInvalid + } + + node = NewTagNode(buffer.String()) + buffer = bytes.NewBufferString("") + mode = modeText + case ctrlClose: + if buffer.Len() == 0 { + return nil, ctrlInvalid + } + + node = NewTagNode(buffer.String()) + + return node, ctrlClose + default: + return nil, ctrlInvalid + } + case modeText: + // Reading the text including the subnodes following + // the space after the tag or id. + switch ctrl { + case ctrlEOF: + return nil, ctrlEOF + case ctrlOpen: + text := strings.TrimSpace(buffer.String()) + + if len(text) > 0 { + node.AppendText(text) + } + + buffer = bytes.NewBufferString("") + + sr.reader.UnreadRune() + + subnode, subctrl := sr.readNode() + + if subctrl == ctrlClose { + // Correct closed subnode. + + node.AppendTagNode(subnode) + } else { + // Error while reading the subnode. + + return nil, subctrl + } + case ctrlClose: + text := strings.TrimSpace(buffer.String()) + + if len(text) > 0 { + node.AppendText(text) + } + + return node, ctrlClose + case ctrlEscape: + rune, ctrl = sr.readRune() + + if ctrl == ctrlOpen || ctrl == ctrlClose || ctrl == ctrlEscape { + buffer.WriteRune(rune) + + sr.index++ + } else { + return nil, ctrlInvalid + } + default: + buffer.WriteRune(rune) + } + } + } + + return nil, ctrlEOF +} + +// Read a rune. +func (sr *SmlReader) readRune() (rune, control int) { + var size int + + rune, size, sr.error = sr.reader.ReadRune() + + switch { + case size == 0: + return rune, ctrlEOF + case rune == '{': + return rune, ctrlOpen + case rune == '}': + return rune, ctrlClose + case rune == '^': + return rune, ctrlEscape + case rune >= 'a' && rune <= 'z': + return rune, ctrlTag + case rune >= 'A' && rune <= 'Z': + return rune, ctrlTag + case rune >= '0' && rune <= '9': + return rune, ctrlTag + case rune == '-': + return rune, ctrlTag + case rune == ':': + return rune, ctrlTag + case unicode.IsSpace(rune): + return rune, ctrlSpace + } + + return rune, ctrlText +} + +//-------------------- +// SML WRITER PROCESSOR +//-------------------- + +// Processor for writing SML. +type SmlWriterProcessor struct { + writer *bufio.Writer + prettyPrint bool + indentLevel int +} + +// Create a new SML writer processor. +func NewSmlWriterProcessor(writer io.Writer, prettyPrint bool) *SmlWriterProcessor { + swp := &SmlWriterProcessor{ + writer: bufio.NewWriter(writer), + prettyPrint: prettyPrint, + indentLevel: 0, + } + + return swp +} + +// Open a tag. +func (swp *SmlWriterProcessor) OpenTag(tag []string) { + swp.writeIndent(true) + + swp.writer.WriteString("{") + swp.writer.WriteString(strings.Join(tag, ":")) +} + +// Close a tag. +func (swp *SmlWriterProcessor) CloseTag(tag []string) { + swp.writer.WriteString("}") + + if swp.prettyPrint { + swp.indentLevel-- + } + + swp.writer.Flush() +} + +// Write a text. +func (swp *SmlWriterProcessor) Text(text string) { + ta := strings.Replace(text, "^", "^^", -1) + tb := strings.Replace(ta, "{", "^{", -1) + tc := strings.Replace(tb, "}", "^}", -1) + + swp.writeIndent(false) + + swp.writer.WriteString(tc) +} + +// Write an indent in case of pretty print. +func (swp *SmlWriterProcessor) writeIndent(increase bool) { + if swp.prettyPrint { + if swp.indentLevel > 0 { + swp.writer.WriteString("\n") + } + + for i := 0; i < swp.indentLevel; i++ { + swp.writer.WriteString("\t") + } + + if increase { + swp.indentLevel++ + } + } else { + swp.writer.WriteString(" ") + } +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go new file mode 100644 index 0000000..06f3479 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go @@ -0,0 +1,408 @@ +/* + Tideland Common Go Library - Sorting and Map/Reduce + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "hash/adler32" + "sort" +) + +//-------------------- +// CONTROL VALUES +//-------------------- + +// Threshold for switching from parallel to sequential quick sort. +var QuickSortParallelThreshold int = 4095 + +// Threshold for switching from sequential quick sort to insertion sort. +var QuickSortSequentialThreshold int = 63 + +//-------------------- +// HELPING FUNCS +//-------------------- + +// Simple insertion sort for smaller data collections. +func insertionSort(data sort.Interface, lo, hi int) { + for i := lo + 1; i < hi+1; i++ { + for j := i; j > lo && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Get the median based on Tukey's ninther. +func median(data sort.Interface, lo, hi int) int { + m := (lo + hi) / 2 + d := (hi - lo) / 8 + + // Move median into the middle. + + mot := func(ml, mm, mh int) { + if data.Less(mm, ml) { + data.Swap(mm, ml) + } + if data.Less(mh, mm) { + data.Swap(mh, mm) + } + if data.Less(mm, ml) { + data.Swap(mm, ml) + } + } + + // Get low, middle, and high median. + + if hi-lo > 40 { + mot(lo+d, lo, lo+2*d) + mot(m-d, m, m+d) + mot(hi-d, hi, hi-2*d) + } + + // Get combined median. + + mot(lo, m, hi) + + return m +} + +// Partition the data based on the median. +func partition(data sort.Interface, lo, hi int) (int, int) { + med := median(data, lo, hi) + idx := lo + + data.Swap(med, hi) + + for i := lo; i < hi; i++ { + if data.Less(i, hi) { + data.Swap(i, idx) + + idx++ + } + } + + data.Swap(idx, hi) + + return idx - 1, idx + 1 +} + +// Sequential quicksort using itself recursively. +func sequentialQuickSort(data sort.Interface, lo, hi int) { + if hi-lo > QuickSortSequentialThreshold { + // Use sequential quicksort. + + plo, phi := partition(data, lo, hi) + + sequentialQuickSort(data, lo, plo) + sequentialQuickSort(data, phi, hi) + } else { + // Use insertion sort. + + insertionSort(data, lo, hi) + } +} + +// Parallel quicksort using itself recursively +// and concurrent. +func parallelQuickSort(data sort.Interface, lo, hi int, done chan bool) { + if hi-lo > QuickSortParallelThreshold { + // Parallel QuickSort. + + plo, phi := partition(data, lo, hi) + partDone := make(chan bool) + + go parallelQuickSort(data, lo, plo, partDone) + go parallelQuickSort(data, phi, hi, partDone) + + // Wait for the end of both sorts. + + <-partDone + <-partDone + } else { + // Sequential QuickSort. + + sequentialQuickSort(data, lo, hi) + } + + // Signal that it's done. + + done <- true +} + +//-------------------- +// PARALLEL QUICKSORT +//-------------------- + +func Sort(data sort.Interface) { + done := make(chan bool) + + go parallelQuickSort(data, 0, data.Len()-1, done) + + <-done +} + +//-------------------- +// BASIC KEY/VALUE TYPES +//-------------------- + +// Data processing is based on key/value pairs. +type KeyValue struct { + Key string + Value interface{} +} + +// Channel for the transfer of key/value pairs. +type KeyValueChan chan *KeyValue + +// Slice of key/value channels. +type KeyValueChans []KeyValueChan + +// Map a key/value pair, emit to the channel. +type MapFunc func(*KeyValue, KeyValueChan) + +// Reduce the key/values of the first channel, emit to the second channel. +type ReduceFunc func(KeyValueChan, KeyValueChan) + +// Channel for closing signals. +type SigChan chan bool + +//-------------------- +// HELPING FUNCS +//-------------------- + +// Close given channel after a number of signals. +func closeSignalChannel(kvc KeyValueChan, size int) SigChan { + sigChan := make(SigChan) + + go func() { + ctr := 0 + + for { + <-sigChan + + ctr++ + + if ctr == size { + close(kvc) + + return + } + } + }() + + return sigChan +} + +// Perform the reducing. +func performReducing(mapEmitChan KeyValueChan, reduceFunc ReduceFunc, reduceSize int, reduceEmitChan KeyValueChan) { + // Start a closer for the reduce emit chan. + + sigChan := closeSignalChannel(reduceEmitChan, reduceSize) + + // Start reduce funcs. + + reduceChans := make(KeyValueChans, reduceSize) + + for i := 0; i < reduceSize; i++ { + reduceChans[i] = make(KeyValueChan) + + go func(inChan KeyValueChan) { + reduceFunc(inChan, reduceEmitChan) + + sigChan <- true + }(reduceChans[i]) + } + + // Read map emitted data. + + for kv := range mapEmitChan { + hash := adler32.Checksum([]byte(kv.Key)) + idx := hash % uint32(reduceSize) + + reduceChans[idx] <- kv + } + + // Close reduce channels. + + for _, reduceChan := range reduceChans { + close(reduceChan) + } +} + +// Perform the mapping. +func performMapping(mapInChan KeyValueChan, mapFunc MapFunc, mapSize int, mapEmitChan KeyValueChan) { + // Start a closer for the map emit chan. + + sigChan := closeSignalChannel(mapEmitChan, mapSize) + + // Start mapping goroutines. + + mapChans := make(KeyValueChans, mapSize) + + for i := 0; i < mapSize; i++ { + mapChans[i] = make(KeyValueChan) + + go func(inChan KeyValueChan) { + for kv := range inChan { + mapFunc(kv, mapEmitChan) + } + + sigChan <- true + }(mapChans[i]) + } + + // Dispatch input data to map channels. + + idx := 0 + + for kv := range mapInChan { + mapChans[idx%mapSize] <- kv + + idx++ + } + + // Close mapping channels channel. + + for i := 0; i < mapSize; i++ { + close(mapChans[i]) + } +} + +//-------------------- +// MAP/REDUCE +//-------------------- + +// Simple map/reduce function. +func MapReduce(inChan KeyValueChan, mapFunc MapFunc, mapSize int, reduceFunc ReduceFunc, reduceSize int) KeyValueChan { + mapEmitChan := make(KeyValueChan) + reduceEmitChan := make(KeyValueChan) + + // Perform operations. + + go performReducing(mapEmitChan, reduceFunc, reduceSize, reduceEmitChan) + go performMapping(inChan, mapFunc, mapSize, mapEmitChan) + + return reduceEmitChan +} + +//-------------------- +// RESULT SORTING +//-------------------- + +// Less function for sorting. +type KeyValueLessFunc func(*KeyValue, *KeyValue) bool + +// Sortable set of key/value pairs. +type SortableKeyValueSet struct { + data []*KeyValue + lessFunc KeyValueLessFunc +} + +// Constructor for the sortable set. +func NewSortableKeyValueSet(kvChan KeyValueChan, kvLessFunc KeyValueLessFunc) *SortableKeyValueSet { + s := &SortableKeyValueSet{ + data: make([]*KeyValue, 0, 1024), + lessFunc: kvLessFunc, + } + + for kv := range kvChan { + l := len(s.data) + + if l == cap(s.data) { + tmp := make([]*KeyValue, l, l+1024) + + copy(tmp, s.data) + + s.data = tmp + } + + s.data = s.data[0 : l+1] + s.data[l] = kv + } + + return s +} + +// Sort interface: Return the len of the data. +func (s *SortableKeyValueSet) Len() int { + return len(s.data) +} + +// Sort interface: Return which element is less. +func (s *SortableKeyValueSet) Less(a, b int) bool { + return s.lessFunc(s.data[a], s.data[b]) +} + +// Sort interface: Swap two elements. +func (s *SortableKeyValueSet) Swap(a, b int) { + s.data[a], s.data[b] = s.data[b], s.data[a] +} + +// Return the data using a channel. +func (s *SortableKeyValueSet) DataChan() KeyValueChan { + kvChan := make(KeyValueChan) + + go func() { + for _, kv := range s.data { + kvChan <- kv + } + + close(kvChan) + }() + + return kvChan +} + +// SortedMapReduce performes a map/reduce and sorts the result. +func SortedMapReduce(inChan KeyValueChan, mapFunc MapFunc, mapSize int, reduceFunc ReduceFunc, reduceSize int, lessFunc KeyValueLessFunc) KeyValueChan { + kvChan := MapReduce(inChan, mapFunc, mapSize, reduceFunc, reduceSize) + s := NewSortableKeyValueSet(kvChan, lessFunc) + + Sort(s) + + return s.DataChan() +} + +// KeyLessFunc compares the keys of two key/value +// pairs. It returns true if the key of a is less +// the key of b. +func KeyLessFunc(a *KeyValue, b *KeyValue) bool { + return a.Key < b.Key +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go new file mode 100644 index 0000000..d6470cd --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go @@ -0,0 +1,290 @@ +/* + Tideland Common Go Library - Supervision + + Copyright (C) 2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "log" + "os" + "time" +) + +//-------------------- +// GLOBAL VARIABLES +//-------------------- + +var supervisor *Supervisor + +//-------------------- +// INIT +//-------------------- + +func init() { + supervisor = NewSupervisor(nil) +} + +//-------------------- +// FUNCTIONS +//-------------------- + +// Return the global supervisor. +func GlobalSupervisor() *Supervisor { + return supervisor +} + +//-------------------- +// RECOVERABLE +//-------------------- + +// The interface for recoverable types. +type Recoverable interface { + Supervisor() *Supervisor + Recover(Recoverable, interface{}) +} + +//-------------------- +// SUPERVISOR +//-------------------- + +// Message: Add a recoverable for mass recovering. +type addRecoverableMsg struct { + id string + r Recoverable +} + +// Message: Cry for help after an error. +type cryForHelpMsg struct { + r Recoverable + err interface{} +} + +// The supervisor itself. +type Supervisor struct { + supervisor *Supervisor + recoverables map[string]Recoverable + addChan chan *addRecoverableMsg + helpChan chan *cryForHelpMsg +} + +// Create a new supervisor. +func NewSupervisor(parent *Supervisor) *Supervisor { + s := &Supervisor{ + supervisor: parent, + recoverables: make(map[string]Recoverable), + addChan: make(chan *addRecoverableMsg), + helpChan: make(chan *cryForHelpMsg), + } + + go s.backend() + + return s +} + +// Add a recoverable for joint restart in case of an error. +func (s *Supervisor) AddRecoverable(id string, r Recoverable) { + s.addChan <- &addRecoverableMsg{id, r} +} + +// Let a recoverable cry for help at its supervisor. +func (s *Supervisor) Help(r Recoverable, err interface{}) { + s.helpChan <- &cryForHelpMsg{r, err} +} + +// Implement Supervisor() of the recoverable interface for the supervisor itself. +func (s *Supervisor) Supervisor() *Supervisor { + return s.supervisor +} + +// Implement Recover() of the recoverable interface for the supervisor itself. +func (s *Supervisor) Recover(r Recoverable, err interface{}) { + if s == r { + go s.backend() + } +} + +// Backend goroutine of the supervisor. +func (s *Supervisor) backend() { + defer func() { + // Test for error and cry for help + // if needed. + HelpIfNeeded(s, recover()) + }() + + // Wait for cries for help. + + for { + select { + case add := <-s.addChan: + s.recoverables[add.id] = add.r + case cfh := <-s.helpChan: + if len(s.recoverables) > 0 { + // Recover all recoverables. + + done := false + + for _, recoverable := range s.recoverables { + recoverable.Recover(recoverable, cfh.err) + + if recoverable == cfh.r { + done = true + } + } + + // Erroreous recoverable is not registered. + + if !done { + cfh.r.Recover(cfh.r, cfh.err) + } + } else { + // Recover the erroreous recoverable. + + cfh.r.Recover(cfh.r, cfh.err) + } + } + } +} + +//-------------------- +// HEARTBEATABLE +//-------------------- + +// The interface for heartbeatable types. +type Heartbeatable interface { + Recoverable + SetHearbeat(*Heartbeat) +} + +//-------------------- +// HEARBEAT +//-------------------- + +// Heartbeat for one recoverable. +type Heartbeat struct { + recoverable Recoverable + ticker *time.Ticker + openTicks int64 + HeartbeatChan chan *Heartbeat + ImAliveChan chan bool +} + +// Create a new heartbeat. +func NewHeartbeat(r Recoverable, ns int64) *Heartbeat { + h := &Heartbeat{ + recoverable: r, + ticker: time.NewTicker(ns), + openTicks: 0, + HeartbeatChan: make(chan *Heartbeat), + ImAliveChan: make(chan bool), + } + + go h.backend() + + return h +} + +// Backend goroutine of the heartbeat. +func (h *Heartbeat) backend() { + for { + select { + case <-h.ticker.C: + // Check open ticks. + if h.openTicks > 0 { + h.recoverBelated() + } else { + h.sendHeartbeat() + } + case <-h.ImAliveChan: + // Reduce number of open ticks. + if h.openTicks > 0 { + h.openTicks-- + } + } + } +} + +// Recover a belated recaverable. +func (h *Heartbeat) recoverBelated() { + err := os.NewError("Belated recoverable!") + + if h.recoverable.Supervisor() != nil { + // Cry for help using the supervisor. + h.recoverable.Supervisor().Help(h.recoverable, err) + } else { + // Recover directly. + h.recoverable.Recover(h.recoverable, err) + } + + h.openTicks = 0 +} + +// Send a heartbeat. +func (h *Heartbeat) sendHeartbeat() { + select { + case h.HeartbeatChan <- h: + break + default: + log.Printf("Heartbeat can't be sent!") + } + + h.openTicks++ +} + +//-------------------- +// CONVENIENCE FUNCTIONS +//-------------------- + +// Tell the supervisor to help if +// the passed error is not nil. +func HelpIfNeeded(r Recoverable, err interface{}) { + // Test for error. + if err != nil { + // Test for configured supervisor. + if r.Supervisor() != nil { + // Cry for help. + r.Supervisor().Help(r, err) + } + } +} + +// Send a heartbeat. +func ImAlive(h *Heartbeat) { + h.ImAliveChan <- true +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go new file mode 100644 index 0000000..6764316 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go @@ -0,0 +1,316 @@ +/* + Tideland Common Go Library - Time and Crontab + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + modification, are permitted provided that the following conditions are + met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of Tideland nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "log" + "time" +) + +//-------------------- +// DATE AND TIME +//-------------------- + +// Calc nanoseconds from microseconds. +func NsMicroseconds(count int64) int64 { return count * 1e3 } + +// Calc nanoseconds from milliseconds. +func NsMilliseconds(count int64) int64 { return NsMicroseconds(count * 1e3) } + +// Calc nanoseconds from seconds. +func NsSeconds(count int64) int64 { return NsMilliseconds(count * 1e3) } + +// Calc nanoseconds from minutes. +func NsMinutes(count int64) int64 { return NsSeconds(count * 60) } + +// Calc nanoseconds from hours. +func NsHours(count int64) int64 { return NsMinutes(count * 60) } + +// Calc nanoseconds from days. +func NsDays(count int64) int64 { return NsHours(count * 24) } + +// Calc nanoseconds from weeks. +func NsWeeks(count int64) int64 { return NsDays(count * 7) } + +// Test if the year of a time is in a given list. +func YearInList(time *time.Time, years []int64) bool { + for _, year := range years { + if time.Year == year { + return true + } + } + + return false +} + +// Test if a year of a time is in a given range. +func YearInRange(time *time.Time, minYear, maxYear int64) bool { + return (minYear <= time.Year) && (time.Year <= maxYear) +} + +// Test if the month of a time is in a given list. +func MonthInList(time *time.Time, months []int) bool { + return fieldInList(time.Month, months) +} + +// Test if a month of a time is in a given range. +func MonthInRange(time *time.Time, minMonth, maxMonth int) bool { + return fieldInRange(time.Month, minMonth, maxMonth) +} + +// Test if the day of a time is in a given list. +func DayInList(time *time.Time, days []int) bool { + return fieldInList(time.Day, days) +} + +// Test if a day of a time is in a given range. +func DayInRange(time *time.Time, minDay, maxDay int) bool { + return fieldInRange(time.Day, minDay, maxDay) +} + +// Test if the hour of a time is in a given list. +func HourInList(time *time.Time, hours []int) bool { + return fieldInList(time.Hour, hours) +} + +// Test if a hour of a time is in a given range. +func HourInRange(time *time.Time, minHour, maxHour int) bool { + return fieldInRange(time.Hour, minHour, maxHour) +} + +// Test if the minute of a time is in a given list. +func MinuteInList(time *time.Time, minutes []int) bool { + return fieldInList(time.Minute, minutes) +} + +// Test if a minute of a time is in a given range. +func MinuteInRange(time *time.Time, minMinute, maxMinute int) bool { + return fieldInRange(time.Minute, minMinute, maxMinute) +} + +// Test if the second of a time is in a given list. +func SecondInList(time *time.Time, seconds []int) bool { + return fieldInList(time.Second, seconds) +} + +// Test if a second of a time is in a given range. +func SecondInRange(time *time.Time, minSecond, maxSecond int) bool { + return fieldInRange(time.Second, minSecond, maxSecond) +} + +// Test if the weekday of a time is in a given list. +func WeekdayInList(time *time.Time, weekdays []int) bool { + return fieldInList(time.Weekday, weekdays) +} + +// Test if a weekday of a time is in a given range. +func WeekdayInRange(time *time.Time, minWeekday, maxWeekday int) bool { + return fieldInRange(time.Weekday, minWeekday, maxWeekday) +} + +//-------------------- +// JOB +//-------------------- + +// Check function type. +type CheckFunc func(*time.Time) (bool, bool) + +// Tast function type. +type TaskFunc func(string) + +// Job type. +type Job struct { + id string + check CheckFunc + task TaskFunc +} + +// Create a new job. +func NewJob(id string, check CheckFunc, task TaskFunc) *Job { + return &Job{id, check, task} +} + +// Check if the job has to be performed at a given time. +func (job *Job) checkAndPerform(time *time.Time) bool { + perform, delete := job.check(time) + + if perform { + go job.task(job.id) + } + + return perform && delete +} + +//-------------------- +// CRONTAB +//-------------------- + +const ( + opJobAdd = iota + opJobDel + opCrontabStop +) + +// Crontab control type. +type crontabControl struct { + opCode int + args interface{} +} + +// Crontab. +type Crontab struct { + jobs map[string]*Job + control chan *crontabControl + ticker *time.Ticker +} + +// Start a crontab server. +func NewCrontab() *Crontab { + ctb := &Crontab{ + jobs: make(map[string]*Job), + control: make(chan *crontabControl), + ticker: time.NewTicker(1e9), + } + + go ctb.backend() + + return ctb +} + +// Stop the server. +func (ctb *Crontab) Stop() { + ctb.control <- &crontabControl{opCrontabStop, nil} +} + +// Add a job to the server. +func (ctb *Crontab) AddJob(job *Job) { + ctb.control <- &crontabControl{opJobAdd, job} +} + +// Delete a job from the server. +func (ctb *Crontab) DeleteJob(id string) { + ctb.control <- &crontabControl{opJobDel, id} +} + +// Return the supervisor. +func (src *Crontab) Supervisor() *Supervisor { + return GlobalSupervisor() +} + +// Recover after an error. +func (ctb *Crontab) Recover(recoverable Recoverable, err interface{}) { + log.Printf("Recovering crontab backend after error '%v'!", err) + + go ctb.backend() +} + +// Crontab backend. +func (ctb *Crontab) backend() { + defer func() { + HelpIfNeeded(ctb, recover()) + }() + + for { + select { + case sc := <-ctb.control: + // Control the server. + + switch sc.opCode { + case opJobAdd: + job := sc.args.(*Job) + ctb.jobs[job.id] = job + case opJobDel: + id := sc.args.(string) + job, _ := ctb.jobs[id] + ctb.jobs[id] = job, false + case opCrontabStop: + ctb.ticker.Stop() + } + case <-ctb.ticker.C: + // One tick every second. + + ctb.tick() + } + } +} + +// Handle one server tick. +func (ctb *Crontab) tick() { + now := time.UTC() + deletes := make(map[string]*Job) + + // Check and perform jobs. + + for id, job := range ctb.jobs { + delete := job.checkAndPerform(now) + + if delete { + deletes[id] = job + } + } + + // Delete those marked for deletion. + + for id, job := range deletes { + ctb.jobs[id] = job, false + } +} + +//-------------------- +// HELPERS +//-------------------- + +// Test if an int is in a list of ints. +func fieldInList(field int, list []int) bool { + for _, item := range list { + if field == item { + return true + } + } + + return false +} + +// Test if an int is in a given range. +func fieldInRange(field int, min, max int) bool { + return (min <= field) && (field <= max) +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/type_interfaces.go b/eBook/examples/chapter_11/type_interfaces.go new file mode 100644 index 0000000..9042428 --- /dev/null +++ b/eBook/examples/chapter_11/type_interfaces.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "math" +) + +type Square struct { + side float32 +} + +type Circle struct { + radius float32 +} + +type Shaper interface { + Area() float32 +} + +func main() { + var areaIntf Shaper + sq1 := new(Square) + sq1.side = 5 + + areaIntf = sq1 + // Is Square the type of areaIntf ? + if t, ok := areaIntf.(*Square); ok { + fmt.Printf("The type of areaIntf is: %T\n", t) + } + if u, ok := areaIntf.(*Circle); ok { + fmt.Printf("The type of areaIntf is: %T\n", u) + } else { + fmt.Println("areaIntf does not contain a variable of type Circle") + } + // testing with switch: + switch t := areaIntf.(type) { + case *Square: + fmt.Printf("Type Square %T with value %v\n", t, t) + case *Circle: + fmt.Printf("Type Circle %T with value %v\n", t, t) + /* + case bool: + fmt.Printf("Type boolean %t\n", t) + case int: + fmt.Printf("Type int %d\n", t) + case *bool: + fmt.Printf("Type pointer to boolean %t\n", *t) + case *int: + fmt.Printf("Type pointer to int %d\n", *t) + */ + default: + fmt.Printf("Unexpected type %T", t) + } +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func (ci *Circle) Area() float32 { + return ci.radius * ci.radius * math.Pi +} diff --git a/eBook/examples/chapter_12/cat.go b/eBook/examples/chapter_12/cat.go new file mode 100644 index 0000000..2e2abe7 --- /dev/null +++ b/eBook/examples/chapter_12/cat.go @@ -0,0 +1,36 @@ +package main + +import ( + "os" + "io" + "fmt" + "bufio" + "flag" +) + +func cat(r *bufio.Reader) { + for { + buf, err := r.ReadBytes('\n') + if err == io.EOF { + break + } + fmt.Fprintf(os.Stdout, "%s", buf) + } + return +} + +func main() { + flag.Parse() + if flag.NArg() == 0 { + cat(bufio.NewReader(os.Stdin)) + } + for i := 0; i < flag.NArg(); i++ { + f, err := os.Open(flag.Arg(i)) + if err != nil { + fmt.Fprintf(os.Stderr, "%s:error reading from %s: %s\n", os.Args[0], flag.Arg(i), err.Error()) + continue + } + cat(bufio.NewReader(f)) + } +} + diff --git a/eBook/examples/chapter_12/cat2.go b/eBook/examples/chapter_12/cat2.go new file mode 100644 index 0000000..8bb2538 --- /dev/null +++ b/eBook/examples/chapter_12/cat2.go @@ -0,0 +1,41 @@ +package main + +import ( + "flag" + "fmt" + "os" +) + +func cat(f *os.File) { + const NBUF = 512 + var buf [NBUF]byte + for { + switch nr, err := f.Read(buf[:]); true { + case nr < 0: + fmt.Fprintf(os.Stderr, "cat: error reading: %s\n", err.Error()) + os.Exit(1) + case nr == 0: // EOF + return + case nr > 0: + if nw, ew := os.Stdout.Write(buf[0:nr]); nw != nr { + fmt.Fprintf(os.Stderr, "cat: error writing: %s\n", ew.Error()) + } + } + } +} + +func main() { + flag.Parse() // Scans the arg list and sets up flags + if flag.NArg() == 0 { + cat(os.Stdin) + } + for i := 0; i < flag.NArg(); i++ { + f, err := os.Open(flag.Arg(i)) + if f == nil { + fmt.Fprintf(os.Stderr, "cat: can't open %s: error %s\n", flag.Arg(i), err) + os.Exit(1) + } + cat(f) + f.Close() + } +} diff --git a/eBook/examples/chapter_12/echo.go b/eBook/examples/chapter_12/echo.go new file mode 100644 index 0000000..3424772 --- /dev/null +++ b/eBook/examples/chapter_12/echo.go @@ -0,0 +1,29 @@ +package main + +import ( + "os" + "flag" // command line option parser +) + +var NewLine = flag.Bool("n", false, "print newline") // echo -n flag, of type *bool + +const ( + Space = " " + Newline = "\n" +) + +func main() { + flag.PrintDefaults() + flag.Parse() // Scans the arg list and sets up flags + var s string = "" + for i := 0; i < flag.NArg(); i++ { + if i > 0 { + s += " " + if *NewLine { // -n is parsed, flag becomes true + s += Newline + } + } + s += flag.Arg(i) + } + os.Stdout.WriteString(s) +} diff --git a/eBook/examples/chapter_12/filecopy.go b/eBook/examples/chapter_12/filecopy.go new file mode 100644 index 0000000..2cad9af --- /dev/null +++ b/eBook/examples/chapter_12/filecopy.go @@ -0,0 +1,29 @@ +// filecopy.go +package main + +import ( + "fmt" + "io" + "os" +) + +func main() { + CopyFile("target.txt", "source.txt") + fmt.Println("Copy done!") +} + +func CopyFile(dstName, srcName string) (written int64, err error) { + src, err := os.Open(srcName) + if err != nil { + return + } + defer src.Close() + + dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + return + } + defer dst.Close() + + return io.Copy(dst, src) +} diff --git a/eBook/examples/chapter_12/fileinput.go b/eBook/examples/chapter_12/fileinput.go new file mode 100644 index 0000000..d7644d0 --- /dev/null +++ b/eBook/examples/chapter_12/fileinput.go @@ -0,0 +1,34 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "os" +) + +func main() { + // var inputFile *os.File + // var inputError, readerError os.Error + // var inputReader *bufio.Reader + // var inputString string + + inputFile, inputError := os.Open("input.dat") + if inputError != nil { + fmt.Printf("An error occurred on opening the inputfile\n" + + "Does the file exist?\n" + + "Have you got acces to it?\n") + return // exit the function on error + } + defer inputFile.Close() + + inputReader := bufio.NewReader(inputFile) + + for { + inputString, readerError := inputReader.ReadString('\n') + if readerError == io.EOF { + return // error or EOF + } + fmt.Printf("The input was: %s", inputString) + } +} diff --git a/eBook/examples/chapter_12/fileoutput.go b/eBook/examples/chapter_12/fileoutput.go new file mode 100644 index 0000000..50c283e --- /dev/null +++ b/eBook/examples/chapter_12/fileoutput.go @@ -0,0 +1,28 @@ +package main + +import ( + "os" + "bufio" + "fmt" +) + +func main () { + // var outputWriter *bufio.Writer + // var outputFile *os.File + // var outputError os.Error + // var outputString string + outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666) + if outputError != nil { + fmt.Printf("An error occurred with file opening or creation\n") + return + } + defer outputFile.Close() + + outputWriter := bufio.NewWriter(outputFile) + outputString := "hello world!\n" + + for i:=0; i<10; i++ { + outputWriter.WriteString(outputString) + } + outputWriter.Flush() +} \ No newline at end of file diff --git a/eBook/examples/chapter_12/filewrite.go b/eBook/examples/chapter_12/filewrite.go new file mode 100644 index 0000000..7863d5e --- /dev/null +++ b/eBook/examples/chapter_12/filewrite.go @@ -0,0 +1,10 @@ +package main + +import "os" + +func main() { + os.Stdout.WriteString("hello, world\n") + f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0) + defer f.Close() + f.WriteString("hello, world in a file\n") +} diff --git a/eBook/examples/chapter_12/gob1.go b/eBook/examples/chapter_12/gob1.go new file mode 100644 index 0000000..918a23d --- /dev/null +++ b/eBook/examples/chapter_12/gob1.go @@ -0,0 +1,41 @@ +// gob1.go +package main + +import ( + "bytes" + "fmt" + "encoding/gob" + "log" +) + +type P struct { + X, Y, Z int + Name string +} + +type Q struct { + X, Y *int32 + Name string +} + +func main() { + // Initialize the encoder and decoder. Normally enc and dec would be + // bound to network connections and the encoder and decoder would + // run in different processes. + var network bytes.Buffer // Stand-in for a network connection + enc := gob.NewEncoder(&network) // Will write to network. + dec := gob.NewDecoder(&network) // Will read from network. + // Encode (send) the value. + err := enc.Encode(P{3, 4, 5, "Pythagoras"}) + if err != nil { + log.Fatal("encode error:", err) + } + // Decode (receive) the value. + var q Q + err = dec.Decode(&q) + if err != nil { + log.Fatal("decode error:", err) + } + fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y) +} +// Output: "Pythagoras": {3,4} diff --git a/eBook/examples/chapter_12/gob2.go b/eBook/examples/chapter_12/gob2.go new file mode 100644 index 0000000..217e161 --- /dev/null +++ b/eBook/examples/chapter_12/gob2.go @@ -0,0 +1,39 @@ +// gob2.go +package main + +import ( + "encoding/gob" + "log" + "os" +) + +type Address struct { + Type string + City string + Country string +} + +type VCard struct { + FirstName string + LastName string + Addresses []*Address + Remark string +} + +var content string + +func main() { + pa := &Address{"private", "Aartselaar","Belgium"} + wa := &Address{"work", "Boom", "Belgium"} + vc := VCard{"Jan", "Kersschot", []*Address{pa,wa}, "none"} + // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: + // using an encoder: + file, _ := os.OpenFile("vcard.gob", os.O_CREATE|os.O_WRONLY, 0) + defer file.Close() + enc := gob.NewEncoder(file) + err := enc.Encode(vc) + if err != nil { + log.Println("Error in encoding gob") + } +} + diff --git a/eBook/examples/chapter_12/gzipped.go b/eBook/examples/chapter_12/gzipped.go new file mode 100644 index 0000000..2666f43 --- /dev/null +++ b/eBook/examples/chapter_12/gzipped.go @@ -0,0 +1,35 @@ +// gzipped.go +package main + +import ( + "fmt" + "bufio" + "os" + "compress/gzip" +) + +func main() { + fName := "MyFile.gz" + var r *bufio.Reader + fi, err := os.Open(fName) + if err != nil { + fmt.Fprintf(os.Stderr, "%v, Can't open %s: error: %s\n", os.Args[0], fName, + err) + os.Exit(1) + } + fz, err := gzip.NewReader(fi) + if err != nil { + r = bufio.NewReader(fi) + } else { + r = bufio.NewReader(fz) + } + + for { + line, err := r.ReadString('\n') + if err != nil { + fmt.Println("Done reading file") + os.Exit(0) + } + fmt.Println(line) + } +} diff --git a/eBook/examples/chapter_12/hash_sha1.go b/eBook/examples/chapter_12/hash_sha1.go new file mode 100644 index 0000000..d22c8ae --- /dev/null +++ b/eBook/examples/chapter_12/hash_sha1.go @@ -0,0 +1,31 @@ +// hash_sha1.go +package main + +import ( + "fmt" + "crypto/sha1" + "io" + "log" +) + +func main() { + hasher := sha1.New() + io.WriteString(hasher, "test") + b := []byte{} + fmt.Printf("Result: %x\n", hasher.Sum(b)) + fmt.Printf("Result: %d\n", hasher.Sum(b)) + // + hasher.Reset() + data := []byte("We shall overcome!") + n, err := hasher.Write(data) + if n!=len(data) || err!=nil { + log.Printf("Hash write error: %v / %v", n, err) + } + checksum := hasher.Sum(b) + fmt.Printf("Result: %x\n", checksum) +} +/* Output: +Result: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 +Result: [169 74 143 229 204 177 155 166 28 76 8 115 211 145 233 135 152 47 187 211] +Result: e2222bfc59850bbb00a722e764a555603bb59b2a +*/ diff --git a/eBook/examples/chapter_12/input.dat b/eBook/examples/chapter_12/input.dat new file mode 100644 index 0000000..c19fab2 --- /dev/null +++ b/eBook/examples/chapter_12/input.dat @@ -0,0 +1,5 @@ +chicken +cow +donkey +horse +pig diff --git a/eBook/examples/chapter_12/io_interfaces.go b/eBook/examples/chapter_12/io_interfaces.go new file mode 100644 index 0000000..165d9f1 --- /dev/null +++ b/eBook/examples/chapter_12/io_interfaces.go @@ -0,0 +1,18 @@ +// interfaces being used in the GO-package fmt +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + // unbuffered + fmt.Fprintf(os.Stdout, "%s\n", "hello world! - unbuffered") + // buffered: os.Stdout implements io.Writer + buf := bufio.NewWriter(os.Stdout) + // and now so does buf. + fmt.Fprintf(buf, "%s\n", "hello world! - buffered") + buf.Flush() +} diff --git a/eBook/examples/chapter_12/json.go b/eBook/examples/chapter_12/json.go new file mode 100644 index 0000000..7958148 --- /dev/null +++ b/eBook/examples/chapter_12/json.go @@ -0,0 +1,40 @@ +// json.go.go +package main + +import ( + "fmt" + "encoding/json" + "log" + "os" +) + +type Address struct { + Type string + City string + Country string +} + +type VCard struct { + FirstName string + LastName string + Addresses []*Address + Remark string +} + +func main() { + pa := &Address{"private", "Aartselaar","Belgium"} + wa := &Address{"work", "Boom", "Belgium"} + vc := VCard{"Jan", "Kersschot", []*Address{pa,wa}, "none"} + // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: + // JSON format: + js, _ := json.Marshal(vc) + fmt.Printf("JSON format: %s", js) + // using an encoder: + file, _ := os.OpenFile("vcard.json", os.O_CREATE|os.O_WRONLY, 0) + defer file.Close() + enc := json.NewEncoder(file) + err := enc.Encode(vc) + if err != nil { + log.Println("Error in encoding json") + } +} diff --git a/eBook/examples/chapter_12/json_xml_case.go b/eBook/examples/chapter_12/json_xml_case.go new file mode 100644 index 0000000..9c320e2 --- /dev/null +++ b/eBook/examples/chapter_12/json_xml_case.go @@ -0,0 +1,54 @@ +// json_xml_case.go +package main + +import ( + "encoding/json" + "encoding/xml" + "fmt" + "log" + "strings" +) + +type thing struct { + Field1 int + Field2 string +} + +func main() { + x := `423hello from xml` + j := `{"field1": 423, "field2": "hello from json"}` + + tx := thing{} + if err := xml.Unmarshal(strings.NewReader(x), &tx); err != nil { + log.Fatalf("Error unmarshaling XML: %v", err) + } + + tj := thing{} + if err := json.Unmarshal([]byte(j), &tj); err != nil { + log.Fatalf("Error unmarshaling JSON: %v", err) + } + + fmt.Printf("From JSON: %#v\n", tj) + fmt.Printf("From XML: %#v\n", tx) + +} +/* Output with +type thing struct { + Field1 int + Field2 string +}: + +From XML: main.thing{Field1:0, Field2:""} // All matching is case sensitive! +From JSON: main.thing{Field1:423, Field2:"hello from json"} + +Output with +type thing struct { + field1 int + field2 string +}: + +2012/02/22 10:51:11 Error unmarshaling JSON: json: cannot unmarshal object +field1" into unexported field field1 of type main.thing + +JSON uses reflection to unmarshal! +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_12/os_args.go b/eBook/examples/chapter_12/os_args.go new file mode 100644 index 0000000..7dc9aa9 --- /dev/null +++ b/eBook/examples/chapter_12/os_args.go @@ -0,0 +1,16 @@ +// os_args.go +package main + +import ( + "fmt" + "os" + "strings" +) + +func main() { + who := "Alice " + if len(os.Args) > 1 { + who += strings.Join(os.Args[1:], " ") + } + fmt.Println("Good Morning", who) +} diff --git a/eBook/examples/chapter_12/output.dat b/eBook/examples/chapter_12/output.dat new file mode 100644 index 0000000..8ee7109 --- /dev/null +++ b/eBook/examples/chapter_12/output.dat @@ -0,0 +1,10 @@ +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! diff --git a/eBook/examples/chapter_12/products.txt b/eBook/examples/chapter_12/products.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/products.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/products2.txt b/eBook/examples/chapter_12/products2.txt new file mode 100644 index 0000000..e5886d4 --- /dev/null +++ b/eBook/examples/chapter_12/products2.txt @@ -0,0 +1,3 @@ +ABC 40 150 +FUNC 56 280 +GO 45 356 diff --git a/eBook/examples/chapter_12/products_copy.txt b/eBook/examples/chapter_12/products_copy.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/products_copy.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/read_file2.go b/eBook/examples/chapter_12/read_file2.go new file mode 100644 index 0000000..59e4397 --- /dev/null +++ b/eBook/examples/chapter_12/read_file2.go @@ -0,0 +1,38 @@ +// read_csvfile.go +package main + +import ( + "fmt" + "os" +// "io/ioutil" +// "strings" +) + +func main() { + file, err := os.Open("products2.txt") + if err != nil { + panic(err) + } + defer file.Close() + + var col1, col2, col3 []string + for { + var v1, v2, v3 string + _, err := fmt.Fscanln(file, &v1, &v2, &v3) + if err != nil { + break + } + col1 = append(col1, v1) + col2 = append(col2, v2) + col3 = append(col3, v3) + } + + fmt.Println(col1) + fmt.Println(col2) + fmt.Println(col3) +} +/* Output: +[ABC FUNC GO] +[40 56 45] +[150 280 356] +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_12/read_files.go b/eBook/examples/chapter_12/read_files.go new file mode 100644 index 0000000..2c37e95 --- /dev/null +++ b/eBook/examples/chapter_12/read_files.go @@ -0,0 +1,30 @@ +// read_files.go +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "os" +) + +func main() { + fmt.Printf("Reading files...\n") + flag.Parse() + + for i := 0; i < flag.NArg(); i++ { + fmt.Printf("[File: %v]\n", flag.Arg(i)) + fin, err := os.Open(flag.Arg(i)) + if err != nil { + fmt.Printf("The file %v does not exist!\n", flag.Arg(i)) + break + } + r := bufio.NewReader(fin) + for line, _, err := r.ReadLine(); + err != io.EOF; + line, _, err = r.ReadLine() { + fmt.Printf("Lines: %v (error %v)\n", string(line), err) + } + } +} diff --git a/eBook/examples/chapter_12/read_write_file1.go b/eBook/examples/chapter_12/read_write_file1.go new file mode 100644 index 0000000..57314a5 --- /dev/null +++ b/eBook/examples/chapter_12/read_write_file1.go @@ -0,0 +1,21 @@ +// read_write_file.go +package main + +import ( + "fmt" + "io/ioutil" +) + +func main() { + inputFile := "products.txt" + outputFile := "products_copy.txt" + buf, err := ioutil.ReadFile(inputFile) + if err != nil { + panic(err.Error()) + } + fmt.Printf("%s\n", string(buf)) + err = ioutil.WriteFile(outputFile, buf, 0x644) + if err != nil { + panic(err.Error()) + } +} diff --git a/eBook/examples/chapter_12/readinput1.go b/eBook/examples/chapter_12/readinput1.go new file mode 100644 index 0000000..175401c --- /dev/null +++ b/eBook/examples/chapter_12/readinput1.go @@ -0,0 +1,24 @@ +// read input from the console: +package main + +import ( + "fmt" +) + +var ( + firstName, lastName, s string + i int + f float32 + input = "56.12 / 5212 / Go" + format = "%f / %d / %s" +) + +func main() { + fmt.Println("Please enter your full name: ") + fmt.Scanln(&firstName, &lastName) + // fmt.Scanf("%s %s", &firstName, &lastName) + fmt.Printf("Hi %s %s!\n", firstName, lastName) // Hi Chris Naegels + + fmt.Sscanf(input, format, &f, &i, &s) + fmt.Println("From the string we read: ", f, i, s) // From the string we read: 56.12 5212 Go +} diff --git a/eBook/examples/chapter_12/readinput2.go b/eBook/examples/chapter_12/readinput2.go new file mode 100644 index 0000000..21be89a --- /dev/null +++ b/eBook/examples/chapter_12/readinput2.go @@ -0,0 +1,22 @@ +// read input from the console: +package main + +import ( + "fmt" + "bufio" + "os" +) + +var inputReader *bufio.Reader + var input string + var err error + +func main() { + inputReader = bufio.NewReader(os.Stdin) // reader for input + fmt.Println("Please enter some input: ") + input, err = inputReader.ReadString('\n') + + if err == nil { + fmt.Printf("The input was: %s\n", input) + } +} diff --git a/eBook/examples/chapter_12/source.txt b/eBook/examples/chapter_12/source.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/source.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/switch_input.go b/eBook/examples/chapter_12/switch_input.go new file mode 100644 index 0000000..99e606b --- /dev/null +++ b/eBook/examples/chapter_12/switch_input.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "os" + "bufio" +) + +func main() { + inputReader := bufio.NewReader(os.Stdin) + fmt.Println("Please enter your name:") + input, err := inputReader.ReadString('\n') + + if err != nil { + fmt.Println("There were errors reading, exiting program.") + return + } + + fmt.Printf("Your name is %s", input) + // For Unix: test with delimiter "\n", for Windows: test with "\r\n" + switch input { + case "Philip\r\n": fmt.Println("Welcome Philip!") + case "Chris\r\n": fmt.Println("Welcome Chris!") + case "Ivo\r\n": fmt.Println("Welcome Ivo!") + default: fmt.Printf("You are not welcome here! Goodbye!") + } + + // version 2: + switch input { + case "Philip\r\n": fallthrough + case "Ivo\r\n": fallthrough + case "Chris\r\n": fmt.Printf("Welcome %s\n", input) + default: fmt.Printf("You are not welcome here! Goodbye!\n") + } + + // version 3: + switch input { + case "Philip\r\n", "Ivo\r\n": fmt.Printf("Welcome %s\n", input) + default: fmt.Printf("You are not welcome here! Goodbye!\n") + } +} diff --git a/eBook/examples/chapter_12/target.txt b/eBook/examples/chapter_12/target.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/target.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/test b/eBook/examples/chapter_12/test new file mode 100644 index 0000000..6f2c2db --- /dev/null +++ b/eBook/examples/chapter_12/test @@ -0,0 +1 @@ +hello, world in a file diff --git a/eBook/examples/chapter_12/vcard.gob b/eBook/examples/chapter_12/vcard.gob new file mode 100644 index 0000000..fafd384 Binary files /dev/null and b/eBook/examples/chapter_12/vcard.gob differ diff --git a/eBook/examples/chapter_12/vcard.json b/eBook/examples/chapter_12/vcard.json new file mode 100644 index 0000000..91d0da3 --- /dev/null +++ b/eBook/examples/chapter_12/vcard.json @@ -0,0 +1 @@ +{"FirstName":"Jan","LastName":"Kersschot","Addresses":[{"Type":"private","City":"Aartselaar","Country":"Belgium"},{"Type":"work","City":"Boom","Country":"Belgium"}],"Remark":"none"} diff --git a/eBook/examples/chapter_12/xml.go b/eBook/examples/chapter_12/xml.go new file mode 100644 index 0000000..0082aab --- /dev/null +++ b/eBook/examples/chapter_12/xml.go @@ -0,0 +1,49 @@ +// xml.go +package main + +import ( + "fmt" + "strings" + "encoding/xml" +) + +var t, token xml.Token +var err error + +func main() { + input := "LauraLynn" + inputReader := strings.NewReader(input) + p := xml.NewDecoder(inputReader) + + for t, err = p.Token(); err == nil; t, err = p.Token() { + switch token := t.(type) { + case xml.StartElement: + name := token.Name.Local + fmt.Printf("Token name: %s\n", name) + for _, attr := range token.Attr { + attrName := attr.Name.Local + attrValue := attr.Value + fmt.Printf("An attribute is: %s %s\n", attrName, attrValue) + // ... + } + case xml.EndElement: + fmt.Println("End of token") + case xml.CharData: + content := string([]byte(token)) + fmt.Printf("This is the content: %v\n", content ) + // ... + default: + // ... + } + } +} +/* Output: +Token name: Person +Token name: FirstName +This is the content: Laura +End of token +Token name: LastName +This is the content: Lynn +End of token +End of token +*/ diff --git a/eBook/examples/chapter_13/errors.go b/eBook/examples/chapter_13/errors.go new file mode 100644 index 0000000..442c2bc --- /dev/null +++ b/eBook/examples/chapter_13/errors.go @@ -0,0 +1,14 @@ +// errors.go +package main + +import ( + "errors" + "fmt" +) + +var errNotFound error = errors.New("Not found error") + +func main() { + fmt.Printf("error: %v", errNotFound) +} +// error: Not found error \ No newline at end of file diff --git a/eBook/examples/chapter_13/even/even/even.go b/eBook/examples/chapter_13/even/even/even.go new file mode 100644 index 0000000..204c443 --- /dev/null +++ b/eBook/examples/chapter_13/even/even/even.go @@ -0,0 +1,10 @@ +// even.go +package even + +func Even(i int) bool { // Exported function + return i%2 == 0 +} + +func Odd(i int) bool { // Exported function + return i%2 != 0 +} diff --git a/eBook/examples/chapter_13/even/even/oddeven_test.go b/eBook/examples/chapter_13/even/even/oddeven_test.go new file mode 100644 index 0000000..0afd978 --- /dev/null +++ b/eBook/examples/chapter_13/even/even/oddeven_test.go @@ -0,0 +1,27 @@ +// oddeven_test.go +package even + +import "testing" + +func TestEven(t *testing.T) { + if !Even(10) { + t.Log(" 10 must be even!") + t.Fail() + } + if Even(7) { + t.Log(" 7 is not even!") + t.Fail() + } + +} + +func TestOdd(t *testing.T) { + if !Odd(11) { + t.Log(" 11 must be odd!") + t.Fail() + } + if Odd(10) { + t.Log(" 10 is not odd!") + t.Fail() + } +} \ No newline at end of file diff --git a/eBook/examples/chapter_13/even/even_main/even_main.go b/eBook/examples/chapter_13/even/even_main/even_main.go new file mode 100644 index 0000000..bf9dd88 --- /dev/null +++ b/eBook/examples/chapter_13/even/even_main/even_main.go @@ -0,0 +1,13 @@ +// test_oddeven.go +package main + +import ( + "fmt" + "even/even" +) + +func main() { + for i:=0; i<=100; i++ { + fmt.Printf("Is the integer %d even? %v\n", i, even.Even(i)) + } +} diff --git a/eBook/examples/chapter_13/exec.go b/eBook/examples/chapter_13/exec.go new file mode 100644 index 0000000..c81f6e1 --- /dev/null +++ b/eBook/examples/chapter_13/exec.go @@ -0,0 +1,61 @@ +// exec.go +package main +import ( + "fmt" + "os/exec" + "os" +) + +func main() { +// 1) os.StartProcess // +/*********************/ +/* Linux: */ + env := os.Environ() + procAttr := &os.ProcAttr{ + Env: env, + Files: []*os.File{ + os.Stdin, + os.Stdout, + os.Stderr, + }, + } + // 1st example: list files + pid, err := os.StartProcess("/bin/ls", []string{"ls", "-l"}, procAttr) + if err != nil { + fmt.Printf("Error %v starting process!", err) // + os.Exit(1) + } + fmt.Printf("The process id is %v", pid) + // 2nd example: show all processes + pid, err = os.StartProcess("/bin/ps", []string{"-e", "-opid,ppid,comm"}, procAttr) + if err != nil { + fmt.Printf("Error %v starting process!", err) // + os.Exit(1) + } + fmt.Printf("The process id is %v", pid) +/* Output 1st: +The process id is &{2054 0}total 2056 +-rwxr-xr-x 1 ivo ivo 1157555 2011-07-04 16:48 Mieken_exec +-rw-r--r-- 1 ivo ivo 2124 2011-07-04 16:48 Mieken_exec.go +-rw-r--r-- 1 ivo ivo 18528 2011-07-04 16:48 Mieken_exec_go_.6 +-rwxr-xr-x 1 ivo ivo 913920 2011-06-03 16:13 panic.exe +-rw-r--r-- 1 ivo ivo 180 2011-04-11 20:39 panic.go +*/ + +// 2) exec.Run // +/***************/ +// Linux: OK, but not for ls ? +// cmd := exec.Command("ls", "-l") // no error, but doesn't show anything ? +// cmd := exec.Command("ls") // no error, but doesn't show anything ? + cmd := exec.Command("gedit") // this opens a gedit-window + err = cmd.Run() + if err != nil { + fmt.Printf("Error %v executing command!", err) + os.Exit(1) + } + fmt.Printf("The command is %v", cmd) +// The command is &{/bin/ls [ls -l] [] 0xf840000210 true [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [] [] 0xf8400128c0} +} +// in Windows: uitvoering: Error fork/exec /bin/ls: The system cannot find the path specified. starting process! + + diff --git a/eBook/examples/chapter_13/panic.go b/eBook/examples/chapter_13/panic.go new file mode 100644 index 0000000..139c62f --- /dev/null +++ b/eBook/examples/chapter_13/panic.go @@ -0,0 +1,9 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Starting the program") + panic("A severe error occurred: stopping the program!") + fmt.Println("Ending the program") +} \ No newline at end of file diff --git a/eBook/examples/chapter_13/panic_package.go b/eBook/examples/chapter_13/panic_package.go new file mode 100644 index 0000000..8368875 --- /dev/null +++ b/eBook/examples/chapter_13/panic_package.go @@ -0,0 +1,39 @@ +// panic_package.go +package main + +import ( + "fmt" + "./parse/parse" +) + +func main() { + var examples = []string{ + "1 2 3 4 5", + "100 50 25 12.5 6.25", + "2 + 2 = 4", + "1st class", + "", + } + + for _, ex := range examples { + fmt.Printf("Parsing %q:\n ", ex) + nums, err := parse.Parse(ex) + if err != nil { + fmt.Println(err) // here String() method from ParseError is used + continue + } + fmt.Println(nums) + } +} +/* Output: +Parsing "1 2 3 4 5": + [1 2 3 4 5] +Parsing "100 50 25 12.5 6.25": + pkg parse: error parsing "12.5" as int +Parsing "2 + 2 = 4": + pkg parse: error parsing "+" as int +Parsing "1st class": + pkg parse: error parsing "1st" as int +Parsing "": + pkg: no words to parse +*/ diff --git a/eBook/examples/chapter_13/panic_recover.go b/eBook/examples/chapter_13/panic_recover.go new file mode 100644 index 0000000..e743575 --- /dev/null +++ b/eBook/examples/chapter_13/panic_recover.go @@ -0,0 +1,32 @@ +// panic_recover.go +package main + +import ( + "fmt" +) + +func badCall() { + panic("bad end") +} + +func test() { + defer func() { + if e := recover(); e != nil { + fmt.Printf("Panicing %s\r\n", e) + } + }() + badCall() + fmt.Printf("After bad call\r\n") // <-- wordt niet bereikt +} + +func main() { + fmt.Printf("Calling test\r\n") + test() + fmt.Printf("Test completed\r\n") +} + +/* Output: +Calling test +Panicing bad end +Test completed +*/ diff --git a/eBook/examples/chapter_13/parse/parse.go b/eBook/examples/chapter_13/parse/parse.go new file mode 100644 index 0000000..1c81a3c --- /dev/null +++ b/eBook/examples/chapter_13/parse/parse.go @@ -0,0 +1,51 @@ +// parse.go +package parse + +import ( + "fmt" + "strings" + "strconv" +) + +// A ParseError indicates an error in converting a word into an integer. +type ParseError struct { + Index int // The index into the space-separated list of words. + Word string // The word that generated the parse error. + Err error // The raw error that precipitated this error, if any. +} + +// String returns a human-readable error message. +func (e *ParseError) String() string { + return fmt.Sprintf("pkg parse: error parsing %q as int", e.Word) +} + +// Parse parses the space-separated words in in put as integers. +func Parse(input string) (numbers []int, err error) { + defer func() { + if r := recover(); r != nil { + var ok bool + err, ok = r.(error) + if !ok { + err = fmt.Errorf("pkg: %v", r) + } + } + }() + + fields := strings.Fields(input) + numbers = fields2numbers(fields) + return +} + +func fields2numbers(fields []string) (numbers []int) { + if len(fields) == 0 { + panic("no words to parse") + } + for idx, field := range fields { + num, err := strconv.Atoi(field) + if err != nil { + panic(&ParseError{idx, field, err}) + } + numbers = append(numbers, num) + } + return +} diff --git a/eBook/examples/chapter_13/xtime b/eBook/examples/chapter_13/xtime new file mode 100644 index 0000000..8075c1f --- /dev/null +++ b/eBook/examples/chapter_13/xtime @@ -0,0 +1,2 @@ +#!/bin/sh +/usr/bin/time -f '%Uu %Ss %er %MkB %C' "$@" \ No newline at end of file diff --git a/eBook/examples/chapter_14/benchmark_channels.go b/eBook/examples/chapter_14/benchmark_channels.go new file mode 100644 index 0000000..c05a7f5 --- /dev/null +++ b/eBook/examples/chapter_14/benchmark_channels.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "testing" +) + +func main() { + fmt.Println(" sync", testing.Benchmark(BenchmarkChannelSync).String()) + fmt.Println("buffered", testing.Benchmark(BenchmarkChannelBuffered).String()) +} + +func BenchmarkChannelSync(b *testing.B) { + ch := make(chan int) + go func() { + for i := 0; i < b.N; i++ { + ch <- i + } + close(ch) + }() + for _ = range ch { + } +} + +func BenchmarkChannelBuffered(b *testing.B) { + ch := make(chan int, 128) + go func() { + for i := 0; i < b.N; i++ { + ch <- i + } + close(ch) + }() + for _ = range ch { + } +} diff --git a/eBook/examples/chapter_14/chaining.go b/eBook/examples/chapter_14/chaining.go new file mode 100644 index 0000000..42d595e --- /dev/null +++ b/eBook/examples/chapter_14/chaining.go @@ -0,0 +1,23 @@ +package main + +import ( + "flag" + "fmt" +) + +var ngoroutine = flag.Int("n", 100000, "how many goroutines") + +func f(left, right chan int) { left <- 1+<-right } + +func main() { + flag.Parse() + leftmost := make(chan int) + var left, right chan int = nil, leftmost + for i := 0; i < *ngoroutine; i++ { + left, right = right, make(chan int) + go f(left, right) + } + right <- 0 // bang! + x := <-leftmost // wait for completion + fmt.Println(x) // 100000, ongeveer 1,5 s +} diff --git a/eBook/examples/chapter_14/channel_block.go b/eBook/examples/chapter_14/channel_block.go new file mode 100644 index 0000000..d45d041 --- /dev/null +++ b/eBook/examples/chapter_14/channel_block.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func main() { + ch1 := make(chan int) + go pump(ch1) // pump hangs + fmt.Println(<-ch1) // prints only 0 +} + +func pump(ch chan int) { + for i := 0; ; i++ { + ch <- i + } +} + diff --git a/eBook/examples/chapter_14/channel_block2.go b/eBook/examples/chapter_14/channel_block2.go new file mode 100644 index 0000000..eae7239 --- /dev/null +++ b/eBook/examples/chapter_14/channel_block2.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + ch1 := make(chan int) + go pump(ch1) + go suck(ch1) // tons of numbers appear + time.Sleep(1e9) +} + +func pump(ch chan int) { + for i := 0; ; i++ { + ch <- i + } +} + +func suck(ch chan int) { + for { + fmt.Println(<-ch) + } +} diff --git a/eBook/examples/chapter_14/channel_idiom.go b/eBook/examples/chapter_14/channel_idiom.go new file mode 100644 index 0000000..b4aec25 --- /dev/null +++ b/eBook/examples/chapter_14/channel_idiom.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + stream := pump() + go suck(stream) + time.Sleep(1e9) +} + +func pump() chan int { + ch := make(chan int) + go func() { + for i := 0; ; i++ { + ch <- i + } + }() + return ch +} + +func suck(ch chan int) { + for { + fmt.Println(<-ch) + } +} diff --git a/eBook/examples/chapter_14/channel_idiom2.go b/eBook/examples/chapter_14/channel_idiom2.go new file mode 100644 index 0000000..1499008 --- /dev/null +++ b/eBook/examples/chapter_14/channel_idiom2.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + suck(pump()) + time.Sleep(1e9) +} + +func pump() chan int { + ch := make(chan int) + go func() { + for i := 0; ; i++ { + ch <- i + } + }() + return ch +} + +func suck(ch chan int) { + go func() { + for v := range ch { + fmt.Println(v) + } + }() +} diff --git a/eBook/examples/chapter_14/conc_access.go b/eBook/examples/chapter_14/conc_access.go new file mode 100644 index 0000000..3bc20cc --- /dev/null +++ b/eBook/examples/chapter_14/conc_access.go @@ -0,0 +1,54 @@ +// conc_access.go +package main + +import ( + "fmt" + "strconv" +) + +type Person struct { + Name string + salary float64 + chF chan func() +} + +func NewPerson(name string, salary float64) *Person { + p := &Person{name, salary, make(chan func())} + go p.backend() + return p +} + +func (p *Person) backend() { + for f := range p.chF { + f() + } +} + +// Set salary. +func (p *Person) SetSalary(sal float64) { + p.chF <- func() { p.salary = sal } +} + +// Retrieve salary. +func (p *Person) Salary() float64 { + fChan := make(chan float64) + p.chF <- func() { fChan <- p.salary } + return <-fChan +} + +func (p *Person) String() string { + return "Person - name is: " + p.Name + " - salary is: " + strconv.FormatFloat(p.Salary(), 'f', 2, 64) +} + +func main() { + bs := NewPerson("Smith Bill", 2500.5) + fmt.Println(bs) + bs.SetSalary(4000.25) + fmt.Println("Salary changed:") + fmt.Println(bs) +} +/* Output: +Person - name is: Smith Bill - salary is: 2500.50 +Salary changed: +Person - name is: Smith Bill - salary is: 4000.25 +*/ diff --git a/eBook/examples/chapter_14/general_lazy_evalution1.go b/eBook/examples/chapter_14/general_lazy_evalution1.go new file mode 100644 index 0000000..c645b63 --- /dev/null +++ b/eBook/examples/chapter_14/general_lazy_evalution1.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" +) + +type Any interface{} +type EvalFunc func(Any) (Any, Any) + +func main() { + evenFunc := func(state Any) (Any, Any) { + os := state.(int) + ns := os + 2 + return os, ns + } + even := BuildLazyIntEvaluator(evenFunc, 0) + + for i := 0; i < 10; i++ { + fmt.Printf("%vth even: %v\n", i, even()) + } +} + +func BuildLazyEvaluator(evalFunc EvalFunc, initState Any) func() Any { + retValChan := make(chan Any) + loopFunc := func() { + var actState Any = initState + var retVal Any + for { + retVal, actState = evalFunc(actState) + retValChan <- retVal + } + } + retFunc := func() Any { + return <-retValChan + } + go loopFunc() + return retFunc +} + +func BuildLazyIntEvaluator(evalFunc EvalFunc, initState Any) func() int { + ef := BuildLazyEvaluator(evalFunc, initState) + return func() int { + return ef().(int) + } +} +/* Output: +0th even: 0 +1th even: 2 +2th even: 4 +3th even: 6 +4th even: 8 +5th even: 10 +6th even: 12 +7th even: 14 +8th even: 16 +9th even: 18 +*/ diff --git a/eBook/examples/chapter_14/goroutine1.go b/eBook/examples/chapter_14/goroutine1.go new file mode 100644 index 0000000..df3eba5 --- /dev/null +++ b/eBook/examples/chapter_14/goroutine1.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + fmt.Println("In main()") + // longWait() + go longWait() + // shortWait() + go shortWait() + fmt.Println("About to sleep in main()") + time.Sleep(10 * 1e9) // sleep works with a Duration in nanoseconds (ns) ! + fmt.Println("At the end of main()") +} + +func longWait() { + fmt.Println("Beginning longWait()") + time.Sleep(5 * 1e9) // sleep for 5 seconds + fmt.Println("End of longWait()") +} + +func shortWait() { + fmt.Println("Beginning shortWait()") + time.Sleep(2 * 1e9) // sleep for 2 seconds + fmt.Println("End of shortWait()") +} diff --git a/eBook/examples/chapter_14/goroutine2.go b/eBook/examples/chapter_14/goroutine2.go new file mode 100644 index 0000000..f504f8c --- /dev/null +++ b/eBook/examples/chapter_14/goroutine2.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + ch := make(chan string) + + go sendData(ch) + go getData(ch) + + time.Sleep(1e9) +} + +func sendData(ch chan string) { + ch <- "Washington" + ch <- "Tripoli" + ch <- "London" + ch <- "Beijing" + ch <- "Tokio" +} + +func getData(ch chan string) { + var input string + // time.Sleep(1e9) + for { + input = <-ch + fmt.Printf("%s ", input) + } +} +// Washington Tripoli London Beijing Tokio \ No newline at end of file diff --git a/eBook/examples/chapter_14/goroutine3.go b/eBook/examples/chapter_14/goroutine3.go new file mode 100644 index 0000000..f827593 --- /dev/null +++ b/eBook/examples/chapter_14/goroutine3.go @@ -0,0 +1,29 @@ +package main + +import "fmt" + +func main() { + ch := make(chan string) + go sendData(ch) + getData(ch) +} + +func sendData(ch chan string) { + ch <- "Washington" + ch <- "Tripoli" + ch <- "London" + ch <- "Beijing" + ch <- "Tokio" + close(ch) +} + +func getData(ch chan string) { + for { + input, open := <-ch + if !open { + break + } + fmt.Printf("%s ", input) + } +} +// Washington Tripoli London Beijing Tokio \ No newline at end of file diff --git a/eBook/examples/chapter_14/goroutine_select.go b/eBook/examples/chapter_14/goroutine_select.go new file mode 100644 index 0000000..b88877f --- /dev/null +++ b/eBook/examples/chapter_14/goroutine_select.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + ch1 := make(chan int) + ch2 := make(chan int) + + go pump1(ch1) + go pump2(ch2) + go suck(ch1, ch2) + + time.Sleep(1e9) +} + +func pump1(ch chan int) { + for i := 0; ; i++ { + ch <- i * 2 + } +} + +func pump2(ch chan int) { + for i := 0; ; i++ { + ch <- i + 5 + } +} + +func suck(ch1, ch2 chan int) { + for { + select { + case v := <-ch1: + fmt.Printf("Received on channel 1: %d\n", v) + case v := <-ch2: + fmt.Printf("Received on channel 2: %d\n", v) + } + } +} diff --git a/eBook/examples/chapter_14/goroutine_select2.go b/eBook/examples/chapter_14/goroutine_select2.go new file mode 100644 index 0000000..8adb7c2 --- /dev/null +++ b/eBook/examples/chapter_14/goroutine_select2.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "time" + "runtime" +) + +func main() { + // setting GOMAXPROCS to 2 gives +- 22% performance increase, + // but increasing the number doesn't increase the performance + // without GOMAXPROCS: +- 86000 + // setting GOMAXPROCS to 2: +- 105000 + // setting GOMAXPROCS to 3: +- 94000 + runtime.GOMAXPROCS(2) + ch1 := make(chan int) + ch2 := make(chan int) + + go pump1(ch1) + go pump2(ch2) + go suck(ch1, ch2) + + time.Sleep(1e9) +} + +func pump1(ch chan int) { + for i:=0; ; i++ { + ch <- i*2 + } +} + +func pump2(ch chan int) { + for i:=0; ; i++ { + ch <- i+5 + } +} + +func suck(ch1,ch2 chan int) { + for i := 0; ; i++ { + select { + case v := <- ch1: + fmt.Printf("%d - Received on channel 1: %d\n", i, v) + case v := <- ch2: + fmt.Printf("%d - Received on channel 2: %d\n", i, v) + } + } +} + + diff --git a/eBook/examples/chapter_14/lazy_evaluation.go b/eBook/examples/chapter_14/lazy_evaluation.go new file mode 100644 index 0000000..f2e2348 --- /dev/null +++ b/eBook/examples/chapter_14/lazy_evaluation.go @@ -0,0 +1,30 @@ +// lazy_evaluation.go +package main + +import ( + "fmt" +) + +var resume chan int + +func integers() chan int { + yield := make (chan int) + count := 0 + go func () { + for { + yield <- count + count++ + } + } () + return yield +} + +func generateInteger() int { + return <-resume +} +func main() { + resume = integers() + fmt.Println(generateInteger()) //=> 0 + fmt.Println(generateInteger()) //=> 1 + fmt.Println(generateInteger()) //=> 2 +} diff --git a/eBook/examples/chapter_14/max_tasks.go b/eBook/examples/chapter_14/max_tasks.go new file mode 100644 index 0000000..6965b32 --- /dev/null +++ b/eBook/examples/chapter_14/max_tasks.go @@ -0,0 +1,31 @@ +package main + +const MAXREQS = 50 +var sem = make(chan int, MAXREQS) + +type Request struct { + a, b int + replyc chan int +} + +func process(r *Request) { + // do something +} + +func handle(r *Request) { + sem <- 1 // doesn't matter what we put in it + process(r) + <-sem // one empty place in the buffer: the next request can start +} + +func server(service chan *Request) { + for { + request := <-service + go handle(request) + } +} + +func main() { + service := make(chan *Request) + go server(service) +} diff --git a/eBook/examples/chapter_14/multiplex_server.go b/eBook/examples/chapter_14/multiplex_server.go new file mode 100644 index 0000000..86e0b37 --- /dev/null +++ b/eBook/examples/chapter_14/multiplex_server.go @@ -0,0 +1,53 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package main + +import "fmt" + +type Request struct { + a, b int + replyc chan int // reply channel inside the Request +} + +type binOp func(a, b int) int + +func run(op binOp, req *Request) { + req.replyc <- op(req.a, req.b) +} + +func server(op binOp, service chan *Request) { + for { + req := <-service // requests arrive here + // start goroutine for request: + go run(op, req) // don't wait for op + } +} + +func startServer(op binOp) chan *Request { + reqChan := make(chan *Request) + go server(op, reqChan) + return reqChan +} + +func main() { + adder := startServer(func(a, b int) int { return a + b }) + const N = 100 + var reqs [N]Request + for i := 0; i < N; i++ { + req := &reqs[i] + req.a = i + req.b = i + N + req.replyc = make(chan int) + adder <- req + } + // checks: + for i := N - 1; i >= 0; i-- { // doesn't matter what order + if <-reqs[i].replyc != N+2*i { + fmt.Println("fail at", i) + } else { + fmt.Println("Request ", i, " is ok!") + } + } + fmt.Println("done") +} diff --git a/eBook/examples/chapter_14/multiplex_server2.go b/eBook/examples/chapter_14/multiplex_server2.go new file mode 100644 index 0000000..49c0823 --- /dev/null +++ b/eBook/examples/chapter_14/multiplex_server2.go @@ -0,0 +1,58 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package main + +import "fmt" + +type Request struct { + a, b int + replyc chan int // reply channel inside the Request +} + +type binOp func(a, b int) int + +func run(op binOp, req *Request) { + req.replyc <- op(req.a, req.b) +} + +func server(op binOp, service chan *Request, quit chan bool) { + for { + select { + case req := <-service: + go run(op, req) + case <-quit: + return + } + } +} + +func startServer(op binOp) (service chan *Request, quit chan bool) { + service = make(chan *Request) + quit = make(chan bool) + go server(op, service, quit) + return service, quit +} + +func main() { + adder, quit := startServer(func(a, b int) int { return a + b }) + const N = 100 + var reqs [N]Request + for i := 0; i < N; i++ { + req := &reqs[i] + req.a = i + req.b = i + N + req.replyc = make(chan int) + adder <- req + } + // checks: + for i := N - 1; i >= 0; i-- { // doesn't matter what order + if <-reqs[i].replyc != N+2*i { + fmt.Println("fail at", i) + } else { + fmt.Println("Request ", i, " is ok!") + } + } + quit <- true + fmt.Println("done") +} diff --git a/eBook/examples/chapter_14/sieve1.go b/eBook/examples/chapter_14/sieve1.go new file mode 100644 index 0000000..184c76e --- /dev/null +++ b/eBook/examples/chapter_14/sieve1.go @@ -0,0 +1,37 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file.package main +package main + +import "fmt" + +// Send the sequence 2, 3, 4, ... to channel 'ch'. +func generate(ch chan int) { + for i := 2; ; i++ { + ch <- i // Send 'i' to channel 'ch'. + } +} + +// Copy the values from channel 'in' to channel 'out', +// removing those divisible by 'prime'. +func filter(in, out chan int, prime int) { + for { + i := <-in // Receive value of new variable 'i' from 'in'. + if i%prime != 0 { + out <- i // Send 'i' to channel 'out'. + } + } +} + +// The prime sieve: Daisy-chain filter processes together. +func main() { + ch := make(chan int) // Create a new channel. + go generate(ch) // Start generate() as a goroutine. + for { + prime := <-ch + fmt.Print(prime, " ") + ch1 := make(chan int) + go filter(ch, ch1, prime) + ch = ch1 + } +} diff --git a/eBook/examples/chapter_14/sieve2.go b/eBook/examples/chapter_14/sieve2.go new file mode 100644 index 0000000..c3e4299 --- /dev/null +++ b/eBook/examples/chapter_14/sieve2.go @@ -0,0 +1,53 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +// Send the sequence 2, 3, 4, ... to returned channel +func generate() chan int { + ch := make(chan int) + go func() { + for i := 2; ; i++ { + ch <- i + } + }() + return ch +} + +// Filter out input values divisible by 'prime', send rest to returned channel +func filter(in chan int, prime int) chan int { + out := make(chan int) + go func() { + for { + if i := <-in; i%prime != 0 { + out <- i + } + } + }() + return out +} + +func sieve() chan int { + out := make(chan int) + go func() { + ch := generate() + for { + prime := <-ch + ch = filter(ch, prime) + out <- prime + } + }() + return out +} + +func main() { + primes := sieve() + for { + fmt.Println(<-primes) + } +} diff --git a/eBook/examples/chapter_14/timer_goroutine.go b/eBook/examples/chapter_14/timer_goroutine.go new file mode 100644 index 0000000..d9bfb5a --- /dev/null +++ b/eBook/examples/chapter_14/timer_goroutine.go @@ -0,0 +1,42 @@ +// default.go +package main + +import ( + "fmt" + "time" +) + +func main() { + tick := time.Tick(1e8) + boom := time.After(5e8) + for { + select { + case <-tick: + fmt.Println("tick.") + case <-boom: + fmt.Println("BOOM!") + return + default: + fmt.Println(" .") + time.Sleep(5e7) + } + } +} +/* Output: + . + . +tick. + . + . +tick. + . + . +tick. + . + . +tick. + . + . +tick. +BOOM! +*/ diff --git a/eBook/examples/chapter_16/closures_goroutines.go b/eBook/examples/chapter_16/closures_goroutines.go new file mode 100644 index 0000000..7c2fdbe --- /dev/null +++ b/eBook/examples/chapter_16/closures_goroutines.go @@ -0,0 +1,47 @@ +// closures_goroutines.go +package main + +import ( + "fmt" + "time" +) + +var values = [5]int{10, 11, 12, 13, 14} + +func main() { + // version A: + for ix := range values { // ix is index! + func() { + fmt.Print(ix, " ") + }() // call closure, prints each index + } + fmt.Println() + // version B: same as A, but call closure as a goroutine + for ix := range values { + go func() { + fmt.Print(ix, " ") + }() + } + time.Sleep(1e9) + // version C: the right way + for ix := range values { + go func(ix interface{}) { + fmt.Print(ix, " ") + }(ix) + } + time.Sleep(1e9) + // version D: print out the values: + for ix := range values { + val := values[ix] + go func() { + fmt.Print(val, " ") + }() + } + time.Sleep(1e9) +} +/* Output: +0 1 2 3 4 +4 4 4 4 4 +1 0 3 4 2 +0 1 2 4 3 +*/ diff --git a/eBook/examples/chapter_16/pointer_interface.go b/eBook/examples/chapter_16/pointer_interface.go new file mode 100644 index 0000000..18858b4 --- /dev/null +++ b/eBook/examples/chapter_16/pointer_interface.go @@ -0,0 +1,31 @@ +// nexter.go +package main + +import ( + "fmt" +) + +type nexter interface { + next() byte +} + + +func nextFew1(n nexter, num int) []byte { + var b []byte + for i:=0; i < num; i++ { + b[i] = n.next() + } + return b +} + +func nextFew2(n *nexter, num int) []byte { + var b []byte + for i:=0; i < num; i++ { + b[i] = n.next() // compile error: n.next undefined (type *nexter has no field or method next) + } + return b +} + +func main() { + fmt.Println("Hello World!") +} diff --git a/eBook/examples/chapter_19/goto_v1/Makefile b/eBook/examples/chapter_19/goto_v1/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v1/key.go b/eBook/examples/chapter_19/goto_v1/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v1/main.go b/eBook/examples/chapter_19/goto_v1/main.go new file mode 100644 index 0000000..bcac800 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "net/http" +) + +const AddForm = ` +
+URL: + +
+` +var store = NewURLStore() + +func main() { + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(":8080", nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://localhost:8080/%s", key) +} diff --git a/eBook/examples/chapter_19/goto_v1/store.go b/eBook/examples/chapter_19/goto_v1/store.go new file mode 100644 index 0000000..1d6e598 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/store.go @@ -0,0 +1,45 @@ +package main + +import "sync" + +type URLStore struct { + urls map[string]string + mu sync.RWMutex +} + +func NewURLStore() *URLStore { + return &URLStore{urls: make(map[string]string)} +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) // generate the short URL + if ok := s.Set(key, url); ok { + return key + } + } + // shouldn't get here + return "" +} diff --git a/eBook/examples/chapter_19/goto_v2/Makefile b/eBook/examples/chapter_19/goto_v2/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v2/key.go b/eBook/examples/chapter_19/goto_v2/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v2/main.go b/eBook/examples/chapter_19/goto_v2/main.go new file mode 100644 index 0000000..4849910 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "net/http" +) + +var store = NewURLStore("store.gob") + +func main() { + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(":8080", nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://localhost:8080/%s", key) +} + +const AddForm = ` +
+URL: + +
+` diff --git a/eBook/examples/chapter_19/goto_v2/store.go b/eBook/examples/chapter_19/goto_v2/store.go new file mode 100644 index 0000000..0de2fd1 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/store.go @@ -0,0 +1,90 @@ +package main + +import ( + "encoding/gob" + "io" + "log" + "os" + "sync" +) + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + file *os.File +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{urls: make(map[string]string)} + f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore:", err) + } + s.file = f + if err := s.load(); err != nil { + log.Println("Error loading URLStore:", err) + } + return s +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) + if ok := s.Set(key, url); ok { + if err := s.save(key, url); err != nil { + log.Println("Error saving to URLStore:", err) + } + return key + } + } + panic("shouldn't get here") +} + +func (s *URLStore) load() error { + if _, err := s.file.Seek(0, 0); err != nil { + return err + } + d := gob.NewDecoder(s.file) + var err error + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(r.Key, r.URL) + } + } + if err == io.EOF { + return nil + } + return err +} + +func (s *URLStore) save(key, url string) error { + e := gob.NewEncoder(s.file) + return e.Encode(record{key, url}) +} diff --git a/eBook/examples/chapter_19/goto_v2/store.gob b/eBook/examples/chapter_19/goto_v2/store.gob new file mode 100644 index 0000000..e69de29 diff --git a/eBook/examples/chapter_19/goto_v3/Makefile b/eBook/examples/chapter_19/goto_v3/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v3/key.go b/eBook/examples/chapter_19/goto_v3/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v3/main.go b/eBook/examples/chapter_19/goto_v3/main.go new file mode 100644 index 0000000..f7b6503 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "flag" + "fmt" + "net/http" +) + +var ( + listenAddr = flag.String("http", ":8080", "http listen address") + dataFile = flag.String("file", "store.gob", "data store file name") + hostname = flag.String("host", "localhost:8080", "http host name") +) + +var store *URLStore + +func main() { + flag.Parse() + store = NewURLStore(*dataFile) + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(*listenAddr, nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://%s/%s", *hostname, key) +} + +const AddForm = ` +
+URL: + +
+` diff --git a/eBook/examples/chapter_19/goto_v3/store.go b/eBook/examples/chapter_19/goto_v3/store.go new file mode 100644 index 0000000..bb55289 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/store.go @@ -0,0 +1,111 @@ +package main + +import ( +// "bufio" + "encoding/gob" + "io" + "log" + "os" + "sync" +) + +const saveQueueLength = 1000 + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + save chan record +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{ + urls: make(map[string]string), + save: make(chan record, saveQueueLength), + } + if err := s.load(filename); err != nil { + log.Println("Error loading URLStore:", err) + } + go s.saveLoop(filename) + return s +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) + if ok := s.Set(key, url); ok { + s.save <- record{key, url} + return key + } + } + panic("shouldn't get here") +} + +func (s *URLStore) load(filename string) error { + f, err := os.Open(filename) + if err != nil { + log.Println("Error opening URLStore:", err) + return err + } + defer f.Close() + // buffered reading: + // b := bufio.NewReader(f) + // d := gob.NewDecoder(b) + d := gob.NewDecoder(f) + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(r.Key, r.URL) + } + } + if err == io.EOF { + return nil + } + // error occurred: + log.Println("Error decoding URLStore:", err) // map hasn't been read correctly + return err +} + +func (s *URLStore) saveLoop(filename string) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore: ", err) + } + defer f.Close() + e := gob.NewEncoder(f) + // buffered encoding: + // b := bufio.NewWriter(f) + // e := gob.NewEncoder(b) + // defer b.Flush() + for { + r := <-s.save // takes a record from the channel + if err := e.Encode(r); err != nil { + log.Println("Error saving to URLStore: ", err) + } + } +} diff --git a/eBook/examples/chapter_19/goto_v3/store.gob b/eBook/examples/chapter_19/goto_v3/store.gob new file mode 100644 index 0000000..ded3e3d Binary files /dev/null and b/eBook/examples/chapter_19/goto_v3/store.gob differ diff --git a/eBook/examples/chapter_19/goto_v4/Makefile b/eBook/examples/chapter_19/goto_v4/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v4/key.go b/eBook/examples/chapter_19/goto_v4/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v4/main.go b/eBook/examples/chapter_19/goto_v4/main.go new file mode 100644 index 0000000..3c6ee0e --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "flag" + "fmt" + "net/http" +) + +var ( + listenAddr = flag.String("http", ":8080", "http listen address") + dataFile = flag.String("file", "store.json", "data store file name") + hostname = flag.String("host", "localhost:8080", "http host name") +) + +var store *URLStore + +func main() { + flag.Parse() + store = NewURLStore(*dataFile) + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(*listenAddr, nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://%s/%s", *hostname, key) +} + +const AddForm = ` +
+URL: + +
+` diff --git a/eBook/examples/chapter_19/goto_v4/store.go b/eBook/examples/chapter_19/goto_v4/store.go new file mode 100644 index 0000000..54d5421 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/store.go @@ -0,0 +1,103 @@ +package main + +import ( + "encoding/json" + "io" + "log" + "os" + "sync" +) + +const saveQueueLength = 1000 + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + save chan record +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{ + urls: make(map[string]string), + save: make(chan record, saveQueueLength), + } + if err := s.load(filename); err != nil { + log.Println("Error loading URLStore:", err) + } + go s.saveLoop(filename) + return s +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) + if ok := s.Set(key, url); ok { + s.save <- record{key, url} + return key + } + } + panic("shouldn't get here") +} + +func (s *URLStore) load(filename string) error { + f, err := os.Open(filename) + if err != nil { + log.Println("Error opening URLStore:", err) + return err + } + defer f.Close() + d := json.NewDecoder(f) + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(r.Key, r.URL) + } + } + if err == io.EOF { + return nil + } + // error occurred: + log.Println("Error decoding URLStore:", err) // map hasn't been read correctly + return err +} + +func (s *URLStore) saveLoop(filename string) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore: ", err) + } + defer f.Close() + e := json.NewEncoder(f) + for { + r := <-s.save // takes a record from the channel + if err := e.Encode(r); err != nil { + log.Println("Error saving to URLStore: ", err) + } + } +} diff --git a/eBook/examples/chapter_19/goto_v4/store.json b/eBook/examples/chapter_19/goto_v4/store.json new file mode 100644 index 0000000..deaa85c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/store.json @@ -0,0 +1,4 @@ +{"Key":"0","URL":"http://www.standaard.be"} +{"Key":"1","URL":"http://www.google.be"} +{"Key":"2","URL":"http://www.gva.be"} +{"Key":"3","URL":"http://www.golang.org"} diff --git a/eBook/examples/chapter_19/goto_v5/Makefile b/eBook/examples/chapter_19/goto_v5/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v5/demo.sh b/eBook/examples/chapter_19/goto_v5/demo.sh new file mode 100644 index 0000000..e87576b --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/demo.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +gomake +./goto -http=:8081 -rpc=true & +master_pid=$! +sleep 1 +./goto -master=127.0.0.1:8081 & +slave_pid=$! +echo "Running master on :8081, slave on :8080." +echo "Visit: http://localhost:8080/add" +echo "Press enter to shut down" +read +kill $master_pid +kill $slave_pid + diff --git a/eBook/examples/chapter_19/goto_v5/key.go b/eBook/examples/chapter_19/goto_v5/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v5/main.go b/eBook/examples/chapter_19/goto_v5/main.go new file mode 100644 index 0000000..c054498 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/main.go @@ -0,0 +1,70 @@ +package main + +import ( + "flag" + "fmt" + "net/http" + "net/rpc" +) + +var ( + listenAddr = flag.String("http", ":8080", "http listen address") + dataFile = flag.String("file", "store.gob", "data store file name") + hostname = flag.String("host", "localhost:8080", "http host name") + masterAddr = flag.String("master", "", "RPC master address") + rpcEnabled = flag.Bool("rpc", false, "enable RPC server") +) + +var store Store + +func main() { + flag.Parse() + if *masterAddr != "" { + store = NewProxyStore(*masterAddr) + } else { + store = NewURLStore(*dataFile) + } + if *rpcEnabled { // the master is the rpc server: + rpc.RegisterName("Store", store) + rpc.HandleHTTP() + } + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(*listenAddr, nil) + +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + if key == "" { + http.NotFound(w, r) + return + } + var url string + if err := store.Get(&key, &url); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + var key string + if err := store.Put(&url, &key); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + fmt.Fprintf(w, "http://%s/%s", *hostname, key) +} + +const AddForm = ` +
+URL: + +
+` diff --git a/eBook/examples/chapter_19/goto_v5/store.go b/eBook/examples/chapter_19/goto_v5/store.go new file mode 100644 index 0000000..557799f --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/store.go @@ -0,0 +1,147 @@ +package main + +import ( + "encoding/gob" + "errors" + "io" + "log" + "os" + "net/rpc" + "sync" +) + +const saveQueueLength = 1000 + +type Store interface { + Put(url, key *string) error + Get(key, url *string) error +} + +type ProxyStore struct { + urls *URLStore // local cache + client *rpc.Client +} + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + save chan record +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{urls: make(map[string]string)} + if filename != "" { + s.save = make(chan record, saveQueueLength) + if err := s.load(filename); err != nil { + log.Println("Error loading URLStore: ", err) + } + go s.saveLoop(filename) + } + return s +} + +func (s *URLStore) Get(key, url *string) error { + s.mu.RLock() + defer s.mu.RUnlock() + if u, ok := s.urls[*key]; ok { + *url = u + return nil + } + return errors.New("key not found") +} + +func (s *URLStore) Set(key, url *string) error { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[*key]; present { + return errors.New("key already exists") + } + s.urls[*key] = *url + return nil +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url, key *string) error { + for { + *key = genKey(s.Count()) + if err := s.Set(key, url); err == nil { + break + } + } + if s.save != nil { + s.save <- record{*key, *url} + } + return nil +} + +func (s *URLStore) load(filename string) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + d := gob.NewDecoder(f) + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(&r.Key, &r.URL) + } + } + if err == io.EOF { + return nil + } + return err +} + +func (s *URLStore) saveLoop(filename string) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore: ", err) + } + e := gob.NewEncoder(f) + for { + r := <-s.save + if err := e.Encode(r); err != nil { + log.Println("Error saving to URLStore: ", err) + } + } +} + +func NewProxyStore(addr string) *ProxyStore { + client, err := rpc.DialHTTP("tcp", addr) + if err != nil { + log.Println("Error constructing ProxyStore: ", err) + // return // ? + } + return &ProxyStore{urls: NewURLStore(""), client: client} +} + +func (s *ProxyStore) Get(key, url *string) error { + if err := s.urls.Get(key, url); err == nil { + return nil + } + // rpc call to master: + if err := s.client.Call("Store.Get", key, url); err != nil { + return err + } + s.urls.Set(key, url) // update local cache + return nil +} + +func (s *ProxyStore) Put(url, key *string) error { + // rpc call to master: + if err := s.client.Call("Store.Put", url, key); err != nil { + return err + } + s.urls.Set(key, url) // update local cache + return nil +} diff --git a/eBook/examples/chapter_19/goto_v5/store.gob b/eBook/examples/chapter_19/goto_v5/store.gob new file mode 100644 index 0000000..89eabaf Binary files /dev/null and b/eBook/examples/chapter_19/goto_v5/store.gob differ diff --git a/eBook/examples/chapter_2/hello_world1.go b/eBook/examples/chapter_2/hello_world1.go index 6a6e5a7..0c71f1b 100644 --- a/eBook/examples/chapter_2/hello_world1.go +++ b/eBook/examples/chapter_2/hello_world1.go @@ -1,7 +1,7 @@ -// hello_world1.go -package main - -func main() { - println("Hello", "world") -} - +// hello_world1.go +package main + +func main() { + println("Hello", "world") +} + diff --git a/eBook/examples/chapter_2/version.go b/eBook/examples/chapter_2/version.go index 485eec4..b470bbf 100644 --- a/eBook/examples/chapter_2/version.go +++ b/eBook/examples/chapter_2/version.go @@ -1,12 +1,12 @@ -package main - -import ( - "fmt" - "runtime" -) - -func main() { - fmt.Printf("%s", runtime.Version()) -} -// Output: -// go1.0.3 or go 1.1 +package main + +import ( + "fmt" + "runtime" +) + +func main() { + fmt.Printf("%s", runtime.Version()) +} +// Output: +// go1.0.3 or go 1.1 diff --git a/eBook/examples/chapter_20/helloapp/app.yaml b/eBook/examples/chapter_20/helloapp/app.yaml new file mode 100644 index 0000000..baa19d9 --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/app.yaml @@ -0,0 +1,8 @@ +application: helloworld +version: 1 +runtime: go +api_version: 3 + +handlers: +- url: /.* + script: _go_app diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go new file mode 100644 index 0000000..66d664d --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go @@ -0,0 +1,14 @@ +package hello + +import ( + "fmt" + "net/http" +) + +func init() { + http.HandleFunc("/", handler) +} + +func handler(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello, world!") +} diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go new file mode 100644 index 0000000..848a534 --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go @@ -0,0 +1,28 @@ +package hello + +import ( + "appengine" + "appengine/user" + "fmt" + "net/http" +) + +func init() { + http.HandleFunc("/", handler) +} + +func handler(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + u := user.Current(c) + if u == nil { + url, err := user.LoginURL(c, r.URL.String()) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + w.Header().Set("Location", url) + w.WriteHeader(http.StatusFound) + return + } + fmt.Fprintf(w, "Hello, %v!", u) +} diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go new file mode 100644 index 0000000..38a5f50 --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go @@ -0,0 +1,46 @@ +package hello + +import ( + "fmt" + "net/http" + "template" +) + +const guestbookForm = ` + + +
+
+
+
+ + +` +const signTemplateHTML = ` + + +

You wrote:

+
{{html .}}
+ + +` +var signTemplate = template.Must(template.New("sign").Parse(signTemplateHTML)) + +func init() { + http.HandleFunc("/", root) + http.HandleFunc("/sign", sign) +} + +func root(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + fmt.Fprint(w, guestbookForm) +} + +func sign(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + err := signTemplate.Execute(w, r.FormValue("content")) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + } +} + diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go new file mode 100644 index 0000000..51b72ae --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go @@ -0,0 +1,72 @@ +package hello + +import ( + "appengine" + "appengine/datastore" + "appengine/user" + "net/http" + "template" + "time" +) + +const guestbookTemplateHTML = ` + + + {{range .}} + {{with .Author}} +

{{html .}} wrote:

+ {{else}} +

An anonymous person wrote:

+ {{end}} +
{{html .Content}}
+
{{html .Date}}
+ {{end}} +
+
+
+
+ + +` +var guestbookTemplate = template.Must(template.New("book").Parse(guestbookTemplateHTML)) + +type Greeting struct { + Author string + Content string + Date datastore.Time +} + +func init() { + http.HandleFunc("/", root) + http.HandleFunc("/sign", sign) +} + +func root(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + q := datastore.NewQuery("Greeting").Order("-Date").Limit(10) + greetings := make([]Greeting, 0, 10) + if _, err := q.GetAll(c, &greetings); err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + if err := guestbookTemplate.Execute(w, greetings); err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + } +} + +func sign(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + g := Greeting{ + Content: r.FormValue("content"), + Date: datastore.SecondsToTime(time.Seconds()), + } + if u := user.Current(c); u != nil { + g.Author = u.String() + } + _, err := datastore.Put(c, datastore.NewIncompleteKey(c, "Greeting", nil), &g) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, "/", http.StatusFound) +} diff --git a/eBook/examples/chapter_20/helloworld.go b/eBook/examples/chapter_20/helloworld.go new file mode 100644 index 0000000..70fa14d --- /dev/null +++ b/eBook/examples/chapter_20/helloworld.go @@ -0,0 +1,16 @@ +// helloworld.go +package helloworld + +import ( + "fmt" + "net/http" +) + +func init() { + http.HandleFunc("/", handle) +} + +func handle(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello, World! 세상아 안녕!! ") +} + diff --git a/eBook/examples/chapter_3/CandGo/Makefile b/eBook/examples/chapter_3/CandGo/Makefile index a05adee..9c5f632 100644 --- a/eBook/examples/chapter_3/CandGo/Makefile +++ b/eBook/examples/chapter_3/CandGo/Makefile @@ -1,7 +1,7 @@ -include $(GOROOT)/src/Make.inc - -TARG=rand -CGOFILES=\ - c1.go\ - +include $(GOROOT)/src/Make.inc + +TARG=rand +CGOFILES=\ + c1.go\ + include $(GOROOT)/src/Make.pkg \ No newline at end of file diff --git a/eBook/examples/chapter_3/CandGo/c1.go b/eBook/examples/chapter_3/CandGo/c1.go index c072630..77f1854 100644 --- a/eBook/examples/chapter_3/CandGo/c1.go +++ b/eBook/examples/chapter_3/CandGo/c1.go @@ -1,13 +1,13 @@ -// c1.go -package rand - -// #include -import "C" - -func Random() int { - return int(C.random()) -} - -func Seed(i int) { - C.srandom(C.uint(i)) -} +// c1.go +package rand + +// #include +import "C" + +func Random() int { + return int(C.random()) +} + +func Seed(i int) { + C.srandom(C.uint(i)) +} diff --git a/eBook/examples/chapter_3/CandGo/c2.go b/eBook/examples/chapter_3/CandGo/c2.go index f734763..ba96ee4 100644 --- a/eBook/examples/chapter_3/CandGo/c2.go +++ b/eBook/examples/chapter_3/CandGo/c2.go @@ -1,13 +1,13 @@ -// c2.go -package print - -// #include -// #include -import "C" -import "unsafe" - -func Print(s string) { - cs := C.CString(s) - defer C.free(unsafe.Pointer(cs)) - C.fputs(cs, (*C.FILE)(C.stdout)) -} +// c2.go +package print + +// #include +// #include +import "C" +import "unsafe" + +func Print(s string) { + cs := C.CString(s) + defer C.free(unsafe.Pointer(cs)) + C.fputs(cs, (*C.FILE)(C.stdout)) +} diff --git a/eBook/examples/chapter_3/Makefile b/eBook/examples/chapter_3/Makefile index 0026f79..0b7b04b 100644 --- a/eBook/examples/chapter_3/Makefile +++ b/eBook/examples/chapter_3/Makefile @@ -1,7 +1,7 @@ - include $(GOROOT)/src/Make.inc -TARG=test -GOFILES=\ - test1.go\ -test2.go\ - -include $(GOROOT)/src/Make.cmd + include $(GOROOT)/src/Make.inc +TARG=test +GOFILES=\ + test1.go\ +test2.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_3/gocomp b/eBook/examples/chapter_3/gocomp index a7c79f7..3ff0197 100644 --- a/eBook/examples/chapter_3/gocomp +++ b/eBook/examples/chapter_3/gocomp @@ -1,9 +1,9 @@ -#!/bin/bash -FILES=~/goprograms/compiletest/*.go -for f in $FILES -do - echo "Processing $f file..." - # take action on each file. $f stores current file name - # cat $f - 6g $f >> compout -done +#!/bin/bash +FILES=~/goprograms/compiletest/*.go +for f in $FILES +do + echo "Processing $f file..." + # take action on each file. $f stores current file name + # cat $f + 6g $f >> compout +done diff --git a/eBook/examples/chapter_3/gocomp.bat b/eBook/examples/chapter_3/gocomp.bat index 4c9770c..20382c1 100644 --- a/eBook/examples/chapter_3/gocomp.bat +++ b/eBook/examples/chapter_3/gocomp.bat @@ -1,2 +1,2 @@ -FOR %%X in (*.go) DO 8g %%X >> compout - +FOR %%X in (*.go) DO 8g %%X >> compout + diff --git a/eBook/examples/chapter_3/run.cmd b/eBook/examples/chapter_3/run.cmd index 9b47375..59a1d5e 100644 --- a/eBook/examples/chapter_3/run.cmd +++ b/eBook/examples/chapter_3/run.cmd @@ -1,9 +1,9 @@ -set GOROOT=E:\Go\GoforWindows\gowin32_release.r59\go -set GOBIN=$GOROOT\bin -set PATH=%PATH%;$GOBIN -set GOARCH=386 -set GOOS=windows -echo off -8g %1.go -8l -o %1.exe %1.8 -%1 +set GOROOT=E:\Go\GoforWindows\gowin32_release.r59\go +set GOBIN=$GOROOT\bin +set PATH=%PATH%;$GOBIN +set GOARCH=386 +set GOOS=windows +echo off +8g %1.go +8l -o %1.exe %1.8 +%1 diff --git a/eBook/examples/chapter_4/alias.go b/eBook/examples/chapter_4/alias.go index ba30f40..5c0c829 100644 --- a/eBook/examples/chapter_4/alias.go +++ b/eBook/examples/chapter_4/alias.go @@ -1,7 +1,7 @@ -package main - -import fm "fmt" // alias - -func main() { - fm.Println("hello, world") -} +package main + +import fm "fmt" // alias + +func main() { + fm.Println("hello, world") +} diff --git a/eBook/examples/chapter_4/casting.go b/eBook/examples/chapter_4/casting.go index 35850d6..cacf560 100644 --- a/eBook/examples/chapter_4/casting.go +++ b/eBook/examples/chapter_4/casting.go @@ -1,18 +1,18 @@ -package main -import "fmt" - -func main() { - var n int16 = 34 - var m int32 - -// compiler error: cannot use n (type int16) as type int32 in assignment - //m = n - m = int32(n) - - fmt.Printf("32 bit int is: %d\n", m) - fmt.Printf("16 bit int is: %d\n", n) -} -/* Output: -32 bit int is: 34 -16 bit int is: 34 +package main +import "fmt" + +func main() { + var n int16 = 34 + var m int32 + +// compiler error: cannot use n (type int16) as type int32 in assignment + //m = n + m = int32(n) + + fmt.Printf("32 bit int is: %d\n", m) + fmt.Printf("16 bit int is: %d\n", n) +} +/* Output: +32 bit int is: 34 +16 bit int is: 34 */ \ No newline at end of file diff --git a/eBook/examples/chapter_4/char.go b/eBook/examples/chapter_4/char.go index 67e5668..e450ab4 100644 --- a/eBook/examples/chapter_4/char.go +++ b/eBook/examples/chapter_4/char.go @@ -1,22 +1,22 @@ -// char.go -package main - -import ( - "fmt" -) - -func main() { - var ch int = '\u0041' - var ch2 int = '\u03B2' - var ch3 int = '\U00101234' - fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) - fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) - fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) - fmt.Printf("%U - %U - %U", ch, ch2, ch3) -} -/* Ouput: -65 - 946 - 1053236 -A - β - 􁈴 -41 - 3B2 - 101234 -U+0041 - U+03B2 - U+101234 +// char.go +package main + +import ( + "fmt" +) + +func main() { + var ch int = '\u0041' + var ch2 int = '\u03B2' + var ch3 int = '\U00101234' + fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) + fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) + fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) + fmt.Printf("%U - %U - %U", ch, ch2, ch3) +} +/* Ouput: +65 - 946 - 1053236 +A - β - 􁈴 +41 - 3B2 - 101234 +U+0041 - U+03B2 - U+101234 */ \ No newline at end of file diff --git a/eBook/examples/chapter_4/count_substring.go b/eBook/examples/chapter_4/count_substring.go index e97712f..d9927a6 100644 --- a/eBook/examples/chapter_4/count_substring.go +++ b/eBook/examples/chapter_4/count_substring.go @@ -1,17 +1,17 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var str string = "Hello, how is it going, Hugo?" - var manyG = "gggggggggg" - - fmt.Printf("Number of H's in %s is: ", str) - fmt.Printf("%d\n", strings.Count(str, "H")) - - fmt.Printf("Number of double g's in %s is: ", manyG) - fmt.Printf("%d\n", strings.Count(manyG, "gg")) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var str string = "Hello, how is it going, Hugo?" + var manyG = "gggggggggg" + + fmt.Printf("Number of H's in %s is: ", str) + fmt.Printf("%d\n", strings.Count(str, "H")) + + fmt.Printf("Number of double g's in %s is: ", manyG) + fmt.Printf("%d\n", strings.Count(manyG, "gg")) +} diff --git a/eBook/examples/chapter_4/function_calls_function.go b/eBook/examples/chapter_4/function_calls_function.go index 12ebdab..84509c9 100644 --- a/eBook/examples/chapter_4/function_calls_function.go +++ b/eBook/examples/chapter_4/function_calls_function.go @@ -1,15 +1,15 @@ -package main -var a string -func main() { - a = "G" - print(a) - f1() -} -func f1() { - a := "O" - print(a) - f2() -} -func f2() { - print(a) +package main +var a string +func main() { + a = "G" + print(a) + f1() +} +func f1() { + a := "O" + print(a) + f2() +} +func f2() { + print(a) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/global_scope.go b/eBook/examples/chapter_4/global_scope.go index 5b1ff29..558afce 100644 --- a/eBook/examples/chapter_4/global_scope.go +++ b/eBook/examples/chapter_4/global_scope.go @@ -1,14 +1,14 @@ -package main -var a = "G" -func main() { - n() - m() - n() -} -func n() { - print(a) -} -func m() { - a = "O" - print(a) +package main +var a = "G" +func main() { + n() + m() + n() +} +func n() { + print(a) +} +func m() { + a = "O" + print(a) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/goos.go b/eBook/examples/chapter_4/goos.go index 90fb6eb..9fe9a46 100644 --- a/eBook/examples/chapter_4/goos.go +++ b/eBook/examples/chapter_4/goos.go @@ -1,25 +1,25 @@ -package main -<<<<<<< HEAD - -======= ->>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 -import ( - "fmt" - "os" -) -<<<<<<< HEAD - -func main() { - var goos string = os.Getenv("GOOS") - fmt.Printf("The operating system is: %s\n", goos) - path := os.Getenv("PATH") - fmt.Printf("Path is %s\n", path) -} -======= -func main() { - var goos string = os.Getenv("GOOS") - fmt.Printf("The operating system is: %s\n", goos) - path := os.Getenv("PATH") - fmt.Printf("Path is %s\n", path) -} ->>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 +package main +<<<<<<< HEAD + +======= +>>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 +import ( + "fmt" + "os" +) +<<<<<<< HEAD + +func main() { + var goos string = os.Getenv("GOOS") + fmt.Printf("The operating system is: %s\n", goos) + path := os.Getenv("PATH") + fmt.Printf("Path is %s\n", path) +} +======= +func main() { + var goos string = os.Getenv("GOOS") + fmt.Printf("The operating system is: %s\n", goos) + path := os.Getenv("PATH") + fmt.Printf("Path is %s\n", path) +} +>>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 diff --git a/eBook/examples/chapter_4/gotemplate.go b/eBook/examples/chapter_4/gotemplate.go index 68de9ca..aafb5ab 100644 --- a/eBook/examples/chapter_4/gotemplate.go +++ b/eBook/examples/chapter_4/gotemplate.go @@ -1,30 +1,30 @@ -package main - -import ( - "fmt" -) - -const c = "C" - -var v int = 5 - -type T struct{} - -func init() { - // initialization of package -} - -func main() { - var a int - Func1() - // ... - fmt.Println(a) -} - -func (t T) Method1() { - //... -} - -func Func1() { // exported function Func1 - //... -} +package main + +import ( + "fmt" +) + +const c = "C" + +var v int = 5 + +type T struct{} + +func init() { + // initialization of package +} + +func main() { + var a int + Func1() + // ... + fmt.Println(a) +} + +func (t T) Method1() { + //... +} + +func Func1() { // exported function Func1 + //... +} diff --git a/eBook/examples/chapter_4/hello_world.go b/eBook/examples/chapter_4/hello_world.go index c3cb0ae..8e4e589 100644 --- a/eBook/examples/chapter_4/hello_world.go +++ b/eBook/examples/chapter_4/hello_world.go @@ -1,7 +1,7 @@ -package main - -import "fmt" - -func main() { - fmt.Println("hello, world") -} +package main + +import "fmt" + +func main() { + fmt.Println("hello, world") +} diff --git a/eBook/examples/chapter_4/hello_world2.go b/eBook/examples/chapter_4/hello_world2.go index e8e85c4..c52d126 100644 --- a/eBook/examples/chapter_4/hello_world2.go +++ b/eBook/examples/chapter_4/hello_world2.go @@ -1,7 +1,7 @@ -package main - -import "fmt" // Package implementing formatted I/O. - -func main() { - fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n") -} +package main + +import "fmt" // Package implementing formatted I/O. + +func main() { + fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n") +} diff --git a/eBook/examples/chapter_4/index_in_string.go b/eBook/examples/chapter_4/index_in_string.go index 2964bfa..abc9d07 100644 --- a/eBook/examples/chapter_4/index_in_string.go +++ b/eBook/examples/chapter_4/index_in_string.go @@ -1,21 +1,21 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var str string = "Hi, I'm Marc, Hi." - - fmt.Printf("The position of \"Marc\" is: ") - fmt.Printf("%d\n", strings.Index(str, "Marc")) - - fmt.Printf("The position of the first instance of \"Hi\" is: ") - fmt.Printf("%d\n", strings.Index(str, "Hi")) - fmt.Printf("The position of the last instance of \"Hi\" is: ") - fmt.Printf("%d\n", strings.LastIndex(str, "Hi")) - - fmt.Printf("The position of \"Burger\" is: ") - fmt.Printf("%d\n", strings.Index(str, "Burger")) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var str string = "Hi, I'm Marc, Hi." + + fmt.Printf("The position of \"Marc\" is: ") + fmt.Printf("%d\n", strings.Index(str, "Marc")) + + fmt.Printf("The position of the first instance of \"Hi\" is: ") + fmt.Printf("%d\n", strings.Index(str, "Hi")) + fmt.Printf("The position of the last instance of \"Hi\" is: ") + fmt.Printf("%d\n", strings.LastIndex(str, "Hi")) + + fmt.Printf("The position of \"Burger\" is: ") + fmt.Printf("%d\n", strings.Index(str, "Burger")) +} diff --git a/eBook/examples/chapter_4/init.go b/eBook/examples/chapter_4/init.go index 26f07ca..023e570 100644 --- a/eBook/examples/chapter_4/init.go +++ b/eBook/examples/chapter_4/init.go @@ -1,17 +1,17 @@ -package trans -<<<<<<< HEAD - -import "math" - -var Pi float64 - -func init() { - Pi = 4 * math.Atan(1) // init() function computes Pi -} -======= -import "math" -var Pi float64 -func init() { - Pi = 4 * math.Atan(1) // init() function computes Pi -} ->>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 +package trans +<<<<<<< HEAD + +import "math" + +var Pi float64 + +func init() { + Pi = 4 * math.Atan(1) // init() function computes Pi +} +======= +import "math" +var Pi float64 +func init() { + Pi = 4 * math.Atan(1) // init() function computes Pi +} +>>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 diff --git a/eBook/examples/chapter_4/local_scope.go b/eBook/examples/chapter_4/local_scope.go index 7fd3aea..decff22 100644 --- a/eBook/examples/chapter_4/local_scope.go +++ b/eBook/examples/chapter_4/local_scope.go @@ -1,12 +1,12 @@ -package main -var a = "G" -func main() { - n() - m() - n() -} -func n() { print(a) } -func m() { - a := "O" - print(a) +package main +var a = "G" +func main() { + n() + m() + n() +} +func n() { print(a) } +func m() { + a := "O" + print(a) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/pointer.go b/eBook/examples/chapter_4/pointer.go index ff230fd..1ae2248 100644 --- a/eBook/examples/chapter_4/pointer.go +++ b/eBook/examples/chapter_4/pointer.go @@ -1,12 +1,12 @@ -package main - -import "fmt" - -func main() { - var i1 = 5 - fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1) - - var intP *int - intP = &i1 - fmt.Printf("The value at memory location %p is %d\n", intP, *intP) -} +package main + +import "fmt" + +func main() { + var i1 = 5 + fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1) + + var intP *int + intP = &i1 + fmt.Printf("The value at memory location %p is %d\n", intP, *intP) +} diff --git a/eBook/examples/chapter_4/presuffix.go b/eBook/examples/chapter_4/presuffix.go index c7484f6..7b4fd88 100644 --- a/eBook/examples/chapter_4/presuffix.go +++ b/eBook/examples/chapter_4/presuffix.go @@ -1,14 +1,14 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var str string = "This is an example of a string" - - fmt.Printf("T/F? Does the string \"%s\" have prefix %s? ", str, "Th") - fmt.Printf("%t\n", strings.HasPrefix(str, "Th")) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var str string = "This is an example of a string" + + fmt.Printf("T/F? Does the string \"%s\" have prefix %s? ", str, "Th") + fmt.Printf("%t\n", strings.HasPrefix(str, "Th")) +} // Output: T/F? Does the string "This is an example of a string" have prefix Th? true \ No newline at end of file diff --git a/eBook/examples/chapter_4/random.go b/eBook/examples/chapter_4/random.go index 9dc8e61..2c5c604 100644 --- a/eBook/examples/chapter_4/random.go +++ b/eBook/examples/chapter_4/random.go @@ -1,28 +1,28 @@ -package main - -import ( - "fmt" - "math/rand" - "time" -) - -func main() { - for i := 0; i < 10; i++ { - a := rand.Int() - fmt.Printf("%d / ", a) - } - for i := 0; i < 5; i++ { - r := rand.Intn(8) - fmt.Printf("%d / ", r) - } - fmt.Println() - timens := int64(time.Now().Nanosecond()) - rand.Seed(timens) - for i := 0; i < 10; i++ { - fmt.Printf("%2.2f / ", 100*rand.Float32()) - } -} -/* Output: -134020434 / 1597969999 / 1721070109 / 2068675587 / 1237770961 / 220031192 / 2031484958 / 583324308 / 958990240 / 413002649 / 6 / 7 / 2 / 1 / 0 / -22.84 / 10.12 / 44.32 / 58.58 / 15.49 / 12.23 / 30.16 / 88.48 / 34.26 / 27.18 / -*/ +package main + +import ( + "fmt" + "math/rand" + "time" +) + +func main() { + for i := 0; i < 10; i++ { + a := rand.Int() + fmt.Printf("%d / ", a) + } + for i := 0; i < 5; i++ { + r := rand.Intn(8) + fmt.Printf("%d / ", r) + } + fmt.Println() + timens := int64(time.Now().Nanosecond()) + rand.Seed(timens) + for i := 0; i < 10; i++ { + fmt.Printf("%2.2f / ", 100*rand.Float32()) + } +} +/* Output: +134020434 / 1597969999 / 1721070109 / 2068675587 / 1237770961 / 220031192 / 2031484958 / 583324308 / 958990240 / 413002649 / 6 / 7 / 2 / 1 / 0 / +22.84 / 10.12 / 44.32 / 58.58 / 15.49 / 12.23 / 30.16 / 88.48 / 34.26 / 27.18 / +*/ diff --git a/eBook/examples/chapter_4/repeat_string.go b/eBook/examples/chapter_4/repeat_string.go index 043ee14..426e76f 100644 --- a/eBook/examples/chapter_4/repeat_string.go +++ b/eBook/examples/chapter_4/repeat_string.go @@ -1,14 +1,14 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var origS string = "Hi there! " - var newS string - - newS = strings.Repeat(origS, 3) - fmt.Printf("The new repeated string is: %s\n", newS) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var origS string = "Hi there! " + var newS string + + newS = strings.Repeat(origS, 3) + fmt.Printf("The new repeated string is: %s\n", newS) +} diff --git a/eBook/examples/chapter_4/string_conversion.go b/eBook/examples/chapter_4/string_conversion.go index 4506023..61a6ff1 100644 --- a/eBook/examples/chapter_4/string_conversion.go +++ b/eBook/examples/chapter_4/string_conversion.go @@ -1,20 +1,20 @@ -package main - -import ( - "fmt" - "strconv" -) - -func main() { - var orig string = "666" - var an int - var newS string - - fmt.Printf("The size of ints is: %d\n", strconv.IntSize) - - an, _ = strconv.Atoi(orig) - fmt.Printf("The integer is: %d\n", an) - an = an + 5 - newS = strconv.Itoa(an) - fmt.Printf("The new string is: %s\n", newS) -} +package main + +import ( + "fmt" + "strconv" +) + +func main() { + var orig string = "666" + var an int + var newS string + + fmt.Printf("The size of ints is: %d\n", strconv.IntSize) + + an, _ = strconv.Atoi(orig) + fmt.Printf("The integer is: %d\n", an) + an = an + 5 + newS = strconv.Itoa(an) + fmt.Printf("The new string is: %s\n", newS) +} diff --git a/eBook/examples/chapter_4/string_pointer.go b/eBook/examples/chapter_4/string_pointer.go index abd62bd..7448423 100644 --- a/eBook/examples/chapter_4/string_pointer.go +++ b/eBook/examples/chapter_4/string_pointer.go @@ -1,13 +1,13 @@ -package main - -import "fmt" - -func main() { - s := "good bye" - var p *string = &s - *p = "ciao" - - fmt.Printf("Here is the pointer p: %p\n", p) // prints address - fmt.Printf("Here is the string *p: %s\n", *p) // prints string - fmt.Printf("Here is the string s: %s\n", s) // prints same string -} +package main + +import "fmt" + +func main() { + s := "good bye" + var p *string = &s + *p = "ciao" + + fmt.Printf("Here is the pointer p: %p\n", p) // prints address + fmt.Printf("Here is the string *p: %s\n", *p) // prints string + fmt.Printf("Here is the string s: %s\n", s) // prints same string +} diff --git a/eBook/examples/chapter_4/strings_splitjoin.go b/eBook/examples/chapter_4/strings_splitjoin.go index 8d64620..a31d43c 100644 --- a/eBook/examples/chapter_4/strings_splitjoin.go +++ b/eBook/examples/chapter_4/strings_splitjoin.go @@ -1,33 +1,33 @@ -// strings.go -package main - -import ( - "fmt" - "strings" -) - -func main() { - str := "The quick brown fox jumps over the lazy dog" - sl := strings.Fields(str) - fmt.Printf("Splitted in slice: %v\n", sl) - for _, val := range sl { - fmt.Printf("%s - ", val) - } - fmt.Println() - str2 := "GO1|The ABC of Go|25" - sl2 := strings.Split(str2, "|") - fmt.Printf("Splitted in slice: %v\n", sl2) - for _, val := range sl2 { - fmt.Printf("%s - ", val) - } - fmt.Println() - str3 := strings.Join(sl2,";") - fmt.Printf("sl2 joined by ;: %s\n", str3) -} -/* Output: -Splitted in slice: [The quick brown fox jumps over the lazy dog] -The - quick - brown - fox - jumps - over - the - lazy - dog - -Splitted in slice: [GO1 The ABC of Go 25] -GO1 - The ABC of Go - 25 - -sl2 joined by ;: GO1;The ABC of Go;25 +// strings.go +package main + +import ( + "fmt" + "strings" +) + +func main() { + str := "The quick brown fox jumps over the lazy dog" + sl := strings.Fields(str) + fmt.Printf("Splitted in slice: %v\n", sl) + for _, val := range sl { + fmt.Printf("%s - ", val) + } + fmt.Println() + str2 := "GO1|The ABC of Go|25" + sl2 := strings.Split(str2, "|") + fmt.Printf("Splitted in slice: %v\n", sl2) + for _, val := range sl2 { + fmt.Printf("%s - ", val) + } + fmt.Println() + str3 := strings.Join(sl2,";") + fmt.Printf("sl2 joined by ;: %s\n", str3) +} +/* Output: +Splitted in slice: [The quick brown fox jumps over the lazy dog] +The - quick - brown - fox - jumps - over - the - lazy - dog - +Splitted in slice: [GO1 The ABC of Go 25] +GO1 - The ABC of Go - 25 - +sl2 joined by ;: GO1;The ABC of Go;25 */ \ No newline at end of file diff --git a/eBook/examples/chapter_4/testcrash.go b/eBook/examples/chapter_4/testcrash.go index e2891c1..faff80f 100644 --- a/eBook/examples/chapter_4/testcrash.go +++ b/eBook/examples/chapter_4/testcrash.go @@ -1,11 +1,11 @@ -// testcrash.go -// compiles , but crashes -package main - -func main() { - var p *int = nil - *p = 0 - -} -// in Windows: stops only with: -// runtime error: invalid memory address or nil pointer dereference +// testcrash.go +// compiles , but crashes +package main + +func main() { + var p *int = nil + *p = 0 + +} +// in Windows: stops only with: +// runtime error: invalid memory address or nil pointer dereference diff --git a/eBook/examples/chapter_4/time.go b/eBook/examples/chapter_4/time.go index 1228c20..4ebf08e 100644 --- a/eBook/examples/chapter_4/time.go +++ b/eBook/examples/chapter_4/time.go @@ -1,27 +1,27 @@ -package main - -import ( - "fmt" - "time" -) - -var week time.Duration - -func main() { - t := time.Now() - fmt.Println(t) // Wed Dec 21 09:52:14 +0100 RST 2011 - fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) // 21.12.2011 - t = time.Now().UTC() - fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011 - fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011 - // calculating times: - week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec - week_from_now := t.Add(week) - fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011 - // formatting times: - fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC - fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011 - fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52 - s := t.Format("20060102") - fmt.Println(t, "=>", s) // Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221 -} +package main + +import ( + "fmt" + "time" +) + +var week time.Duration + +func main() { + t := time.Now() + fmt.Println(t) // Wed Dec 21 09:52:14 +0100 RST 2011 + fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) // 21.12.2011 + t = time.Now().UTC() + fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011 + fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011 + // calculating times: + week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec + week_from_now := t.Add(week) + fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011 + // formatting times: + fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC + fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011 + fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52 + s := t.Format("20060102") + fmt.Println(t, "=>", s) // Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221 +} diff --git a/eBook/examples/chapter_4/toupper_lower.go b/eBook/examples/chapter_4/toupper_lower.go index a170831..6cb2b36 100644 --- a/eBook/examples/chapter_4/toupper_lower.go +++ b/eBook/examples/chapter_4/toupper_lower.go @@ -1,18 +1,18 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var orig string = "Hey, how are you George?" - var lower string - var upper string - - fmt.Printf("The original string is: %s\n", orig) - lower = strings.ToLower(orig) - fmt.Printf("The lowercase string is: %s\n", lower) - upper = strings.ToUpper(orig) - fmt.Printf("The uppercase string is: %s\n", upper) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var orig string = "Hey, how are you George?" + var lower string + var upper string + + fmt.Printf("The original string is: %s\n", orig) + lower = strings.ToLower(orig) + fmt.Printf("The lowercase string is: %s\n", lower) + upper = strings.ToUpper(orig) + fmt.Printf("The uppercase string is: %s\n", upper) +} diff --git a/eBook/examples/chapter_4/type.go b/eBook/examples/chapter_4/type.go index 5f1d539..a541098 100644 --- a/eBook/examples/chapter_4/type.go +++ b/eBook/examples/chapter_4/type.go @@ -1,11 +1,11 @@ -package main - -import "fmt" - -type TZ int - -func main() { - var a, b TZ = 3, 4 - c := a + b - fmt.Printf("c has the value: %d", c) +package main + +import "fmt" + +type TZ int + +func main() { + var a, b TZ = 3, 4 + c := a + b + fmt.Printf("c has the value: %d", c) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/type_mixing.go b/eBook/examples/chapter_4/type_mixing.go index d59eee8..1814249 100644 --- a/eBook/examples/chapter_4/type_mixing.go +++ b/eBook/examples/chapter_4/type_mixing.go @@ -1,9 +1,9 @@ -package main - -func main() { - var a int - var b int32 - a = 15 - b = a + a // compiler error - b = b + 5 // ok: 5 is a constant +package main + +func main() { + var a int + var b int32 + a = 15 + b = a + a // compiler error + b = b + 5 // ok: 5 is a constant } \ No newline at end of file diff --git a/eBook/examples/chapter_4/use_init.go b/eBook/examples/chapter_4/use_init.go index 9cdf255..9b9a62f 100644 --- a/eBook/examples/chapter_4/use_init.go +++ b/eBook/examples/chapter_4/use_init.go @@ -1,12 +1,12 @@ -package main - -import ( - "fmt" - "./trans" -) - -var twoPi = 2 * trans.Pi // decl computes twoPi - -func main() { - fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 -} +package main + +import ( + "fmt" + "./trans" +) + +var twoPi = 2 * trans.Pi // decl computes twoPi + +func main() { + fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 +} diff --git a/eBook/examples/chapter_4/user_init.go b/eBook/examples/chapter_4/user_init.go index fc59361..6f4dd20 100644 --- a/eBook/examples/chapter_4/user_init.go +++ b/eBook/examples/chapter_4/user_init.go @@ -1,9 +1,9 @@ -package main -import ( - "fmt" - "./trans" -) -var twoPi = 2 * trans.Pi -func main() { - fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 +package main +import ( + "fmt" + "./trans" +) +var twoPi = 2 * trans.Pi +func main() { + fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 } \ No newline at end of file diff --git a/eBook/examples/chapter_5/booleans.go b/eBook/examples/chapter_5/booleans.go index bcf145f..3b29401 100644 --- a/eBook/examples/chapter_5/booleans.go +++ b/eBook/examples/chapter_5/booleans.go @@ -1,12 +1,12 @@ -package main - -import "fmt" - -func main() { - bool1 := true - if bool1 { - fmt.Printf("The value is true\n") - } else { - fmt.Printf("The value is false\n") - } -} +package main + +import "fmt" + +func main() { + bool1 := true + if bool1 { + fmt.Printf("The value is true\n") + } else { + fmt.Printf("The value is false\n") + } +} diff --git a/eBook/examples/chapter_5/for1.go b/eBook/examples/chapter_5/for1.go index 79f958a..66efa90 100644 --- a/eBook/examples/chapter_5/for1.go +++ b/eBook/examples/chapter_5/for1.go @@ -1,9 +1,9 @@ -package main - -import "fmt" - -func main() { - for i := 0; i < 5; i++ { - fmt.Printf("This is the %d iteration\n", i) - } -} +package main + +import "fmt" + +func main() { + for i := 0; i < 5; i++ { + fmt.Printf("This is the %d iteration\n", i) + } +} diff --git a/eBook/examples/chapter_5/for2.go b/eBook/examples/chapter_5/for2.go index bf9b294..dceb993 100644 --- a/eBook/examples/chapter_5/for2.go +++ b/eBook/examples/chapter_5/for2.go @@ -1,12 +1,12 @@ -package main - -import "fmt" - -func main() { - var i int = 5 - - for i >= 0 { - i = i - 1 - fmt.Printf("The variable i is now: %d\n", i) - } -} +package main + +import "fmt" + +func main() { + var i int = 5 + + for i >= 0 { + i = i - 1 + fmt.Printf("The variable i is now: %d\n", i) + } +} diff --git a/eBook/examples/chapter_5/for3.go b/eBook/examples/chapter_5/for3.go index 62bd74b..7a045ae 100644 --- a/eBook/examples/chapter_5/for3.go +++ b/eBook/examples/chapter_5/for3.go @@ -1,15 +1,15 @@ -package main - -import "fmt" - -func main() { - var i int = 5 - - for { - i = i - 1 - fmt.Printf("The variable i is now: %d\n", i) - if i < 0 { - break - } - } -} +package main + +import "fmt" + +func main() { + var i int = 5 + + for { + i = i - 1 + fmt.Printf("The variable i is now: %d\n", i) + if i < 0 { + break + } + } +} diff --git a/eBook/examples/chapter_5/for4.go b/eBook/examples/chapter_5/for4.go index cb16d54..6f5c7ab 100644 --- a/eBook/examples/chapter_5/for4.go +++ b/eBook/examples/chapter_5/for4.go @@ -1,13 +1,13 @@ -package main - -func main() { - for i:=0; i<3; i++ { - for j:=0; j<10; j++ { - if j>5 { - break - } - print(j) - } - print(" ") - } +package main + +func main() { + for i:=0; i<3; i++ { + for j:=0; j<10; j++ { + if j>5 { + break + } + print(j) + } + print(" ") + } } \ No newline at end of file diff --git a/eBook/examples/chapter_5/for5.go b/eBook/examples/chapter_5/for5.go index 6e1135e..475b926 100644 --- a/eBook/examples/chapter_5/for5.go +++ b/eBook/examples/chapter_5/for5.go @@ -1,11 +1,11 @@ -package main - -func main() { - for i := 0; i < 10; i++ { - if i == 5 { - continue - } - print(i) - print(" ") - } -} +package main + +func main() { + for i := 0; i < 10; i++ { + if i == 5 { + continue + } + print(i) + print(" ") + } +} diff --git a/eBook/examples/chapter_5/for6.go b/eBook/examples/chapter_5/for6.go index 81a96d8..bf04e78 100644 --- a/eBook/examples/chapter_5/for6.go +++ b/eBook/examples/chapter_5/for6.go @@ -1,17 +1,17 @@ -package main - -import "fmt" - -func main() { - -LABEL1: - for i := 0; i <= 5; i++ { - for j := 0; j <= 5; j++ { - if j == 4 { - continue LABEL1 - } - fmt.Printf("i is: %d, and j is: %d\n", i, j) - } - } - -} +package main + +import "fmt" + +func main() { + +LABEL1: + for i := 0; i <= 5; i++ { + for j := 0; j <= 5; j++ { + if j == 4 { + continue LABEL1 + } + fmt.Printf("i is: %d, and j is: %d\n", i, j) + } + } + +} diff --git a/eBook/examples/chapter_5/for_string.go b/eBook/examples/chapter_5/for_string.go index 7b18921..97b8d59 100644 --- a/eBook/examples/chapter_5/for_string.go +++ b/eBook/examples/chapter_5/for_string.go @@ -1,57 +1,57 @@ -// for_string.go -package main - -import "fmt" - -func main() { - str := "Go is a beautiful language!" - fmt.Printf("The length of str is: %d\n", len(str)) - for ix :=0; ix < len(str); ix++ { - fmt.Printf("Character on position %d is: %c \n", ix, str[ix]) - } - str2 := "日本語" - fmt.Printf("The length of str2 is: %d\n", len(str2)) - for ix :=0; ix < len(str2); ix++ { - fmt.Printf("Character on position %d is: %c \n", ix, str2[ix]) - } -} -/* Output: -The length of str is: 27 -Character on position 0 is: G -Character on position 1 is: o -Character on position 2 is: -Character on position 3 is: i -Character on position 4 is: s -Character on position 5 is: -Character on position 6 is: a -Character on position 7 is: -Character on position 8 is: b -Character on position 9 is: e -Character on position 10 is: a -Character on position 11 is: u -Character on position 12 is: t -Character on position 13 is: i -Character on position 14 is: f -Character on position 15 is: u -Character on position 16 is: l -Character on position 17 is: -Character on position 18 is: l -Character on position 19 is: a -Character on position 20 is: n -Character on position 21 is: g -Character on position 22 is: u -Character on position 23 is: a -Character on position 24 is: g -Character on position 25 is: e -Character on position 26 is: ! -The length of str2 is: 9 -Character on position 0 is: æ -Character on position 1 is: — -Character on position 2 is: ¥ -Character on position 3 is: æ -Character on position 4 is: œ -Character on position 5 is: ¬ -Character on position 6 is: è -Character on position 7 is: ª -Character on position 8 is: ž +// for_string.go +package main + +import "fmt" + +func main() { + str := "Go is a beautiful language!" + fmt.Printf("The length of str is: %d\n", len(str)) + for ix :=0; ix < len(str); ix++ { + fmt.Printf("Character on position %d is: %c \n", ix, str[ix]) + } + str2 := "日本語" + fmt.Printf("The length of str2 is: %d\n", len(str2)) + for ix :=0; ix < len(str2); ix++ { + fmt.Printf("Character on position %d is: %c \n", ix, str2[ix]) + } +} +/* Output: +The length of str is: 27 +Character on position 0 is: G +Character on position 1 is: o +Character on position 2 is: +Character on position 3 is: i +Character on position 4 is: s +Character on position 5 is: +Character on position 6 is: a +Character on position 7 is: +Character on position 8 is: b +Character on position 9 is: e +Character on position 10 is: a +Character on position 11 is: u +Character on position 12 is: t +Character on position 13 is: i +Character on position 14 is: f +Character on position 15 is: u +Character on position 16 is: l +Character on position 17 is: +Character on position 18 is: l +Character on position 19 is: a +Character on position 20 is: n +Character on position 21 is: g +Character on position 22 is: u +Character on position 23 is: a +Character on position 24 is: g +Character on position 25 is: e +Character on position 26 is: ! +The length of str2 is: 9 +Character on position 0 is: æ +Character on position 1 is: — +Character on position 2 is: ¥ +Character on position 3 is: æ +Character on position 4 is: œ +Character on position 5 is: ¬ +Character on position 6 is: è +Character on position 7 is: ª +Character on position 8 is: ž */ \ No newline at end of file diff --git a/eBook/examples/chapter_5/goto.go b/eBook/examples/chapter_5/goto.go index e61b47c..c36a7ea 100644 --- a/eBook/examples/chapter_5/goto.go +++ b/eBook/examples/chapter_5/goto.go @@ -1,12 +1,12 @@ -package main - -func main() { - i:=0 - HERE: - print(i) - i++ - if i==5 { - return - } - goto HERE +package main + +func main() { + i:=0 + HERE: + print(i) + i++ + if i==5 { + return + } + goto HERE } \ No newline at end of file diff --git a/eBook/examples/chapter_5/goto2.go b/eBook/examples/chapter_5/goto2.go index 705b9a9..118f47c 100644 --- a/eBook/examples/chapter_5/goto2.go +++ b/eBook/examples/chapter_5/goto2.go @@ -1,13 +1,13 @@ -// compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8 -package main - -import "fmt" - -func main() { - a := 1 - goto TARGET // compile error - b := 9 - TARGET: - b += a - fmt.Printf("a is %v *** b is %v", a, b) +// compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8 +package main + +import "fmt" + +func main() { + a := 1 + goto TARGET // compile error + b := 9 + TARGET: + b += a + fmt.Printf("a is %v *** b is %v", a, b) } \ No newline at end of file diff --git a/eBook/examples/chapter_5/ifelse.go b/eBook/examples/chapter_5/ifelse.go index 0b8dc61..aad629e 100644 --- a/eBook/examples/chapter_5/ifelse.go +++ b/eBook/examples/chapter_5/ifelse.go @@ -1,22 +1,22 @@ -package main - -import "fmt" - -func main() { - var first int = 10 - var cond int - - if first <= 0 { - fmt.Printf("first is less than or equal to 0\n") - } else if first > 0 && first < 5 { - fmt.Printf("first is between 0 and 5\n") - } else { - fmt.Printf("first is 5 or greater\n") - } - - if cond = 5; cond > 10 { - fmt.Printf("cond is greater than 10\n") - } else { - fmt.Printf("cond is not greater than 10\n") - } -} +package main + +import "fmt" + +func main() { + var first int = 10 + var cond int + + if first <= 0 { + fmt.Printf("first is less than or equal to 0\n") + } else if first > 0 && first < 5 { + fmt.Printf("first is between 0 and 5\n") + } else { + fmt.Printf("first is 5 or greater\n") + } + + if cond = 5; cond > 10 { + fmt.Printf("cond is greater than 10\n") + } else { + fmt.Printf("cond is not greater than 10\n") + } +} diff --git a/eBook/examples/chapter_5/range_string.go b/eBook/examples/chapter_5/range_string.go index f5bdc2e..465b392 100644 --- a/eBook/examples/chapter_5/range_string.go +++ b/eBook/examples/chapter_5/range_string.go @@ -1,80 +1,80 @@ -package main - -import "fmt" - -func main() { - str := "Go is a beautiful language!" - fmt.Printf("The length of str is: %d\n", len(str)) - for pos, char := range str { - fmt.Printf("Character on position %d is: %c \n", pos, char) - } - fmt.Println() - str2 := "Chinese: 日本語" - fmt.Printf("The length of str2 is: %d\n", len(str2)) - for pos, char := range str2 { - fmt.Printf("character %c starts at byte position %d\n", char, pos) - } - fmt.Println() - fmt.Println("index int(rune) rune char bytes") - for index, rune := range str2 { - fmt.Printf("%-2d %d %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune))) - } -} -/* Output: -The length of str is: 27 -Character on position 0 is: G -Character on position 1 is: o -Character on position 2 is: -Character on position 3 is: i -Character on position 4 is: s -Character on position 5 is: -Character on position 6 is: a -Character on position 7 is: -Character on position 8 is: b -Character on position 9 is: e -Character on position 10 is: a -Character on position 11 is: u -Character on position 12 is: t -Character on position 13 is: i -Character on position 14 is: f -Character on position 15 is: u -Character on position 16 is: l -Character on position 17 is: -Character on position 18 is: l -Character on position 19 is: a -Character on position 20 is: n -Character on position 21 is: g -Character on position 22 is: u -Character on position 23 is: a -Character on position 24 is: g -Character on position 25 is: e -Character on position 26 is: ! - -The length of str2 is: 18 -character C starts at byte position 0 -character h starts at byte position 1 -character i starts at byte position 2 -character n starts at byte position 3 -character e starts at byte position 4 -character s starts at byte position 5 -character e starts at byte position 6 -character : starts at byte position 7 -character starts at byte position 8 -character 日 starts at byte position 9 -character 本 starts at byte position 12 -character 語 starts at byte position 15 - -index int(rune) rune char bytes -0 67 U+0043 'C' 43 -1 104 U+0068 'h' 68 -2 105 U+0069 'i' 69 -3 110 U+006E 'n' 6E -4 101 U+0065 'e' 65 -5 115 U+0073 's' 73 -6 101 U+0065 'e' 65 -7 58 U+003A ':' 3A -8 32 U+0020 ' ' 20 -9 26085 U+65E5 '日' E6 97 A5 -12 26412 U+672C '本' E6 9C AC -15 35486 U+8A9E '語' E8 AA 9E -*/ +package main + +import "fmt" + +func main() { + str := "Go is a beautiful language!" + fmt.Printf("The length of str is: %d\n", len(str)) + for pos, char := range str { + fmt.Printf("Character on position %d is: %c \n", pos, char) + } + fmt.Println() + str2 := "Chinese: 日本語" + fmt.Printf("The length of str2 is: %d\n", len(str2)) + for pos, char := range str2 { + fmt.Printf("character %c starts at byte position %d\n", char, pos) + } + fmt.Println() + fmt.Println("index int(rune) rune char bytes") + for index, rune := range str2 { + fmt.Printf("%-2d %d %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune))) + } +} +/* Output: +The length of str is: 27 +Character on position 0 is: G +Character on position 1 is: o +Character on position 2 is: +Character on position 3 is: i +Character on position 4 is: s +Character on position 5 is: +Character on position 6 is: a +Character on position 7 is: +Character on position 8 is: b +Character on position 9 is: e +Character on position 10 is: a +Character on position 11 is: u +Character on position 12 is: t +Character on position 13 is: i +Character on position 14 is: f +Character on position 15 is: u +Character on position 16 is: l +Character on position 17 is: +Character on position 18 is: l +Character on position 19 is: a +Character on position 20 is: n +Character on position 21 is: g +Character on position 22 is: u +Character on position 23 is: a +Character on position 24 is: g +Character on position 25 is: e +Character on position 26 is: ! + +The length of str2 is: 18 +character C starts at byte position 0 +character h starts at byte position 1 +character i starts at byte position 2 +character n starts at byte position 3 +character e starts at byte position 4 +character s starts at byte position 5 +character e starts at byte position 6 +character : starts at byte position 7 +character starts at byte position 8 +character 日 starts at byte position 9 +character 本 starts at byte position 12 +character 語 starts at byte position 15 + +index int(rune) rune char bytes +0 67 U+0043 'C' 43 +1 104 U+0068 'h' 68 +2 105 U+0069 'i' 69 +3 110 U+006E 'n' 6E +4 101 U+0065 'e' 65 +5 115 U+0073 's' 73 +6 101 U+0065 'e' 65 +7 58 U+003A ':' 3A +8 32 U+0020 ' ' 20 +9 26085 U+65E5 '日' E6 97 A5 +12 26412 U+672C '本' E6 9C AC +15 35486 U+8A9E '語' E8 AA 9E +*/ diff --git a/eBook/examples/chapter_5/string_conversion2.go b/eBook/examples/chapter_5/string_conversion2.go index 4add5eb..49e9479 100644 --- a/eBook/examples/chapter_5/string_conversion2.go +++ b/eBook/examples/chapter_5/string_conversion2.go @@ -1,25 +1,25 @@ -package main - -import ( - "fmt" - "strconv" -) - -func main() { - var orig string = "ABC" - // var an int - var newS string - // var err error - - fmt.Printf("The size of ints is: %d\n", strconv.IntSize) - // anInt, err = strconv.Atoi(origStr) - an, err := strconv.Atoi(orig) - if err != nil { - fmt.Printf("orig %s is not an integer - exiting with error\n", orig) - return - } - fmt.Printf("The integer is %d\n", an) - an = an + 5 - newS = strconv.Itoa(an) - fmt.Printf("The new string is: %s\n", newS) -} +package main + +import ( + "fmt" + "strconv" +) + +func main() { + var orig string = "ABC" + // var an int + var newS string + // var err error + + fmt.Printf("The size of ints is: %d\n", strconv.IntSize) + // anInt, err = strconv.Atoi(origStr) + an, err := strconv.Atoi(orig) + if err != nil { + fmt.Printf("orig %s is not an integer - exiting with error\n", orig) + return + } + fmt.Printf("The integer is %d\n", an) + an = an + 5 + newS = strconv.Itoa(an) + fmt.Printf("The new string is: %s\n", newS) +} diff --git a/eBook/examples/chapter_5/switch1.go b/eBook/examples/chapter_5/switch1.go index a108596..e5a2fa0 100644 --- a/eBook/examples/chapter_5/switch1.go +++ b/eBook/examples/chapter_5/switch1.go @@ -1,16 +1,16 @@ -package main - -import "fmt" - -func main() { - var num1 int = 100 - - switch num1 { - case 98, 99: - fmt.Println("It's equal to 98") - case 100: - fmt.Println("It's equal to 100") - default: - fmt.Println("It's not equal to 98 or 100") - } -} +package main + +import "fmt" + +func main() { + var num1 int = 100 + + switch num1 { + case 98, 99: + fmt.Println("It's equal to 98") + case 100: + fmt.Println("It's equal to 100") + default: + fmt.Println("It's not equal to 98 or 100") + } +} diff --git a/eBook/examples/chapter_5/switch2.go b/eBook/examples/chapter_5/switch2.go index 4f0afe8..80ccae0 100644 --- a/eBook/examples/chapter_5/switch2.go +++ b/eBook/examples/chapter_5/switch2.go @@ -1,16 +1,16 @@ -package main - -import "fmt" - -func main() { - var num1 int = 7 - - switch { - case num1 < 0: - fmt.Println("Number is negative") - case num1 > 0 && num1 < 10: - fmt.Println("Number is between 0 and 10") - default: - fmt.Println("Number is 10 or greater") - } -} +package main + +import "fmt" + +func main() { + var num1 int = 7 + + switch { + case num1 < 0: + fmt.Println("Number is negative") + case num1 > 0 && num1 < 10: + fmt.Println("Number is between 0 and 10") + default: + fmt.Println("Number is 10 or greater") + } +} diff --git a/eBook/examples/chapter_6/blank_identifier.go b/eBook/examples/chapter_6/blank_identifier.go index 2731645..e0a04d0 100644 --- a/eBook/examples/chapter_6/blank_identifier.go +++ b/eBook/examples/chapter_6/blank_identifier.go @@ -1,15 +1,14 @@ -package main - -import "fmt" - -func main() { - var i1 int - var f1 float32 - i1, _, f1 = ThreeValues() - fmt.Printf("The int: %d, the float: %f \n", i1, f1) -} - -func ThreeValues() (int, int, float32) { - return 5, 6, 7.5 -} - +package main + +import "fmt" + +func main() { + var i1 int + var f1 float32 + i1, _, f1 = ThreeValues() + fmt.Printf("The int: %d, the float; %f\n", i1, f1) +} + +func ThreeValues() (int, int, float32) { + return 5, 6, 7.5 +} diff --git a/eBook/examples/chapter_6/defer.go b/eBook/examples/chapter_6/defer.go new file mode 100644 index 0000000..61c92c8 --- /dev/null +++ b/eBook/examples/chapter_6/defer.go @@ -0,0 +1,17 @@ +package main + +import "fmt" + +func main() { + Function1() +} + +func Function1() { + fmt.Printf("In Function1 at the top\n") + defer Function2() + fmt.Printf("In Function1 at the bottom!\n") +} + +func Function2() { + fmt.Printf("Function2: Deferred until the end of the calling function!") +} diff --git a/eBook/examples/chapter_6/defer_dbconn.go b/eBook/examples/chapter_6/defer_dbconn.go new file mode 100644 index 0000000..3898669 --- /dev/null +++ b/eBook/examples/chapter_6/defer_dbconn.go @@ -0,0 +1,38 @@ +// defer_dbconn.go +package main + +import "fmt" + +func main() { + doDBOperations() +} + +func connectToDB () { + fmt.Println( "ok, connected to db" ) +} + +func disconnectFromDB () { + fmt.Println( "ok, disconnected from db" ) +} + +func doDBOperations() { + connectToDB() + fmt.Println("Defering the database disconnect.") + defer disconnectFromDB() //function called here with defer + fmt.Println("Doing some DB operations ...") + fmt.Println("Oops! some crash or network error ...") + fmt.Println("Returning from function here!") + return //terminate the program + // deferred function executed here just before actually returning, even if there is a return or abnormal termination before +} +/* Output: +ok, connected to db +Defering the database disconnect. +Doing some DB operations ... +Oops! some crash or network error ... +Returning from function here! +ok, disconnected from db +*/ + + + diff --git a/eBook/examples/chapter_6/defer_logvalues.go b/eBook/examples/chapter_6/defer_logvalues.go new file mode 100644 index 0000000..73d3874 --- /dev/null +++ b/eBook/examples/chapter_6/defer_logvalues.go @@ -0,0 +1,19 @@ +// defer_logvalues.go +package main + +import ( + "io" + "log" +) + +func func1(s string) (n int, err error) { + defer func() { + log.Printf("func1(%q) = %d, %v", s, n, err) + }() + return 7, io.EOF +} + +func main() { + func1("Go") +} +// Output: 2011/10/04 10:46:11 func1("Go") = 7, EOF \ No newline at end of file diff --git a/eBook/examples/chapter_6/defer_tracing.go b/eBook/examples/chapter_6/defer_tracing.go new file mode 100644 index 0000000..b524e41 --- /dev/null +++ b/eBook/examples/chapter_6/defer_tracing.go @@ -0,0 +1,22 @@ +package main + +import "fmt" + +func trace(s string) { fmt.Println("entering:", s) } +func untrace(s string) { fmt.Println("leaving:", s) } + +func a() { + trace("a") + defer untrace("a") + fmt.Println("in a") +} + +func b() { + trace("b") + defer untrace("b") + fmt.Println("in b") + a() +} +func main() { + b() +} diff --git a/eBook/examples/chapter_6/defer_tracing2.go b/eBook/examples/chapter_6/defer_tracing2.go new file mode 100644 index 0000000..03972d3 --- /dev/null +++ b/eBook/examples/chapter_6/defer_tracing2.go @@ -0,0 +1,25 @@ +package main + +import "fmt" + +func trace(s string) string { + fmt.Println("entering:", s) + return s +} +func un(s string) { + fmt.Println("leaving:", s) +} + +func a() { + defer un(trace("a")) + fmt.Println("in a") +} + +func b() { + defer un(trace("b")) + fmt.Println("in b") + a() +} +func main() { + b() +} diff --git a/eBook/examples/chapter_6/fibonacci.go b/eBook/examples/chapter_6/fibonacci.go new file mode 100644 index 0000000..d1f6b0d --- /dev/null +++ b/eBook/examples/chapter_6/fibonacci.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + result := 0 + start := time.Now() + for i:=0; i <= 25; i++ { + result = fibonacci(i) + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + } + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +func fibonacci(n int) (res int) { + if n <= 1 { + res = 1 + } else { + res = fibonacci(n-1) + fibonacci(n-2) + } + return +} +/* Output: +fibonacci(0) is: 1 +fibonacci(1) is: 1 +fibonacci(2) is: 2 +fibonacci(3) is: 3 +fibonacci(4) is: 5 +fibonacci(5) is: 8 +fibonacci(6) is: 13 +fibonacci(7) is: 21 +fibonacci(8) is: 34 +fibonacci(9) is: 55 +fibonacci(10) is: 89 +fibonacci(11) is: 144 +fibonacci(12) is: 233 +fibonacci(13) is: 377 +fibonacci(14) is: 610 +fibonacci(15) is: 987 +fibonacci(16) is: 1597 +fibonacci(17) is: 2584 +fibonacci(18) is: 4181 +fibonacci(19) is: 6765 +fibonacci(20) is: 10946 +fibonacci(21) is: 17711 +fibonacci(22) is: 28657 +fibonacci(23) is: 46368 +fibonacci(24) is: 75025 +fibonacci(25) is: 121393 +longCalculation took this amount of time: 3.0001ms +*/ diff --git a/eBook/examples/chapter_6/fibonacci_memoization.go b/eBook/examples/chapter_6/fibonacci_memoization.go new file mode 100644 index 0000000..0001de6 --- /dev/null +++ b/eBook/examples/chapter_6/fibonacci_memoization.go @@ -0,0 +1,42 @@ +// fibonacci_memoization.go +package main + +import ( + "fmt" + "time" +) + +const LIM = 41 +var fibs [LIM]uint64 + +func main() { + var result uint64 = 0 + start := time.Now() + for i:=0; i < LIM; i++ { + result = fibonacci(i) + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + } + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +func fibonacci(n int) (res uint64) { + // memoization: check if fibonacci(n) is already known in array: + if fibs[n] != 0 { + res = fibs[n] + return + } + if n <= 1 { + res = 1 + } else { + res = fibonacci(n-1) + fibonacci(n-2) + } + fibs[n] = res + return +} +/* +Output: LIM=40: +normal (fibonacci.go): the calculation took this amount of time: 4.730270 s + with memoization: the calculation took this amount of time: 0.001000 s +*/ diff --git a/eBook/examples/chapter_6/filter_factory.go b/eBook/examples/chapter_6/filter_factory.go new file mode 100644 index 0000000..13e6788 --- /dev/null +++ b/eBook/examples/chapter_6/filter_factory.go @@ -0,0 +1,53 @@ +// filter_factory.go +package main +import "fmt" + +type flt func (int) bool +type slice_split func([]int) ([]int, []int) + +func isOdd(integer int) bool{ + if integer%2 == 0 { + return false + } + return true +} + +func isBiggerThan4(integer int) bool{ + if integer > 4 { + return true + } + return false +} + +func filter_factory(f flt) slice_split { + return func(s []int) (yes, no []int){ + for _, val := range s{ + if f(val){ + yes = append(yes, val) + } else { + no = append(no, val) + } + } + return + } +} + +func main(){ + s := []int {1, 2, 3, 4, 5, 7} + fmt.Println("s = ", s) + odd_even_function := filter_factory(isOdd) + odd, even := odd_even_function(s) + fmt.Println("odd = ", odd) + fmt.Println("even = ", even) + //separate those that are bigger than 4 and those that are not. + bigger, smaller := filter_factory(isBiggerThan4)(s) + fmt.Println("Bigger than 4: ", bigger) + fmt.Println("Smaller than or equal to 4: ", smaller) +} +/* +s = [1 2 3 4 5 7] +odd = [1 3 5 7] +even = [2 4] +Bigger than 4: [5 7] +Smaller than or equal to 4: [1 2 3 4] +*/ diff --git a/eBook/examples/chapter_6/function_closure.go b/eBook/examples/chapter_6/function_closure.go new file mode 100644 index 0000000..59104b5 --- /dev/null +++ b/eBook/examples/chapter_6/function_closure.go @@ -0,0 +1,18 @@ +package main + +import "fmt" + +func main() { + var f = Adder() + fmt.Print(f(1)," - ") + fmt.Print(f(20)," - ") + fmt.Print(f(300)) +} + +func Adder() func(int) int { + var x int + return func(delta int) int { + x += delta + return x + } +} diff --git a/eBook/examples/chapter_6/function_filter.go b/eBook/examples/chapter_6/function_filter.go new file mode 100644 index 0000000..fa1a4e7 --- /dev/null +++ b/eBook/examples/chapter_6/function_filter.go @@ -0,0 +1,48 @@ +// function_filter.go +package main +import "fmt" + +type flt func(int) bool + +// isOdd takes an ints and returns a bool set to true if the +// int parameter is odd, or false if not. +// isOdd is of type func(int) bool which is what flt is declared to be. + +func isOdd(n int) bool { + if n%2 == 0 { + return false + } + return true +} + +// Same comment for isEven +func isEven(n int) bool { + if n%2 == 0 { + return true + } + return false +} + +func filter(sl []int, f flt) []int { + var res []int + for _, val := range sl { + if f(val) { + res = append(res, val) + } + } + return res +} + +func main(){ + slice := []int {1, 2, 3, 4, 5, 7} + fmt.Println("slice = ", slice) + odd := filter(slice, isOdd) + fmt.Println("Odd elements of slice are: ", odd) + even := filter(slice, isEven) + fmt.Println("Even elements of slice are: ", even) +} +/* +slice = [1 2 3 4 5 7] +Odd elements of slice are: [1 3 5 7] +Even elements of slice are: [2 4] +*/ diff --git a/eBook/examples/chapter_6/function_literal.go b/eBook/examples/chapter_6/function_literal.go new file mode 100644 index 0000000..ece9faf --- /dev/null +++ b/eBook/examples/chapter_6/function_literal.go @@ -0,0 +1,15 @@ +package main +import "fmt" + +func main() { + f() +} + +func f() { + for i := 0; i < 4; i++ { + g := func(i int) { fmt.Printf("%d ", i) } + g(i) + fmt.Printf(" - g is of type %T and has value %v\n", g, g) + } + +} diff --git a/eBook/examples/chapter_6/function_parameter.go b/eBook/examples/chapter_6/function_parameter.go new file mode 100644 index 0000000..3e2fe40 --- /dev/null +++ b/eBook/examples/chapter_6/function_parameter.go @@ -0,0 +1,20 @@ +// function_parameter.go +package main + +import ( + "fmt" +) + +func main() { + callback(1, Add) +} + +func Add(a,b int) { + fmt.Printf("The sum of %d and %d is: %d\n", a, b, a + b) +} + + +func callback(y int, f func(int, int)) { + f(y, 2) // this becomes Add(1, 2) +} +// Output: The sum of 1 and 2 is: 3 diff --git a/eBook/examples/chapter_6/function_return.go b/eBook/examples/chapter_6/function_return.go new file mode 100644 index 0000000..4d4c72d --- /dev/null +++ b/eBook/examples/chapter_6/function_return.go @@ -0,0 +1,27 @@ +package main +import "fmt" + +func main() { + // make an Add2 function, give it a name p2, and call it: + p2 := Add2() + fmt.Printf("Call Add2 for 2 gives: %v\n", p2(2)) + // make a special Adder function, a gets value 2: + TwoAdder := Adder(2) + fmt.Printf("The result is: %v\n", TwoAdder(2)) +} + +func Add2() (func(b int) int) { + return func(b int) int { + return b + 2 + } +} + +func Adder(a int) (func(b int) int) { + return func(b int) int { + return a + b + } +} +/* Output: +Call Add2 for 2 gives: 4 +The result is: 4 +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_6/greeting.go b/eBook/examples/chapter_6/greeting.go index 10902da..493a00f 100644 --- a/eBook/examples/chapter_6/greeting.go +++ b/eBook/examples/chapter_6/greeting.go @@ -1,11 +1,11 @@ -package main - -func main() { - println("In main before calling greeting") - greeting() - println("In main after calling greeting") -} - -func greeting() { - println("In greeting: Hi!!!!!") -} \ No newline at end of file +package main + +func main() { + println("In main before calling greeting") + greeting() + println("In main after calling greeting") +} + +func greeting() { + println("In greeting: Hi!!!!!") +} diff --git a/eBook/examples/chapter_6/minmax.go b/eBook/examples/chapter_6/minmax.go index 0ccbfb8..f0dc134 100644 --- a/eBook/examples/chapter_6/minmax.go +++ b/eBook/examples/chapter_6/minmax.go @@ -1,20 +1,20 @@ -package main - -import "fmt" - -func main() { - var min, max int - min, max = MinMax(78, 65) - fmt.Printf("Minmium is: %d, Maximum is: %d\n", min, max) -} - -func MinMax(a int, b int) (min int, max int) { - if a < b { - min = a - max = b - } else { // a = b or a < b - min = b - max = a - } - return +package main + +import "fmt" + +func main() { + var min, max int + min, max = MinMax(78, 65) + fmt.Printf("Minimum is: %d, Maximum is: %d\n", min, max) +} + +func MinMax(a int, b int) (min int, max int) { + if a < b { + min = a + max = b + } else { // a = b or a < b + min = b + max = a + } + return } \ No newline at end of file diff --git a/eBook/examples/chapter_6/multiple_return.go b/eBook/examples/chapter_6/multiple_return.go index e1dea97..22304d5 100644 --- a/eBook/examples/chapter_6/multiple_return.go +++ b/eBook/examples/chapter_6/multiple_return.go @@ -1,28 +1,28 @@ -package main - -import "fmt" - -var num int = 10 -var numx2, numx3 int - -func main() { - numx2, numx3 = getX2AndX3(num) - PrintValues() - numx2, numx3 = getX2AndX3_2(num) - PrintValues() -} - -func PrintValues() { - fmt.Printf("num = %d, 2x num = %d, 3x num = %d\n", num, numx2, numx3) -} - -func getX2AndX3(input int) (int, int) { - return 2 * input, 3 * input -} - -func getX2AndX3_2(input int) (x2 int, x3 int) { - x2 = 2 * input - x3 = 3 * input - // return x2, x3 - return -} \ No newline at end of file +package main + +import "fmt" + +var num int = 10 +var numx2, numx3 int + +func main() { + numx2, numx3 = getX2AndX3(num) + PrintValues() + numx2, numx3 = getX2AndX3_2(num) + PrintValues() +} + +func PrintValues() { + fmt.Printf("num = %d, 2x num = %d, 3x num = %d\n", num, numx2, numx3) +} + +func getX2AndX3(input int) (int, int) { + return 2 * input, 3 * input +} + +func getX2AndX3_2(input int) (x2 int, x3 int) { + x2 = 2 * input + x3 = 3 * input + // return x2, x3 + return +} diff --git a/eBook/examples/chapter_6/mut_recurs.go b/eBook/examples/chapter_6/mut_recurs.go new file mode 100644 index 0000000..cc9a8f4 --- /dev/null +++ b/eBook/examples/chapter_6/mut_recurs.go @@ -0,0 +1,27 @@ +// mut_recurs.go +package main + +import ( + "fmt" +) + +func main() { + fmt.Printf("%d is even: is %t\n", 16, even(16)) // 16 is even: is true + fmt.Printf("%d is odd: is %t\n", 17, odd(17)) // 17 is odd: is true + fmt.Printf("%d is odd: is %t\n", 18, odd(18)) // 18 is odd: is false +} + +func even(nr int) bool { + if nr == 0 {return true} + return odd(RevSign(nr)-1) +} + +func odd(nr int) bool { + if nr == 0 {return false} + return even(RevSign(nr)-1) +} + +func RevSign(nr int) int { + if nr < 0 {return -nr} + return nr +} \ No newline at end of file diff --git a/eBook/examples/chapter_6/return_defer.go b/eBook/examples/chapter_6/return_defer.go new file mode 100644 index 0000000..b6a82c7 --- /dev/null +++ b/eBook/examples/chapter_6/return_defer.go @@ -0,0 +1,18 @@ +// test_defer.go +package main + +import ( + "fmt" +) + +func f() (ret int) { + defer func() { + ret++ + }() + return 1 +} + +func main() { + fmt.Println(f()) +} +// Output: 2 diff --git a/eBook/examples/chapter_6/side_effect.go b/eBook/examples/chapter_6/side_effect.go index 700d44f..7c7c055 100644 --- a/eBook/examples/chapter_6/side_effect.go +++ b/eBook/examples/chapter_6/side_effect.go @@ -1,17 +1,18 @@ -package main - -import ( - "fmt" -) - -// this function changes reply: -func Multiply(a, b int, reply *int) { - *reply = a * b -} - -func main() { - n := 0 - reply := &n - Multiply(10, 5, reply) - fmt.Println("Multiply:", *reply) // Multiply: 50 -} \ No newline at end of file +// side_effect.go +package main + +import ( + "fmt" +) + +func Multiply(a, b int, reply *int) { + *reply = a * b +} + +func main() { + n := 0 + reply := &n + Multiply(10, 5, reply) + fmt.Println("Multiply:", *reply) // Multiply: 50 + fmt.Println("Multiply:", n) // Multiply: 50 +} diff --git a/eBook/examples/chapter_6/simple_function.go b/eBook/examples/chapter_6/simple_function.go index deb2e30..3318f96 100644 --- a/eBook/examples/chapter_6/simple_function.go +++ b/eBook/examples/chapter_6/simple_function.go @@ -1,15 +1,15 @@ -package main - -import "fmt" - -func main() { - fmt.Printf("Multiply 2 * 5 * 6 = %d\n", MultiPly3Nums(2, 5, 6)) - // var i1 int = MultiPly3Nums(2, 5, 6) - // fmt.Printf("MultiPly 2 * 5 * 6 = %d\n", i1) -} - -func MultiPly3Nums(a int, b int, c int) int { - // var product int = a * b * c - // return product - return a * b * c -} \ No newline at end of file +package main + +import "fmt" + +func main() { + var i1 int = MultiPly3Nums(2, 5, 6) + fmt.Printf("Multiply 2 * 5 * 6 = %d\n", i1) + // fmt.Printf("Multiply 2 * 5 * 6 = %d\n", MultiPly3Nums(2, 5, 6)) +} + +func MultiPly3Nums(a int, b int, c int) int { + // var product int = a * b * c + // return product + return a * b * c +} diff --git a/eBook/examples/chapter_6/varnumpar.go b/eBook/examples/chapter_6/varnumpar.go new file mode 100644 index 0000000..2e78470 --- /dev/null +++ b/eBook/examples/chapter_6/varnumpar.go @@ -0,0 +1,28 @@ +package main + +import "fmt" + +func main() { + x := Min(1, 3, 2, 0) + fmt.Printf("The minimum is: %d\n", x) + arr := []int{7,9,3,5,1} + x = Min(arr...) + fmt.Printf("The minimum in the array arr is: %d", x) +} + +func Min(a ...int) int { + if len(a)==0 { + return 0 + } + min := a[0] + for _, v := range a { + if v < min { + min = v + } + } + return min +} +/* +The minimum is: 0 +The minimum in the array arr is: 1 +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_7/array_literals.go b/eBook/examples/chapter_7/array_literals.go index 5b9ad34..63e8997 100644 --- a/eBook/examples/chapter_7/array_literals.go +++ b/eBook/examples/chapter_7/array_literals.go @@ -1,14 +1,24 @@ -package main -import "fmt" - -func main() { - // var arrAge = [5]int{18, 20, 15, 22, 16} - // var arrLazy = [...]int{5, 6, 7, 8, 22} - // var arrLazy = []int{5, 6, 7, 8, 22} - var arrKeyValue = [5]string{3: "Chris", 4: "Ron"} - // var arrKeyValue = []string{3: "Chris", 4: "Ron"} - - for i:=0; i < len(arrKeyValue); i++ { - fmt.Printf("Person at %d is %s\n", i, arrKeyValue[i]) - } -} +package main + +import "fmt" + +func main() { + var arrAge = [5]int{18, 20, 15, 22, 16} + var arrLazy = [...]int{5, 6, 7, 8, 22} + // var arrLazy = []int{5, 6, 7, 8, 22} + var arrKeyValue = [5]string{3: "Chris", 4: "Ron"} + //var arrKeyValue = []string{3: "Chris", 4: "Ron"} + for i := 0; i < len(arrAge); i++ { + fmt.Printf("Age at %d is %d\n", i, arrAge[i]) + } + fmt.Println() + + for i := 0; i < len(arrLazy); i++ { + fmt.Printf("Number at %d is %d\n", i, arrLazy[i]) + } + fmt.Printf("\n") + + for i := 0; i < len(arrKeyValue); i++ { + fmt.Printf("Person at %d is %s\n", i, arrKeyValue[i]) + } +} diff --git a/eBook/examples/chapter_7/array_slices.go b/eBook/examples/chapter_7/array_slices.go index de3ffdc..9b1bf12 100644 --- a/eBook/examples/chapter_7/array_slices.go +++ b/eBook/examples/chapter_7/array_slices.go @@ -1,32 +1,33 @@ -package main -import "fmt" - -func main() { - var arr1 [6]int - var slice1 []int = arr1[2:5] // item at index 5 not included! - - // load the array with integers: 0,1,2,3,4,5 - for i := 0; i < len(arr1); i++ { - arr1[i] = i - } - - // print the slice - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } - - fmt.Printf("The length of arr1 is %d\n", len(arr1)) - fmt.Printf("The length of slice1 is %d\n", len(slice1)) - fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) - -// grow the slice - slice1 = slice1[0:4] - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } - fmt.Printf("The length of slice1 is %d\n", len(slice1)) - fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) - -// grow the slice beyond capacity - //slice1 = slice1[0:7 ] // panic: runtime error: slice bound out of range -} +package main + +import "fmt" + +func main() { + var arr1 [6]int + var slice1 []int = arr1[2:5] // index 5 niet meegerekend! + + // load the array with integers: 0,1,2,3,4,5 + for i := 0; i < len(arr1); i++ { + arr1[i] = i + } + + // print the slice: + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } + + fmt.Printf("The length of arr1 is %d\n", len(arr1)) + fmt.Printf("The length of slice1 is %d\n", len(slice1)) + fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) + + // grow the slice: + slice1 = slice1[0:4] + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } + fmt.Printf("The length of slice1 is %d\n", len(slice1)) + fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) + + // grow the slice beyond capacity: + // slice1 = slice1[0:7 ] // panic: runtime error: slice bounds out of range +} diff --git a/eBook/examples/chapter_7/array_sum.go b/eBook/examples/chapter_7/array_sum.go index a1a3a7f..2f33720 100644 --- a/eBook/examples/chapter_7/array_sum.go +++ b/eBook/examples/chapter_7/array_sum.go @@ -1,16 +1,17 @@ -package main -import "fmt" - -func main() { - array := [3]float64{7.0, 8.5, 9.1} - x := Sum(&array) // Note the explicit address-of operator - // to pass a pointer to the array - fmt.Printf("The sum of the array is: %f", x) -} - -func Sum(a *[3]float64) (sum float64) { - for _, v := range a { // derefencing *a to get back to the array is not necessary! - sum += v - } - return -} +package main + +import "fmt" + +func main() { + array := [3]float64{7.0, 8.5, 9.1} + x := Sum(&array) // Note the explicit address-of operator to pass a pointer to the array + fmt.Printf("The sum of the array is: %f", x) +} + +func Sum(a *[3]float64) (sum float64) { + for _, v := range a { // can also with dereferencing *a to get back to the array + sum += v + } + return +} +// Output: The sum of the array is: 24.600000 diff --git a/eBook/examples/chapter_7/copy_append_slice.go b/eBook/examples/chapter_7/copy_append_slice.go index a20a291..f9cb3b6 100644 --- a/eBook/examples/chapter_7/copy_append_slice.go +++ b/eBook/examples/chapter_7/copy_append_slice.go @@ -1,15 +1,16 @@ -package main -import "fmt" - -func main() { - sl_from := []int{1, 2, 3} - sl_to := make([]int, 10) - - n := copy(sl_to, sl_from) - fmt.Println(sl_to) - fmt.Printf("Copied %d elements\n", n) // n == 3 - - sl3 := []int{1, 2, 3} - sl3 = append(sl3, 4, 5, 6) - fmt.Println(sl3) -} +package main + +import "fmt" + +func main() { + sl_from := []int{1,2,3} + sl_to := make([]int,10) + + n := copy(sl_to, sl_from) + fmt.Println(sl_to) // output: [1 2 3 0 0 0 0 0 0 0] + fmt.Printf("Copied %d elements\n", n) // n == 3 + + sl3 := []int{1,2,3} + sl3 = append(sl3, 4, 5, 6) + fmt.Println(sl3) // output: [1 2 3 4 5 6] +} diff --git a/eBook/examples/chapter_7/for_arrays.go b/eBook/examples/chapter_7/for_arrays.go index f5a6239..f7182aa 100644 --- a/eBook/examples/chapter_7/for_arrays.go +++ b/eBook/examples/chapter_7/for_arrays.go @@ -1,14 +1,16 @@ -package main -import "fmt" - -func main() { - var arr1 [5]int - - for i:=0; i < len(arr1); i++ { - arr1[i] = i * 2 - } - - for i:=0; i < len(arr1); i++ { - fmt.Printf("Array at index %d is %d\n", i, arr1[i]) - } -} +package main + +import "fmt" + +func main() { + var arr1 [5]int + // var arr1 = new([5]int) + + for i:=0; i < len(arr1); i++ { + arr1[i] = i * 2 + } + + for i:=0; i < len(arr1); i++ { + fmt.Printf("Array at index %d is %d\n", i, arr1[i]) + } +} \ No newline at end of file diff --git a/eBook/examples/chapter_7/for_string.go b/eBook/examples/chapter_7/for_string.go new file mode 100644 index 0000000..23cfb7b --- /dev/null +++ b/eBook/examples/chapter_7/for_string.go @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + s := "\u00ff\u754c" + for i, c := range s { + fmt.Printf("%d:%c ", i, c) + } +} +// prints: 0:ÿ 2:界 \ No newline at end of file diff --git a/eBook/examples/chapter_7/make_slice.go b/eBook/examples/chapter_7/make_slice.go index f7d9bf4..321e535 100644 --- a/eBook/examples/chapter_7/make_slice.go +++ b/eBook/examples/chapter_7/make_slice.go @@ -1,17 +1,18 @@ -package main -import "fmt" - -func main() { - var slice1 []int = make([]int, 10) - // load the array/slice: - for i := 0; i < len(slice1); i++ { - slice1[i] = 5 * i - } - - // print the slice: - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } - fmt.Printf("\nThe length of slice1 is %d\n", len(slice1)) - fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) -} +package main + +import "fmt" + +func main() { + // var slice1 []int = make([]int, 10) + slice1 := make([]int, 10) + // load the array/slice: + for i := 0; i < len(slice1); i++ { + slice1[i] = 5 * i + } + // print the slice: + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } + fmt.Printf("\nThe length of slice1 is %d\n", len(slice1)) + fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) +} diff --git a/eBook/examples/chapter_7/multidim_array.go b/eBook/examples/chapter_7/multidim_array.go index c787ec2..b73d732 100644 --- a/eBook/examples/chapter_7/multidim_array.go +++ b/eBook/examples/chapter_7/multidim_array.go @@ -1,16 +1,35 @@ -package main -const ( - WIDTH = 1920 - HEIGHT = 1080 -) - -type pixel int -var screen [WIDTH][HEIGHT]pixel - -func main() { - for y := 0; y < HEIGHT; y++ { - for x := 0; x < WIDTH; x++ { - screen[x][y] = 0 - } - } -} +// multidim_array.go +package main + +import "fmt" + +const ( + WIDTH = 1920 + HEIGHT = 1080 + // WIDTH = 5 + // HEIGHT = 4 +) + +type pixel int +var screen [WIDTH][HEIGHT]pixel + +func main() { + for y := 0; y < HEIGHT; y++ { + for x := 0; x < WIDTH; x++ { + screen[x][y] = 0 + } + } + fmt.Println(screen) + + for row := range screen { + for column := range screen[0] { + screen[row][column] = 1 + } + } + + fmt.Println(screen) +} +/* Output for WIDTH = 5 and HEIGHT = 4: +[[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]] +[[1 1 1 1] [1 1 1 1] [1 1 1 1] [1 1 1 1] [1 1 1 1]] +*/ diff --git a/eBook/examples/chapter_7/pointer_array.go b/eBook/examples/chapter_7/pointer_array.go index 6f5e9a4..2cd1487 100644 --- a/eBook/examples/chapter_7/pointer_array.go +++ b/eBook/examples/chapter_7/pointer_array.go @@ -1,10 +1,12 @@ -package main -import "fmt" -func f(a [3]int) { fmt.Println(a) } -func fp(a *[3]int) { fmt.Println(a) } - -func main() { - var ar [3]int - f(ar) // passes a copy of ar - fp(&ar) // passes a pointer to ar -} +package main + +import "fmt" + +func f(a [3]int) { fmt.Println(a) } +func fp(a *[3]int) { fmt.Println(a) } + +func main() { + var ar [3]int + f(ar) // passes a copy of ar + fp(&ar) // passes a pointer to ar +} diff --git a/eBook/examples/chapter_7/pointer_array2.go b/eBook/examples/chapter_7/pointer_array2.go index 0096720..4816f89 100644 --- a/eBook/examples/chapter_7/pointer_array2.go +++ b/eBook/examples/chapter_7/pointer_array2.go @@ -1,10 +1,11 @@ -package main -import "fmt" - -func fp(a *[3]int) { fmt.Println(a) } - -func main() { - for i := 0; i < 3; i++ { - fp(&[3]int{i, i * i, i * i * i}) - } -} +package main + +import "fmt" + +func fp(a *[3]int) { fmt.Println(a) } + +func main() { + for i := 0; i < 3; i++ { + fp(&[3]int{i, i * i, i * i * i}) + } +} diff --git a/eBook/examples/chapter_7/reslicing.go b/eBook/examples/chapter_7/reslicing.go index 87fe45d..a34a4e0 100644 --- a/eBook/examples/chapter_7/reslicing.go +++ b/eBook/examples/chapter_7/reslicing.go @@ -1,17 +1,18 @@ -package main -import "fmt" - -func main() { - slice1 := make([]int, 0, 10) - // load the slice, cap(slice1) is 10: - for i := 0; i < cap(slice1); i++ { - slice1 = slice1[0:i+1] - slice1[i] = i - fmt.Printf("The length of slice is %d\n", len(slice1)) - } - - // print the slice: - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } -} +package main + +import "fmt" + +func main() { + //var slice1 []int = make([]int, 0, 10) + slice1 := make([]int, 0, 10) + // load the slice, cap(slice1) is 10: + for i := 0; i < cap(slice1); i++ { + slice1 = slice1[0:i+1] // reslice + slice1[i] = i + fmt.Printf("The length of slice is %d\n", len(slice1)) + } + // print the slice: + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } +} diff --git a/eBook/examples/chapter_7/slices_forrange.go b/eBook/examples/chapter_7/slices_forrange.go index 772a663..6ffb374 100644 --- a/eBook/examples/chapter_7/slices_forrange.go +++ b/eBook/examples/chapter_7/slices_forrange.go @@ -1,15 +1,22 @@ -package main -import "fmt" - -func main() { - slice1 := make([]int, 4) - - slice1[0] = 1 - slice1[0] = 2 - slice1[0] = 3 - slice1[0] = 4 - - for ix, value := range slice1 { - fmt.Printf("Slice at %d is: %d\n", ix, value) - } -} +package main + +import "fmt" + +func main() { + var slice1 []int = make([]int, 4) + + slice1[0] = 1 + slice1[1] = 2 + slice1[2] = 3 + slice1[3] = 4 + + for ix, value := range slice1 { + fmt.Printf("Slice at %d is: %d\n", ix, value) + } +} +/* +Slice at 0 is: 1 +Slice at 1 is: 2 +Slice at 2 is: 3 +Slice at 3 is: 4 +*/ diff --git a/eBook/examples/chapter_7/slices_forrange2.go b/eBook/examples/chapter_7/slices_forrange2.go index e68a121..365573e 100644 --- a/eBook/examples/chapter_7/slices_forrange2.go +++ b/eBook/examples/chapter_7/slices_forrange2.go @@ -1,14 +1,31 @@ -package main -import "fmt" - -func main() { - seasons := []string{"Spring", "Summer", "Autumn", "Winter"} - for ix, season := range seasons { - fmt.Printf("Season %d is: %s\n", ix, season) - } - - var season string - for _, season = range seasons { - fmt.Printf("%s\n", season) - } -} +package main + +import "fmt" + +func main() { + seasons := []string{"Spring","Summer","Autumn","Winter"} + + for ix, season := range seasons { + fmt.Printf("Season %d is: %s\n", ix, season) + } + + var season string + for _, season = range seasons { + fmt.Printf("%s\n", season) + } + + for ix := range seasons { + fmt.Printf("%d ", ix) + } +} +/* Output: +Season 0 is: Spring +Season 1 is: Summer +Season 2 is: Autumn +Season 3 is: Winter +Spring +Summer +Autumn +Winter +0 1 2 3 +*/ diff --git a/eBook/examples/chapter_8/Makefile.txt b/eBook/examples/chapter_8/Makefile.txt new file mode 100644 index 0000000..ecfff55 --- /dev/null +++ b/eBook/examples/chapter_8/Makefile.txt @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc +TARG=pack1 +GOFILES=\ + pack1.go\ + pack1b.go\ + +include $(GOROOT)/src/Make.pkg diff --git a/eBook/examples/chapter_8/invert_map.go b/eBook/examples/chapter_8/invert_map.go index 69007e0..12eab02 100644 --- a/eBook/examples/chapter_8/invert_map.go +++ b/eBook/examples/chapter_8/invert_map.go @@ -1,23 +1,29 @@ -package main -import ( - "fmt" -) - -var ( - barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, - "delta": 87, "echo": 56, "foxtrot": 12, - "golf": 34, "hotel": 16, "indio": 87, - "juliet": 65, "kili": 43, "lima": 98} -) - -func main() { - invMap := make(map[int]string, len(barVal)) - for k, v := range barVal { - invMap[v] = k - } - fmt.Println("inverted:") - for k, v := range invMap { - fmt.Printf("Key: %v, Value: %v / ", k, v) - } - fmt.Println() -} +// invert_map.go +package main + +import ( + "fmt" +) + +var ( + barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, "delta": 87, + "echo": 56, "foxtrot": 12, "golf": 34, "hotel": 16, "indio": 87, "juliet": 65, "kilo": 43, "lima": 98} +) + +func main() { + invMap := make(map[int]string, len(barVal)) + for k, v := range barVal { + invMap[v] = k + } + fmt.Println("inverted:") + for k, v := range invMap { + fmt.Printf("Key: %v, Value: %v / ", k, v) + } +} +/* Output: +inverted: +Key: 12, Value: foxtrot / Key: 16, Value: hotel / Key: 87, Value: delta / Key: 23, Value: charlie / +Key: 65, Value: juliet / Key: 43, Value: kilo / Key: 56, Value: bravo / Key: 98, Value: lima / +Key: 34, Value: golf / +*/ + diff --git a/eBook/examples/chapter_8/make_maps.go b/eBook/examples/chapter_8/make_maps.go index 70de8a1..f5eec5e 100644 --- a/eBook/examples/chapter_8/make_maps.go +++ b/eBook/examples/chapter_8/make_maps.go @@ -1,21 +1,28 @@ package main + import "fmt" func main() { - var mapLit map[string]int - //var mapCreated map[string]float32 - var mapAssigned map[string]int + var mapLit map[string]int + //var mapCreated map[string]float32 + var mapAssigned map[string]int - mapLit = map[string]int{"one": 1, "two": 2} - mapCreated := make(map[string]float32) - mapAssigned = mapLit + mapLit = map[string]int{"one": 1, "two": 2} + mapCreated := make(map[string]float32) + mapAssigned = mapLit - mapCreated["key1"] = 4.5 - mapCreated["key2"] = 3.14159 - mapAssigned["two"] = 3 + mapCreated["key1"] = 4.5 + mapCreated["key2"] = 3.14159 + mapAssigned["two"] = 3 - fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"]) - fmt.Printf("Map created at \"key2\" is: %f\n", mapCreated["key2"]) - fmt.Printf("Map assigned at \"two\" is: %d\n", mapLit["two"]) - fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"]) + fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"]) + fmt.Printf("Map created at \"key2\" is: %f\n", mapCreated["key2"]) + fmt.Printf("Map assigned at \"two\" is: %d\n", mapLit["two"]) + fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"]) } +/* Output: +Map literal at "one" is: 1 +Map created at "key2" is: 3.141590 +Map assigned at "two" is: 3 +Map literal at "ten" is: 0 +*/ diff --git a/eBook/examples/chapter_8/map_func.go b/eBook/examples/chapter_8/map_func.go index 954975c..c1fe4a2 100644 --- a/eBook/examples/chapter_8/map_func.go +++ b/eBook/examples/chapter_8/map_func.go @@ -1,11 +1,13 @@ -package main -import "fmt" - -func main() { - mf := map[int]func() int{ - 1: func() int { return 10 }, - 2: func() int { return 20 }, - 5: func() int { return 50 }, - } - fmt.Println(mf) -} +// map_func.go +package main +import "fmt" + +func main() { + mf := map[int]func() int{ + 1: func() int { return 10 }, + 2: func() int { return 20 }, + 5: func() int { return 50 }, + } + fmt.Println(mf) +} +// Output: map[1:0x10903be0 5:0x10903ba0 2:0x10903bc0] diff --git a/eBook/examples/chapter_8/map_testelement.go b/eBook/examples/chapter_8/map_testelement.go index 88449b0..35ff35b 100644 --- a/eBook/examples/chapter_8/map_testelement.go +++ b/eBook/examples/chapter_8/map_testelement.go @@ -1,31 +1,33 @@ -package main -import "fmt" - -func main() { - var value int - var isPresent bool - - map1 := make(map[string]int) - map1["New Delhi"] = 55 - map1["Beijing"] = 20 - map1["Washington"] = 25 - value, isPresent = map1["Beijing"] - if isPresent { - fmt.Printf("The value of \"Beijin\" in map1 is: %d\n", value) - } else { - fmt.Printf("map1 does not contain Beijing") - } - - value, isPresent = map1["Paris"] - fmt.Printf("Is \"Paris\" in map1 ?: %t\n", isPresent) - fmt.Printf("Value is: %d\n", value) - - // delete an item: - delete(map1, "Washington") - value, isPresent = map1["Washington"] - if isPresent { - fmt.Printf("The value of \"Washington\" in map1 is: %d\n", value) - } else { - fmt.Println("map1 does not contain Washington") - } -} +package main + +import "fmt" + +func main() { + var value int + var isPresent bool + + map1 := make(map[string]int) + map1["New Delhi"] = 55 + map1["Bejing"] = 20 + map1["Washington"] = 25 + + value, isPresent = map1["Bejing"] + if isPresent { + fmt.Printf("The value of \"Bejing\" in map1 is: %d\n", value) + } else { + fmt.Println("map1 does not contain Bejing") + } + + value, isPresent = map1["Paris"] + fmt.Printf("Is \"Paris\" in map1 ?: %t\n", isPresent) + fmt.Printf("Value is: %d\n", value) + + // delete an item: + delete(map1, "Washington") + value, isPresent = map1["Washington"] + if isPresent { + fmt.Printf("The value of \"Washington\" in map1 is: %d\n", value) + } else { + fmt.Println("map1 does not contain Washington") + } +} diff --git a/eBook/examples/chapter_8/maps_forrange.go b/eBook/examples/chapter_8/maps_forrange.go index 309d0fa..8a2b84e 100644 --- a/eBook/examples/chapter_8/maps_forrange.go +++ b/eBook/examples/chapter_8/maps_forrange.go @@ -1,13 +1,15 @@ -package main -import "fmt" - -func main() { - map1 := make(map[int]float32) - map1[1] = 1.0 - map1[2] = 2.0 - map1[3] = 3.0 - map1[4] = 4.0 - for key, value := range map1 { - fmt.Printf("key is: %d - value is: %f\n", key, value) - } -} +package main + +import "fmt" + +func main() { + map1 := make(map[int]float32) + map1[1] = 1.0 + map1[2] = 2.0 + map1[3] = 3.0 + map1[4] = 4.0 + + for key, value := range map1 { + fmt.Printf("key is: %d - value is: %f\n", key, value) + } +} diff --git a/eBook/examples/chapter_8/slice_maps.go b/eBook/examples/chapter_8/slice_maps.go index 203b72a..ccc17e8 100644 --- a/eBook/examples/chapter_8/slice_maps.go +++ b/eBook/examples/chapter_8/slice_maps.go @@ -1,20 +1,27 @@ -package main -import "fmt" - -func main() { - // Version A: - items := make([]map[int]int, 5) - for i:= range items { - items[i] = make(map[int]int, 1) - items[i][1] = 2 - } - fmt.Printf("Version A: Value of items: %v\n", items) - - // Version B: NOT GOOD! - items2 := make([]map[int]int, 5) - for _, item := range items2 { - item = make(map[int]int, 1) // item is only a copy of the slice element. - item[1] = 2 // This 'item' will be lost on the next iteration. - } - fmt.Printf("Version B: Value of items: %v\n", items2) -} +// slice_maps.go +package main + +import ( + "fmt" +) + +func main() { +// Version A: + items := make([]map[int]int, 5) + for i := range items { + items[i] = make(map[int]int, 1) + items[i][1] = 2 + } + fmt.Printf("Version A: Value of items: %v\n", items) +// Version B: + items2 := make([]map[int]int, 5) + for _, item := range items2 { + item = make(map[int]int, 1) // item is only a copy of the slice element. + item[1] = 2 // This 'item' will be lost on the next iteration. + } + fmt.Printf("Version B: Value of items: %v\n", items2) +} +/* Output: +Version A: Value of items: [map[1:2] map[1:2] map[1:2] map[1:2] map[1:2]] +Version B: Value of items: [map[] map[] map[] map[] map[]] +*/ diff --git a/eBook/examples/chapter_8/sort_map.go b/eBook/examples/chapter_8/sort_map.go index db34f23..976c5a8 100644 --- a/eBook/examples/chapter_8/sort_map.go +++ b/eBook/examples/chapter_8/sort_map.go @@ -1,32 +1,43 @@ -// the telephone alphabet: -package main -import ( - "fmt" - "sort" -) - -var ( - barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, - "delta": 87, "echo": 56, "foxtrot": 12, - "golf": 34, "hotel": 16, "indio": 87, - "juliet": 65, "kili": 43, "lima": 98} -) - -func main() { - fmt.Println("unsorted:") - for k, v := range barVal { - fmt.Printf("Key: %v, Value: %v / ", k, v) - } - keys := make([]string, len(barVal)) - i := 0 - for k, _ := range barVal { - keys[i] = k - i++ - } - sort.Strings(keys) - fmt.Println() - fmt.Println("sorted:") - for _, k := range keys { - fmt.Printf("Key: %v, Value: %v / ", k, barVal[k]) - } -} +// sort_map.go +// the telephone alphabet: +package main + +import ( + "fmt" + "sort" +) + +var ( + barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, "delta": 87, + "echo": 56, "foxtrot": 12, "golf": 34, "hotel": 16, "indio": 87, "juliet": 65, "kilo": 43, "lima": 98} +) + +func main() { + fmt.Println("unsorted:") + for k, v := range barVal { + fmt.Printf("Key: %v, Value: %v / ", k, v) + } + keys := make([]string, len(barVal)) + i := 0 + for k, _ := range barVal { + keys[i] = k + i++ + } + sort.Strings(keys) + fmt.Println() + fmt.Println("sorted:") + for _, k := range keys { + fmt.Printf("Key: %v, Value: %v / ", k, barVal[k]) + } +} +/* Output: +unsorted: +Key: indio, Value: 87 / Key: echo, Value: 56 / Key: juliet, Value: 65 / Key: charlie, Value: 23 / +Key: hotel, Value: 16 / Key: lima, Value: 98 / Key: bravo, Value: 56 / Key: alpha, Value: 34 / +Key: kilo, Value: 43 / Key: delta, Value: 87 / Key: golf, Value: 34 / Key: foxtrot, Value: 12 / +sorted: +Key: alpha, Value: 34 / Key: bravo, Value: 56 / Key: charlie, Value: 23 / Key: delta, Value: 87 / +Key: echo, Value: 56 / Key: foxtrot, Value: 12 / Key: golf, Value: 34 / Key: hotel, Value: 16 / +Key: indio, Value: 87 / Key: juliet, Value: 65 / Key: kilo, Value: 43 / Key: lima, Value: 98 / +*/ + diff --git a/eBook/examples/chapter_9/big.go b/eBook/examples/chapter_9/big.go new file mode 100644 index 0000000..22bc559 --- /dev/null +++ b/eBook/examples/chapter_9/big.go @@ -0,0 +1,30 @@ +// big.go +package main + +import ( + "math" + "math/big" + "fmt" +) + +func main() { +// Here are some calculations with bigInts: + im := big.NewInt(math.MaxInt64) + in := im + io := big.NewInt(1956) + ip := big.NewInt(1) + ip.Mul(im, in).Add(ip, im).Div(ip, io) + fmt.Printf("Big Int: %v\n", ip) +// Here are some calculations with bigInts: + rm := big.NewRat(math.MaxInt64, 1956) + rn := big.NewRat(-1956, math.MaxInt64) + ro := big.NewRat(19, 56) + rp := big.NewRat(1111, 2222) + rq := big.NewRat(1, 1) + rq.Mul(rm, rn).Add(rq, ro).Mul(rq, rp) + fmt.Printf("Big Rat: %v\n", rq) +} +/* Output: +Big Int: 43492122561469640008497075573153004 +Big Rat: -37/112 +*/ diff --git a/eBook/examples/chapter_9/book/book_main/main.go b/eBook/examples/chapter_9/book/book_main/main.go new file mode 100644 index 0000000..503bc2d --- /dev/null +++ b/eBook/examples/chapter_9/book/book_main/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "book/pack1" +) + +func main() { + var test1 string + test1 = pack1.ReturnStr() + fmt.Printf("ReturnStr from package1: %s\n", test1) + fmt.Printf("Integer from package1: %d\n", pack1.Pack1Int) + //fmt.Printf("Float from package1: %f\n", pack1.pack1Float) +} diff --git a/eBook/examples/chapter_9/book/pack1/pack1.go b/eBook/examples/chapter_9/book/pack1/pack1.go new file mode 100644 index 0000000..c4036ac --- /dev/null +++ b/eBook/examples/chapter_9/book/pack1/pack1.go @@ -0,0 +1,8 @@ +package pack1 + +var Pack1Int int = 42 +var pack1Float = 3.14 + +func ReturnStr() string { + return "Hello main!" +} \ No newline at end of file diff --git a/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html new file mode 100644 index 0000000..31455a5 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html @@ -0,0 +1,152 @@ + + + + Package sort - The Go Programming Language + + + + + +
+
+

The Go Programming Language

+ + +
+
+ + +

Package sort

+ + + + + + + + +

import "doc_example"

+

+Sorting using a general interface: +

+ +

+

Package files

+ + sort.go + +

+

func Float64sAreSorted

+

func Float64sAreSorted(a []float64) bool

+ +

func IntsAreSorted

+

func IntsAreSorted(a []int) bool

+ +

func IsSorted

+

func IsSorted(data Interface) bool

+

+Test if data is sorted +

+ +

func Sort

+

func Sort(data Interface)

+

+General sort function +

+ +

func SortFloat64s

+

func SortFloat64s(a []float64)

+ +

func SortInts

+

func SortInts(a []int)

+

+Convenience wrappers for common cases +

+ +

func SortStrings

+

func SortStrings(a []string)

+ +

func StringsAreSorted

+

func StringsAreSorted(a []string) bool

+ +

type Float64Array

+ +

type Float64Array []float64

+

func (Float64Array) Len

+

func (p Float64Array) Len() int

+ +

func (Float64Array) Less

+

func (p Float64Array) Less(i, j int) bool

+ +

func (Float64Array) Swap

+

func (p Float64Array) Swap(i, j int)

+ +

type IntArray

+

+Convenience types for common cases: IntArray +

+ +

type IntArray []int

+

func (IntArray) Len

+

func (p IntArray) Len() int

+ +

func (IntArray) Less

+

func (p IntArray) Less(i, j int) bool

+ +

func (IntArray) Swap

+

func (p IntArray) Swap(i, j int)

+ +

type Interface

+

+Sorting interface +

+ +

type Interface interface {
+    Len() int
+    Less(i, j int) bool
+    Swap(i, j int)
+}

+

type StringArray

+ +

type StringArray []string

+

func (StringArray) Len

+

func (p StringArray) Len() int

+ +

func (StringArray) Less

+

func (p StringArray) Less(i, j int) bool

+ +

func (StringArray) Swap

+

func (p StringArray) Swap(i, j int)

+ +

Other packages

+

+ main
+

+ +
+
+

Build version release.r58 8731. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.

+
+
+ + + \ No newline at end of file diff --git a/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css new file mode 100644 index 0000000..a985d8f --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css @@ -0,0 +1,205 @@ +/* General Styles */ +body { + font-family: "Bitstream Vera Sans", Verdana, sans-serif; + font-size: 81.25%; + line-height: 1.23em; + padding: 0; + margin: 1.23em; + background: white; + color: black; +} +a { + color: #04a; + text-decoration: none; +} +a:visited { + color: #04a; +} +a:hover { + color: #a40; + text-decoration: underline; +} +a:active { + color: #c00; +} +code, pre { + font-size: 1.2em; +} +pre { + background: #F0F0F0; + padding: 0.5em 1em; +} + +/* Top bar */ +#container { + width: 100%; + margin: auto; +} +#topnav { + height: 55px; + background: url(/doc/logo.png) no-repeat top left; +} +a#logo-box { + display: block; + height: 55px; +} +h1#title { + display: none; +} +#nav-main { + float: right; + width: 500px; + margin-top: -5px; + text-align: center; +} +#nav-main ul { + padding-left: 0; + margin-left: 0; + margin-bottom: 0.5em; +} +#nav-main li a { + display: inline; + display: inline-block; + padding: .46em .62em .38em .62em; +} +#nav-main li a:link, +#nav-main li a:visited { + color: #000; +} +#nav-main li { + display: inline; + display: inline-block; + background: #e6e6e6 url(/doc/button_background.png) repeat-x; + border: solid 1px #999; + margin-left: -1px; + text-shadow: #fff 0 1px 0; + box-shadow: 0 1px 1px #ccc; + -moz-box-shadow: 0 1px 1px #ccc; + -webkit-box-shadow: 0 1px 1px #ccc; +} +#nav-main li:first-child { + -moz-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} +#nav-main li:last-child { + -moz-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} +#nav-main .quickref { + color: #444; +} +#nav-main .quickref .sep { + color: #999; +} +#search { + width: 120px; + margin-left: 0.5em; +} +#search.inactive { + text-align: center; + color: #444; +} + +/* Footer */ +#site-info { + position: relative; + text-align: center; +} +#site-info, #site-info a:link, #site-info a:visited { + color: #aaa; +} + +/* Content */ +#content { + clear: both; + padding: 0; + position: relative; + margin-top: 1.5em; + margin-bottom: 1.5em; + border-top: solid 1px #aaa; + border-bottom: solid 1px #aaa; +} +.left-column { + width: 49%; + float: left; +} +.right-column { + width: 49%; + float: right; +} +.end-columns { + clear: both; +} +#content h1 { + margin-bottom: -0em; + padding: 0; +} +#content h2 { + border-top: 2px solid #ddd; + padding: 8px 0; + margin: 1.5em 0 0; +} +#content .subtitle { + margin-top: 1em; + display: block; +} +.navtop a { + font-weight: normal; font-size: 7pt; + float: right; color: #999; +} + +/* Content and Code Highlighting */ +pre.ebnf, pre.grammar { + background: #FFFFE0; +} +span.ln { + font-size: 80%; + color: #777777; +} +span.comment { + color: #002090; +} +span.highlight { + background: #FF9900; + font-weight: bold; +} +span.highlight-comment { + background: #FF9900; + font-weight: bold; + color: #002090; +} +span.selection { + background: #FFFF00 +} +span.selection-comment { + color: #002090; + background: #FFFF00 +} +span.selection-highlight { + background: #FF9900; + font-weight: bold; +} +span.selection-highlight-comment { + background: #FF9900; + font-weight: bold; + color: #002090; +} +span.alert { + color: #D00000; +} +#nav table { + width: 100%; +} +.detail { + padding: 0.25em 1em; + background: #F4F4F4; +} +sup.new { + color: red; + font-size: 8px; + line-height: 0; +} diff --git a/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js new file mode 100644 index 0000000..946c4c3 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js @@ -0,0 +1,190 @@ +// Except as noted, this content is licensed under Creative Commons +// Attribution 3.0 + +/* A little code to ease navigation of these documents. + * + * On window load we: + * + Generate a table of contents (godocs_generateTOC) + * + Add links up to the top of the doc from each section (godocs_addTopLinks) + */ + +/* We want to do some stuff on page load (after the HTML is rendered). + So listen for that: + */ +function bindEvent(el, e, fn) { + if (el.addEventListener){ + el.addEventListener(e, fn, false); + } else if (el.attachEvent){ + el.attachEvent('on'+e, fn); + } +} +bindEvent(window, 'load', godocs_onload); + +function godocs_onload() { + godocs_bindSearchEvents(); + godocs_generateTOC(); + godocs_addTopLinks(); +} + +function godocs_bindSearchEvents() { + var search = document.getElementById('search'); + if (!search) { + // no search box (index disabled) + return; + } + function clearInactive() { + if (search.className == "inactive") { + search.value = ""; + search.className = ""; + } + } + function restoreInactive() { + if (search.value != "") { + return; + } + if (search.type != "search") { + search.value = search.getAttribute("placeholder"); + } + search.className = "inactive"; + } + restoreInactive(); + bindEvent(search, 'focus', clearInactive); + bindEvent(search, 'blur', restoreInactive); +} + +/* Generates a table of contents: looks for h2 and h3 elements and generates + * links. "Decorates" the element with id=="nav" with this table of contents. + */ +function godocs_generateTOC() { + var navbar = document.getElementById('nav'); + if (!navbar) { return; } + + var toc_items = []; + + var i; + for (i = 0; i < navbar.parentNode.childNodes.length; i++) { + var node = navbar.parentNode.childNodes[i]; + if ((node.tagName == 'h2') || (node.tagName == 'H2')) { + if (!node.id) { + node.id = 'tmp_' + i; + } + var text = godocs_nodeToText(node); + if (!text) { continue; } + + var textNode = document.createTextNode(text); + + var link = document.createElement('a'); + link.href = '#' + node.id; + link.appendChild(textNode); + + // Then create the item itself + var item = document.createElement('dt'); + + item.appendChild(link); + toc_items.push(item); + } + if ((node.tagName == 'h3') || (node.tagName == 'H3')) { + if (!node.id) { + node.id = 'tmp_' + i; + } + var text = godocs_nodeToText(node); + if (!text) { continue; } + + var textNode = document.createTextNode(text); + + var link = document.createElement('a'); + link.href = '#' + node.id; + link.appendChild(textNode); + + // Then create the item itself + var item = document.createElement('dd'); + + item.appendChild(link); + toc_items.push(item); + } + } + + if (toc_items.length <= 1) { return; } + + var dl1 = document.createElement('dl'); + var dl2 = document.createElement('dl'); + + var split_index = (toc_items.length / 2) + 1; + if (split_index < 8) { + split_index = toc_items.length; + } + + for (i = 0; i < split_index; i++) { + dl1.appendChild(toc_items[i]); + } + for (/* keep using i */; i < toc_items.length; i++) { + dl2.appendChild(toc_items[i]); + } + + var tocTable = document.createElement('table'); + navbar.appendChild(tocTable); + tocTable.className = 'unruled'; + var tocBody = document.createElement('tbody'); + tocTable.appendChild(tocBody); + + var tocRow = document.createElement('tr'); + tocBody.appendChild(tocRow); + + // 1st column + var tocCell = document.createElement('td'); + tocCell.className = 'first'; + tocRow.appendChild(tocCell); + tocCell.appendChild(dl1); + + // 2nd column + tocCell = document.createElement('td'); + tocRow.appendChild(tocCell); + tocCell.appendChild(dl2); +} + +/* Returns the "This sweet header" from

This sweet header

. + * Takes a node, returns a string. + */ +function godocs_nodeToText(node) { + var TEXT_NODE = 3; // Defined in Mozilla but not MSIE :( + + var text = ''; + for (var j = 0; j != node.childNodes.length; j++) { + var child = node.childNodes[j]; + if (child.nodeType == TEXT_NODE) { + if (child.nodeValue != '[Top]') { //ok, that's a hack, but it works. + text = text + child.nodeValue; + } + } else { + text = text + godocs_nodeToText(child); + } + } + return text; +} + +/* For each H2 heading, add a link up to the #top of the document. + * (As part of this: ensure existence of 'top' named anchor link + * (theoretically at doc's top).) + */ +function godocs_addTopLinks() { + /* Make sure there's a "top" to link to. */ + var top = document.getElementById('top'); + if (!top) { + document.body.id = 'top'; + } + + if (!document.getElementsByTagName) return; // no browser support + + var headers = document.getElementsByTagName('h2'); + + for (var i = 0; i < headers.length; i++) { + var span = document.createElement('span'); + span.className = 'navtop'; + var link = document.createElement('a'); + span.appendChild(link); + link.href = '#top'; + var textNode = document.createTextNode('[Top]'); + link.appendChild(textNode); + headers[i].appendChild(span); + } +} diff --git a/eBook/examples/chapter_9/doc_example/sort.go b/eBook/examples/chapter_9/doc_example/sort.go new file mode 100644 index 0000000..bced106 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/sort.go @@ -0,0 +1,59 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Sorting using a general interface +package sort + +// Sorting interface +type Interface interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +// General sort function +func Sort(data Interface) { + for i := 1; i < data.Len(); i++ { + for j := i; j > 0 && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Test if data is sorted +func IsSorted(data Interface) bool { + n := data.Len() + for i := n - 1; i > 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +// Convenience types for common cases: IntArray +type IntArray []int + +func (p IntArray) Len() int { return len(p) } +func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } +func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type Float64Array []float64 +func (p Float64Array) Len() int { return len(p) } +func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] } +func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type StringArray []string +func (p StringArray) Len() int { return len(p) } +func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } +func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Convenience wrappers for common cases +func SortInts(a []int) { Sort(IntArray(a)) } +func SortFloat64s(a []float64) { Sort(Float64Array(a)) } +func SortStrings(a []string) { Sort(StringArray(a)) } + +func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } +func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Array(a)) } +func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } \ No newline at end of file diff --git a/eBook/examples/chapter_9/doc_example/sortmain.go b/eBook/examples/chapter_9/doc_example/sortmain.go new file mode 100644 index 0000000..da63508 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/sortmain.go @@ -0,0 +1,82 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package gives an example of how to use a custom package with interfaces +package main + +import ( + "fmt" + "./sort" +) + +// sorting of slice of integers +func ints() { + data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} + a := sort.IntArray(data) //conversion to type IntArray + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// sorting of slice of strings +func strings() { + data := []string{"monday", "friday", "tuesday", "wednesday", "sunday","thursday", "", "saturday"} + a := sort.StringArray(data) + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// a type which describes a day of the week +type day struct { + num int + shortName string + longName string +} + +type dayArray struct { + data []*day +} + +func (p *dayArray) Len() int { return len(p.data) } +func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num } +func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] } + +// sorting of custom type day +func days() { + Sunday := day{0, "SUN", "Sunday"} + Monday := day{1, "MON", "Monday"} + Tuesday := day{2, "TUE", "Tuesday"} + Wednesday := day{3, "WED", "Wednesday"} + Thursday := day{4, "THU", "Thursday"} + Friday := day{5, "FRI", "Friday"} + Saturday := day{6, "SAT", "Saturday"} + data := []*day{&Tuesday, &Thursday, &Wednesday, &Sunday, &Monday, &Friday, &Saturday} + a := dayArray{data} + sort.Sort(&a) + if !sort.IsSorted(&a) { + panic("fail") + } + for _, d := range data { + fmt.Printf("%s ", d.longName) + } + fmt.Printf("\n") +} + + +func main() { + ints() + strings() + days() +} + +/* Output: +The sorted array is: [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845] +The sorted array is: [ friday monday saturday sunday thursday tuesday wednesday] +Sunday Monday Tuesday Wednesday Thursday Friday Saturday +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_9/pattern.go b/eBook/examples/chapter_9/pattern.go new file mode 100644 index 0000000..a232392 --- /dev/null +++ b/eBook/examples/chapter_9/pattern.go @@ -0,0 +1,35 @@ +// pattern.go +package main + +import ( + "fmt" + "regexp" + "strconv" +) + +func main() { + searchIn := "John: 2578.34 William: 4567.23 Steve: 5632.18" // string to search + pat := "[0-9]+.[0-9]+" // pattern search for in searchIn + + f := func (s string) string { + v, _ := strconv.ParseFloat(s, 32) + return strconv.FormatFloat(v * 2, 'f', 2, 32) + } + + if ok, _ := regexp.Match(pat, []byte(searchIn)); ok { + fmt.Println("Match found!") + } + + re, _ := regexp.Compile(pat) + str := re.ReplaceAllString(searchIn, "##.#") // replace pat with "##.#" + fmt.Println(str) + // using a function : + str2 := re.ReplaceAllStringFunc(searchIn, f) + fmt.Println(str2) + +} +/* Output: +Match found! +John: ##.# William: ##.# Steve: ##.# +John: 5156.68 William: 9134.46 Steve: 11264.36 +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_9/reboot.go b/eBook/examples/chapter_9/reboot.go new file mode 100644 index 0000000..7250e06 --- /dev/null +++ b/eBook/examples/chapter_9/reboot.go @@ -0,0 +1,21 @@ +// reboot.go +// compile errors (Windows): +//undefined: syscall.SYS_REBOOT +// reboot.go:13: not enough arguments in call to syscall.Syscall +// Linux: compileert, uitvoeren met sudo ./6.out --> systeem herstart +package main + +import ( + "syscall" +) + +const LINUX_REBOOT_MAGIC1 uintptr = 0xfee1dead +const LINUX_REBOOT_MAGIC2 uintptr = 672274793 +const LINUX_REBOOT_CMD_RESTART uintptr = 0x1234567 + +func main() { + syscall.Syscall(syscall.SYS_REBOOT, + LINUX_REBOOT_MAGIC1, + LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART) +} diff --git a/eBook/examples/chapter_9/uppercase/uc/uc.go b/eBook/examples/chapter_9/uppercase/uc/uc.go new file mode 100644 index 0000000..221c5ab --- /dev/null +++ b/eBook/examples/chapter_9/uppercase/uc/uc.go @@ -0,0 +1,8 @@ +// uc.go +package uc + +import "strings" + +func UpperCase(str string) string { + return strings.ToUpper(str) +} diff --git a/eBook/examples/chapter_9/uppercase/uc/uc_test.go b/eBook/examples/chapter_9/uppercase/uc/uc_test.go new file mode 100644 index 0000000..3d01c71 --- /dev/null +++ b/eBook/examples/chapter_9/uppercase/uc/uc_test.go @@ -0,0 +1,23 @@ +// uc_test.go +package uc + +import "testing" + +type ucTest struct { + in, out string +} + +var ucTests = []ucTest { + ucTest{"abc", "ABC"}, + ucTest{"cvo-az", "CVO-AZ"}, + ucTest{"Antwerp", "ANTWERP"}, +} + +func TestUC(t *testing.T) { + for _, ut := range ucTests { + uc := UpperCase(ut.in) + if uc != ut.out { + t.Errorf("UpperCase(%s) = %s, must be %s.", ut.in, uc, ut.out) + } + } +} diff --git a/eBook/examples/chapter_9/uppercase/uc_main/ucmain.go b/eBook/examples/chapter_9/uppercase/uc_main/ucmain.go new file mode 100644 index 0000000..a415f2f --- /dev/null +++ b/eBook/examples/chapter_9/uppercase/uc_main/ucmain.go @@ -0,0 +1,12 @@ +// main.go +package main + +import ( + "fmt" + "uppercase/uc" +) + +func main() { + str1 := "USING package uc!" + fmt.Println(uc.UpperCase(str1)) +} diff --git a/eBook/examples/chapter_9/use_urlshortener.go b/eBook/examples/chapter_9/use_urlshortener.go new file mode 100644 index 0000000..eede5e1 --- /dev/null +++ b/eBook/examples/chapter_9/use_urlshortener.go @@ -0,0 +1,55 @@ +// use_urlshortener.go +package main + +import ( + "fmt" + "net/http" + "text/template" + urlshortener "code.google.com/p/google-api-go-client/urlshortener/v1" +) + +func main() { + http.HandleFunc("/", root) + http.HandleFunc("/short", short) + http.HandleFunc("/long", long) + http.ListenAndServe("localhost:8080", nil) +} + +// the template used to show the forms and the results web page to the user +var rootHtmlTmpl = template.Must(template.New("rootHtml").Parse(` + +

URL SHORTENER

+{{if .}}{{.}}

{{end}} +
+Shorten this: + +
+
+
+Expand this: http://goo.gl/ + +
+ +`)) + +func root(w http.ResponseWriter, r *http.Request) { + rootHtmlTmpl.Execute(w, nil) +} + +func short(w http.ResponseWriter, r *http.Request) { + longUrl := r.FormValue("longUrl") + urlshortenerSvc, _ := urlshortener.New(http.DefaultClient) + url, _ := urlshortenerSvc.Url.Insert(&urlshortener.Url{LongUrl: longUrl,}).Do() + rootHtmlTmpl.Execute(w, fmt.Sprintf("Shortened version of %s is : %s", longUrl, url.Id)) +} + +func long(w http.ResponseWriter, r *http.Request) { + shortUrl := "http://goo.gl/" + r.FormValue("shortUrl") + urlshortenerSvc, _ := urlshortener.New(http.DefaultClient) + url, err := urlshortenerSvc.Url.Get(shortUrl).Do() + if err != nil { + fmt.Println("error: %v", err) + return + } + rootHtmlTmpl.Execute(w, fmt.Sprintf("Longer version of %s is : %s", shortUrl, url.LongUrl)) +} \ No newline at end of file diff --git a/eBook/exercises/chapter_10/anonymous_struct.go b/eBook/exercises/chapter_10/anonymous_struct.go new file mode 100755 index 0000000..57f281c --- /dev/null +++ b/eBook/exercises/chapter_10/anonymous_struct.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +type C struct { +x float32; +int; +string; +} + +func main() { + c := C{3.14, 7, "hello"} + fmt.Println(c.x, c.int, c.string) // output: 3.14 7 hello + fmt.Println(c) // output: {3.14 7 hello} +} \ No newline at end of file diff --git a/eBook/exercises/chapter_10/celsius.go b/eBook/exercises/chapter_10/celsius.go new file mode 100755 index 0000000..64ae03c --- /dev/null +++ b/eBook/exercises/chapter_10/celsius.go @@ -0,0 +1,19 @@ +// celsius.go +package main + +import ( + "fmt" + "strconv" +) + +type Celsius float64 + +func (c Celsius) String() string { + return "The temperature is: " + strconv.FormatFloat(float64(c),'f', 1, 32) + " °C" +} + +func main() { + var c Celsius = 18.36 + fmt.Println(c) +} +// The temperature is: 18.4 °C diff --git a/eBook/exercises/chapter_10/days.go b/eBook/exercises/chapter_10/days.go new file mode 100755 index 0000000..8b606fc --- /dev/null +++ b/eBook/exercises/chapter_10/days.go @@ -0,0 +1,36 @@ +package main + +import "fmt" + +type Day int + +const ( + MO Day = iota + TU + WE + TH + FR + SA + SU +) + +var dayName = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"} + +func (day Day) String() string { + return dayName[day] +} + +func main() { + var th Day = 3 + fmt.Printf("The 3rd day is: %s\n", th) + // If index > 6: panic: runtime error: index out of range + // but use the enumerated type to work with valid values: + var day = SU; + fmt.Println(day); // prints Sunday + fmt.Println(0, MO, 1, TU) +} +/* Output: +The 3rd day is: Thursday +Sunday +0 Monday 1 Tuesday +*/ diff --git a/eBook/exercises/chapter_10/employee_salary.go b/eBook/exercises/chapter_10/employee_salary.go new file mode 100755 index 0000000..af1713b --- /dev/null +++ b/eBook/exercises/chapter_10/employee_salary.go @@ -0,0 +1,25 @@ +// methods1.go +package main + +import "fmt" + +/* basic data structure upon with we'll define methods */ +type employee struct { + salary float32 +} + +/* a method which will add a specified percent to an + employees salary */ +func (this *employee) giveRaise(pct float32) { + this.salary += this.salary * pct +} + +func main() { + /* create an employee instance */ + var e = new(employee) + e.salary = 100000; + /* call our method */ + e.giveRaise(0.04) + fmt.Printf("Employee now makes %f", e.salary) +} +// Employee now makes 104000.000000 \ No newline at end of file diff --git a/eBook/exercises/chapter_10/inherit_methods.go b/eBook/exercises/chapter_10/inherit_methods.go new file mode 100755 index 0000000..256fbff --- /dev/null +++ b/eBook/exercises/chapter_10/inherit_methods.go @@ -0,0 +1,40 @@ +package main + +import "fmt" + +type Base struct { + id string +} + +func (b *Base) Id() string { + return b.id +} + +func (b *Base) SetId(id string) { + b.id = id +} + +type Person struct { + Base + FirstName string + LastName string +} + +type Employee struct { + Person + salary float32 +} + +func main() { + idjb := Base{"007"} + jb := Person{idjb, "James", "Bond"} + e := &Employee{jb, 100000.} + fmt.Printf("ID of our hero: %v\n", e.Id()) + // Change the id: + e.SetId("007B") + fmt.Printf("The new ID of our hero: %v\n", e.Id()) +} +/* Output: +ID of our hero: 007 +The new ID of our hero: 007B +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/inheritance_car.go b/eBook/exercises/chapter_10/inheritance_car.go new file mode 100755 index 0000000..1858aac --- /dev/null +++ b/eBook/exercises/chapter_10/inheritance_car.go @@ -0,0 +1,59 @@ +// inheritance_car.go +package main + +import ( + "fmt" +) + +type Engine interface { + Start() + Stop() +} + +type Car struct { + wheelCount int + Engine +} + +// define a behavior for Car +func (car Car) numberOfWheels() int { + return car.wheelCount +} + +type Mercedes struct { + Car //anonymous field Car +} + +// a behavior only available for the Mercedes +func (m *Mercedes) sayHiToMerkel() { + fmt.Println("Hi Angela!") +} + +func (c *Car) Start() { + fmt.Println("Car is started") +} + +func (c *Car) Stop() { + fmt.Println("Car is stopped") +} + +func (c *Car) GoToWorkIn() { + // get in car + c.Start(); + // drive to work + c.Stop(); + // get out of car +} + +func main() { + m := Mercedes{Car{4, nil}} + fmt.Println("A Mercedes has this many wheels: ", m.numberOfWheels()) + m.GoToWorkIn() + m.sayHiToMerkel() +} +/* Output: +A Mercedes has this many wheels: 4 +Car is started +Car is stopped +Hi Angela! +*/ diff --git a/eBook/exercises/chapter_10/iteration_list.go b/eBook/exercises/chapter_10/iteration_list.go new file mode 100755 index 0000000..75b6f58 --- /dev/null +++ b/eBook/exercises/chapter_10/iteration_list.go @@ -0,0 +1,23 @@ +/* +iteration_list.go:12: cannot define new methods on non-local type list.List +iteration_list.go:17: lst.Iter undefined (type *list.List has no field or method Iter) +---- Build file exited with code 1 +*/ +package main + +import "container/list" + +// cannot define new methods on non-local type list.List +// List iterator: +func (p *list.List) Iter() { +} + +func main() { + lst := new(list.List) + for _ = range lst.Iter() { + } +} + + + + diff --git a/eBook/exercises/chapter_10/magic.go b/eBook/exercises/chapter_10/magic.go new file mode 100755 index 0000000..2cd7d1a --- /dev/null +++ b/eBook/exercises/chapter_10/magic.go @@ -0,0 +1,29 @@ +// magic.go +package main + +import "fmt" + +type Base struct{} + +func (Base) Magic() { fmt.Print("base magic ") } + +func (self Base) MoreMagic() { + self.Magic() + self.Magic() +} + +type Voodoo struct { + Base +} + +func (Voodoo) Magic() { fmt.Println("voodoo magic") } + +func main() { + v := new(Voodoo) + v.Magic() + v.MoreMagic() +} +/* Output: +voodoo magic +base magic base magic +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/main_stack.go b/eBook/exercises/chapter_10/main_stack.go new file mode 100755 index 0000000..2125005 --- /dev/null +++ b/eBook/exercises/chapter_10/main_stack.go @@ -0,0 +1,45 @@ +// Q15.go +package main + +import ( + "fmt" + "./stack/stack" +) + +func main() { + st1 := new(stack.Stack) + fmt.Printf("%v\n", st1) + st1.Push(3) + fmt.Printf("%v\n", st1) + st1.Push(7) + fmt.Printf("%v\n", st1) + st1.Push(10) + fmt.Printf("%v\n", st1) + st1.Push(99) + fmt.Printf("%v\n", st1) + p := st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) +} +/* Output: +[0:3] +[0:3] [1:7] +[0:3] [1:7] [2:10] +[0:3] [1:7] [2:10] [3:99] +Popped 99 +[0:3] [1:7] [2:10] +Popped 10 +[0:3] [1:7] +Popped 7 +[0:3] +Popped 3 +*/ diff --git a/eBook/exercises/chapter_10/personex1.go b/eBook/exercises/chapter_10/personex1.go new file mode 100755 index 0000000..df4e7ae --- /dev/null +++ b/eBook/exercises/chapter_10/personex1.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "strings" +) + +type Person struct { + firstName string + lastName string +} + +func upPerson (p Person) { + p.firstName = strings.ToUpper(p.firstName) + p.lastName = strings.ToUpper(p.lastName) +} + +func main() { +// 1- struct as a value type: + var pers1 Person + pers1.firstName = "Chris" + pers1.lastName = "Woodward" + upPerson(pers1) + fmt.Printf("The name of the person is %s %s\n", pers1.firstName, pers1.lastName) +// 2 - struct as a pointer: + pers2 := new(Person) + pers2.firstName = "Chris" + pers2.lastName = "Woodward" + upPerson(*pers2) + fmt.Printf("The name of the person is %s %s\n", pers2.firstName, pers2.lastName) +// 3 - struct as a literal: + pers3 := &Person{"Chris","Woodward"} + upPerson(*pers3) + fmt.Printf("The name of the person is %s %s\n", pers3.firstName, pers3.lastName) +} +/* Output: +The name of the person is Chris Woodward +The name of the person is Chris Woodward +The name of the person is Chris Woodward +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/point.go b/eBook/exercises/chapter_10/point.go new file mode 100755 index 0000000..a536cbe --- /dev/null +++ b/eBook/exercises/chapter_10/point.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + X, Y float64 +} + +type Point3 struct { + X, Y, Z float64 +} + +type Polar struct { + R, T float64 +} + +func Abs(p *Point) float64 { + return math.Sqrt(float64(p.X*p.X + p.Y*p.Y)) +} + +func Scale(p *Point,s float64) (q Point) { + q.X = p.X * s + q.Y = p.Y * s + return +} + +func main() { + p1 := new(Point) + p1.X = 3 + p1.Y = 4 + fmt.Printf("The length of the vector p1 is: %f\n", Abs(p1) ) + + p2:= &Point{4, 5} + fmt.Printf("The length of the vector p2 is: %f\n", Abs(p2) ) + + q := Scale(p1, 5) + fmt.Printf("The length of the vector q is: %f\n", Abs(&q) ) + fmt.Printf("Point p1 scaled by 5 has the following coordinates: X %f - Y %f", q.X, q.Y) +} +/* Output: +The length of the vector p1 is: 5.000000 +The length of the vector p2 is: 6.403124 +The length of the vector q is: 25.000000 +Point p1 scaled by 5 has the following coordinates: X 15.000000 - Y 20.000000 +*/ + diff --git a/eBook/exercises/chapter_10/point_methods.go b/eBook/exercises/chapter_10/point_methods.go new file mode 100755 index 0000000..fef05bb --- /dev/null +++ b/eBook/exercises/chapter_10/point_methods.go @@ -0,0 +1,54 @@ +// float64 is necessary as input to math.Sqrt() +package main + +import ( + "fmt" + "math" +) + +type Point struct { + X, Y float64 +} + +func (p *Point) Scale(s float64) { + p.X *= s + p.Y *= s +} + +func (p *Point) Abs() float64 { + return math.Sqrt(float64(p.X*p.X + p.Y*p.Y)) +} + +type Point3 struct { + X, Y, Z float64 +} + +func (p *Point3) Abs() float64 { + return math.Sqrt(float64(p.X*p.X + p.Y*p.Y + p.Z*p.Z)) +} + +type Polar struct { + R, T float64 +} + +func (p Polar) Abs() float64 { return p.R } + +func main() { + p1 := new(Point) + p1.X = 3 + p1.Y = 4 + fmt.Printf("The length of the vector p1 is: %f\n", p1.Abs()) + + p2:= &Point{4, 5} + fmt.Printf("The length of the vector p2 is: %f\n", p2.Abs() ) + + p1.Scale(5) + fmt.Printf("The length of the vector p1 after scaling is: %f\n", p1.Abs() ) + fmt.Printf("Point p1 after scaling has the following coordinates: X %f - Y %f", p1.X, p1.Y) +} +/* Output: +The length of the vector p1 is: 5.000000 +The length of the vector p2 is: 6.403124 +The length of the vector p1 after scaling is: 25.000000 +Point p1 after scaling has the following coordinates: X 15.000000 - Y 20.000000 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/rectangle.go b/eBook/exercises/chapter_10/rectangle.go new file mode 100755 index 0000000..7f3a4b2 --- /dev/null +++ b/eBook/exercises/chapter_10/rectangle.go @@ -0,0 +1,28 @@ +// rectangle.go +package main + +import "fmt" + +type Rectangle struct { + length, width int +} + +func (r *Rectangle) Area() int { + return r.length * r.width +} + +func (r *Rectangle) Perimeter() int { + return 2* (r.length + r.width) +} + +func main() { + r1 := Rectangle{4, 3} + fmt.Println("Rectangle is: ", r1) + fmt.Println("Rectangle area is: ", r1.Area()) + fmt.Println("Rectangle perimeter is: ", r1.Perimeter()) +} +/* Output: +Rectangle is: {4 3} +Rectangle area is: 12 +Rectangle perimeter is: 14 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/stack/stack_struct.go b/eBook/exercises/chapter_10/stack/stack_struct.go new file mode 100755 index 0000000..08a58e4 --- /dev/null +++ b/eBook/exercises/chapter_10/stack/stack_struct.go @@ -0,0 +1,32 @@ +// stack_struct.go +package stack + +import "strconv" +const LIMIT = 10 + +type Stack struct { + ix int // first free position, so data[ix] == 0 + data [LIMIT]int +} + +func (st *Stack) Push(n int) { + if (st.ix + 1 > LIMIT) { + return // stack is full! + } + st.data[st.ix] = n + st.ix++ +} + +func (st *Stack) Pop() int { + st.ix-- + return st.data[st.ix] +} + +func (st Stack) String() string { + str := "" + for ix:=0; ix=0; ix-- { + if v=st[ix]; v!=0 { + st[ix] = 0 + return v + } + } + return 0 +} + +func (st Stack) String() string { + str := "" + for ix, v := range st { + str += "[" + strconv.Itoa(ix) + ":" + strconv.Itoa(v) + "] " + } + return str +} \ No newline at end of file diff --git a/eBook/exercises/chapter_10/stack_struct.go b/eBook/exercises/chapter_10/stack_struct.go new file mode 100755 index 0000000..2a0ba11 --- /dev/null +++ b/eBook/exercises/chapter_10/stack_struct.go @@ -0,0 +1,59 @@ +// stack_struct.go +package main + +import ( + "fmt" + "strconv" +) + +const LIMIT = 4 +type Stack struct { + ix int // first free position, so data[ix] == 0 + data [LIMIT]int +} + +func main() { + st1 := new(Stack) + fmt.Printf("%v\n", st1) + st1.Push(3) + fmt.Printf("%v\n", st1) + st1.Push(7) + fmt.Printf("%v\n", st1) + st1.Push(10) + fmt.Printf("%v\n", st1) + st1.Push(99) + fmt.Printf("%v\n", st1) + p := st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) +} + +func (st *Stack) Push(n int) { + if (st.ix + 1 > LIMIT) { + return // stack is full! + } + st.data[st.ix] = n + st.ix++ +} + +func (st *Stack) Pop() int { + st.ix-- + return st.data[st.ix] +} + +func (st Stack) String() string { + str := "" + for ix:=0; ix 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +type Float64Array []float64 + +func (p Float64Array) Len() int { return len(p) } +func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] } +func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func NewFloat64Array() Float64Array { + return make([]float64, 25) +} + +func (p Float64Array) Fill(n int) { + rand.Seed(int64(time.Now().Nanosecond())) + for i := 0; i < n; i++ { + p[i] = 100 * (rand.Float64()) + } +} + +func (p Float64Array) List() string { + s := "{ " + for i := 0; i < p.Len(); i++ { + if p[i] == 0 { + continue + } + s += fmt.Sprintf("%3.1f ", p[i]) + } + s += " }" + return s +} + +func (p Float64Array) String() string { + return p.List() +} diff --git a/eBook/exercises/chapter_11/float_sortmain.go b/eBook/exercises/chapter_11/float_sortmain.go new file mode 100755 index 0000000..e7b1922 --- /dev/null +++ b/eBook/exercises/chapter_11/float_sortmain.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "./float64" +) + +func main() { + f1 := float64.NewFloat64Array() + f1.Fill(10) + fmt.Printf("Before sorting %s\n", f1) + float64.Sort(f1) + fmt.Printf("After sorting %s\n", f1) + if float64.IsSorted(f1) { + fmt.Println("The float64 array is sorted!") + } else { + fmt.Println("The float64 array is NOT sorted!") + } +} + +/* Output: +Before sorting { 55.0 82.3 36.4 66.6 25.3 82.7 47.4 21.5 4.6 81.6 } +After sorting { 4.6 21.5 25.3 36.4 47.4 55.0 66.6 81.6 82.3 82.7 } +The float64 array is sorted! +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/interface_nil.go b/eBook/exercises/chapter_11/interface_nil.go new file mode 100755 index 0000000..b2a4d4d --- /dev/null +++ b/eBook/exercises/chapter_11/interface_nil.go @@ -0,0 +1,46 @@ +// interface_nil.go +package main + +import "fmt" + +type Any interface {} +type Anything struct {} + +func main() { + any := getAny() + if any == nil { + fmt.Println("any is nil") + } else { + fmt.Println("any is not nil") + } +/* + // to get the inner value: + anything := any.(*Anything) + if anything == nil { + fmt.Println("anything is nil") + } else { + fmt.Println("anything is not nil") + } +*/ +} + +func getAny() Any { + return getAnything() +} + +func getAnything() *Anything { + return nil +} + +/* Output: +any is not nil +WHY? +you would perhaps expect: any is nil,because getAnything() returns that +BUT: +the interface value any is storing a value, so it is not nil. +It just so happens that the particular value it is storing is a nil pointer. +The any variable has a type, so it's not a nil interface, +rather an interface variable with type Any and concrete value (*Anything)(nil). +To get the inner value of any, use: anything := any.(*Anything) +now anything contains nil ! +*/ diff --git a/eBook/exercises/chapter_11/interface_poly3.go b/eBook/exercises/chapter_11/interface_poly3.go new file mode 100755 index 0000000..f75b454 --- /dev/null +++ b/eBook/exercises/chapter_11/interface_poly3.go @@ -0,0 +1,68 @@ +// interface_poly3.go +package main + +import ( + "fmt" + "math" +) + +type Shaper interface { + Area() float32 +} + +type Shape struct {} +func (sh Shape) Area() float32 { + return -1 // the shape is indetermined, so we return something impossible +} + +type Square struct { + side float32 + Shape +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +type Rectangle struct { + length, width float32 + Shape +} + +func (r *Rectangle) Area() float32 { + return r.length * r.width +} + +type Circle struct { + radius float32 + Shape +} + +func (c *Circle) Area() float32 { + return math.Pi * c.radius * c.radius +} + +func main() { + s := Shape{} + r := &Rectangle{5, 3, s} // Area() of Rectangle needs a value + q := &Square{5, s} // Area() of Square needs a pointer + c := &Circle{2.5, s} + shapes := []Shaper{r, q, c, s} + fmt.Println("Looping through shapes for area ...") + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +Shape details: &{2.5} +Area of this shape is: 19.634954 +Shape details: {} +Area of this shape is: -1 +*/ + diff --git a/eBook/exercises/chapter_11/interfaces_ext.go b/eBook/exercises/chapter_11/interfaces_ext.go new file mode 100755 index 0000000..4391ebc --- /dev/null +++ b/eBook/exercises/chapter_11/interfaces_ext.go @@ -0,0 +1,51 @@ +package main + +import "fmt" + +type Square struct { + side float32 +} + +type Triangle struct { + base float32 + height float32 +} + +type AreaInterface interface { + Area() float32 +} + +type PeriInterface interface { + Perimeter() float32 +} +func main() { + var areaIntf AreaInterface + var periIntf PeriInterface + + sq1 := new(Square) + sq1.side = 5 + tr1 := new(Triangle) + tr1.base = 3 + tr1.height = 5 + + areaIntf = sq1 + fmt.Printf("The square has area: %f\n", areaIntf.Area()) + + periIntf = sq1 + fmt.Printf("The square has perimeter: %f\n", periIntf.Perimeter()) + + areaIntf = tr1 + fmt.Printf("The triangle has area: %f\n", areaIntf.Area()) +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func (sq *Square) Perimeter() float32 { + return 4 * sq.side +} + +func (tr *Triangle) Area() float32 { + return 0.5 * tr.base*tr.height +} diff --git a/eBook/exercises/chapter_11/interfaces_poly2.go b/eBook/exercises/chapter_11/interfaces_poly2.go new file mode 100755 index 0000000..ce7ec97 --- /dev/null +++ b/eBook/exercises/chapter_11/interfaces_poly2.go @@ -0,0 +1,57 @@ +// interfaces_poly2.go +package main + +import ( + "fmt" + "math" +) + +type Shaper interface { + Area() float32 +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +type Rectangle struct { + length, width float32 +} + +func (r Rectangle) Area() float32 { + return r.length * r.width +} + +type Circle struct { + radius float32 +} + +func (c *Circle) Area() float32 { + return math.Pi * c.radius * c.radius +} + +func main() { + r := Rectangle{5, 3} // Area() of Rectangle needs a value + q := &Square{5} // Area() of Square needs a pointer + c := &Circle{2.5} + fmt.Println("Looping through shapes for area ...") + // shapes := []Shaper{Shaper(r), Shaper(q), Shaper(c)} + shapes := []Shaper{r, q, c} + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +Shape details: &{2.5} +Area of this shape is: 19.634954 +*/ diff --git a/eBook/exercises/chapter_11/main_stack.go b/eBook/exercises/chapter_11/main_stack.go new file mode 100755 index 0000000..1404db1 --- /dev/null +++ b/eBook/exercises/chapter_11/main_stack.go @@ -0,0 +1,29 @@ +// main_stack.go +package main + +import ( + "fmt" + "./stack/stack" +) + +var st1 stack.Stack + +func main() { + st1.Push("Brown") + st1.Push(3.14) + st1.Push(100) + st1.Push([]string{"Java", "C++", "Python", "C#", "Ruby"}) + for { + item, err := st1.Pop() + if err != nil { + break + } + fmt.Println(item) + } +} +/* Output: +[Java C++ Python C# Ruby] +100 +3.14 +Brown +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/main_stack_v2.go b/eBook/exercises/chapter_11/main_stack_v2.go new file mode 100755 index 0000000..447374a --- /dev/null +++ b/eBook/exercises/chapter_11/main_stack_v2.go @@ -0,0 +1,17 @@ +// main_stack_v2.go +package main + +import ( + "./stack/collection" + "fmt" +) + +func main() { + var s collection.Stack + s.Push("world") + s.Push("hello, ") + for s.Size() > 0 { + fmt.Print(s.Pop()) + } + fmt.Println() +} \ No newline at end of file diff --git a/eBook/exercises/chapter_11/map_function_interface.go b/eBook/exercises/chapter_11/map_function_interface.go new file mode 100755 index 0000000..90edce9 --- /dev/null +++ b/eBook/exercises/chapter_11/map_function_interface.go @@ -0,0 +1,62 @@ +package main + +import "fmt" + +type obj interface{} + +func main() { + // define a generic lambda function mf: + mf := func(i obj) obj { + switch i.(type) { + case int: + return i.(int) * 2 + case string: + return i.(string) + i.(string) + } + return i + } + + isl := []obj{0, 1, 2, 3, 4, 5} + res1 := mapFunc(mf, isl) + for _, v := range res1 { + fmt.Println(v) + } + println() + + ssl := []obj{"0", "1", "2", "3", "4", "5"} + res2 := mapFunc(mf, ssl) + for _, v := range res2 { + fmt.Println(v) + } +} + +func mapFunc(mf func(obj) obj, list []obj) ([]obj) { + result := make([]obj, len(list)) + + for ix, v := range list { + result[ix] = mf(v) + } + + // Equivalent: + /* + for ix := 0; ix 0 {os.Stdout.WriteString(" ")} + switch a := arg.(type) { // type switch + case Stringer: os.Stdout.WriteString(a.String()) + case int: os.Stdout.WriteString(strconv.Itoa(a)) + case string: os.Stdout.WriteString(a) + // more types + default: os.Stdout.WriteString("???") + } + } +} + +func main() { + print(Day(1), "was", Celsius(18.36)) // Tuesday was 18.4 °C +} +// Tuesday was 18.4 °C \ No newline at end of file diff --git a/eBook/exercises/chapter_11/simple_interface.go b/eBook/exercises/chapter_11/simple_interface.go new file mode 100755 index 0000000..f4a6fd9 --- /dev/null +++ b/eBook/exercises/chapter_11/simple_interface.go @@ -0,0 +1,34 @@ +// simple_interface.go +package main + +import ( + "fmt" +) + +type Simpler interface { + Get() int + Put(int) +} + +type Simple struct { + i int +} + +func (p *Simple) Get() int { + return p.i +} + +func (p *Simple) Put(u int) { + p.i = u +} + +func fI(it Simpler) int { + it.Put(5) + return it.Get() +} + +func main() { + var s Simple + fmt.Println(fI(&s)) // &s is required because Get() is defined with a receiver type pointer +} +// Output: 5 \ No newline at end of file diff --git a/eBook/exercises/chapter_11/simple_interface2.go b/eBook/exercises/chapter_11/simple_interface2.go new file mode 100755 index 0000000..5fb495b --- /dev/null +++ b/eBook/exercises/chapter_11/simple_interface2.go @@ -0,0 +1,61 @@ +// simple_interface2.go +package main + +import ( + "fmt" +) + +type Simpler interface { + Get() int + Set(int) +} + +type Simple struct { + i int +} + +func (p *Simple) Get() int { + return p.i +} + +func (p *Simple) Set(u int) { + p.i = u +} + +type RSimple struct { + i int + j int +} + +func (p *RSimple) Get() int { + return p.j +} + +func (p *RSimple) Set(u int) { + p.j = u +} + +func fI(it Simpler) int { + switch it.(type) { + case *Simple: + it.Set(5) + return it.Get() + case *RSimple: + it.Set(50) + return it.Get() + default: + return 99 + } + return 0 +} + +func main() { + var s Simple + fmt.Println(fI(&s)) // &s is required because Get() is defined with a receiver type pointer + var r RSimple + fmt.Println(fI(&r)) +} +/* Output: +5 +50 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/simple_interface3.go b/eBook/exercises/chapter_11/simple_interface3.go new file mode 100755 index 0000000..f747f4b --- /dev/null +++ b/eBook/exercises/chapter_11/simple_interface3.go @@ -0,0 +1,74 @@ +// simple_interface2.go +package main + +import ( + "fmt" +) + +type Simpler interface { + Get() int + Set(int) +} + +type Simple struct { + i int +} + +func (p *Simple) Get() int { + return p.i +} + +func (p *Simple) Set(u int) { + p.i = u +} + +type RSimple struct { + i int + j int +} + +func (p *RSimple) Get() int { + return p.j +} + +func (p *RSimple) Set(u int) { + p.j = u +} + +func fI(it Simpler) int { + switch it.(type) { + case *Simple: + it.Set(5) + return it.Get() + case *RSimple: + it.Set(50) + return it.Get() + default: + return 99 + } + return 0 +} + + +func gI(any interface{}) int { + // return any.(Simpler).Get() // unsafe, runtime panic possible + if v, ok := any.(Simpler); ok { + return v.Get() + } + return 0 // default value +} +/* Output: +6 +60 +*/ + +func main() { + var s Simple = Simple{6} + fmt.Println(gI(&s)) // &s is required because Get() is defined with a receiver type pointer + var r RSimple = RSimple{60,60} + fmt.Println(gI(&r)) +} +/* Output: +6 +60 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/sort/sort.go b/eBook/exercises/chapter_11/sort/sort.go new file mode 100755 index 0000000..9135d40 --- /dev/null +++ b/eBook/exercises/chapter_11/sort/sort.go @@ -0,0 +1,60 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package sort + +type Sorter interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +/* +func Sort(Sorter Interface) { + for i := 1; i < data.Len(); i++ { + for j := i; j > 0 && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} +*/ + +func Sort(data Sorter) { + for pass:=1; pass < data.Len(); pass++ { + for i:=0; i < data.Len() - pass; i++ { + if data.Less(i+1, i) { + data.Swap(i, i+1) + } + } + } +} + +func IsSorted(data Sorter) bool { + n := data.Len() + for i := n - 1; i > 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +// Convenience types for common cases +type IntArray []int + +func (p IntArray) Len() int { return len(p) } +func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } +func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type StringArray []string + +func (p StringArray) Len() int { return len(p) } +func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } +func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Convenience wrappers for common cases +func SortInts(a []int) { Sort(IntArray(a)) } +func SortStrings(a []string) { Sort(StringArray(a)) } + +func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } +func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } diff --git a/eBook/exercises/chapter_11/sort_persons.go b/eBook/exercises/chapter_11/sort_persons.go new file mode 100755 index 0000000..31b4a6d --- /dev/null +++ b/eBook/exercises/chapter_11/sort_persons.go @@ -0,0 +1,36 @@ +// sort_persons.go +package main + +import ( + "fmt" + "./sort" +) + +type Person struct { + firstName string + lastName string +} + +type Persons []Person + +func (p Persons) Len() int { return len(p) } + +func (p Persons) Less(i, j int) bool { + in := p[i].lastName + " " + p[i].firstName + jn := p[j].lastName + " " + p[j].firstName + return in < jn +} + +func (p Persons) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func main() { + p1 := Person{"Xavier","Papadopoulos"} + p2 := Person{"Chris","Naegels"} + p3 := Person{"John","Doe"} + arrP := Persons{p1,p2,p3} + fmt.Printf("Before sorting: %v\n", arrP) + sort.Sort(arrP) + fmt.Printf("After sorting: %v\n", arrP) +} diff --git a/eBook/exercises/chapter_11/stack/stack_general.go b/eBook/exercises/chapter_11/stack/stack_general.go new file mode 100755 index 0000000..da78464 --- /dev/null +++ b/eBook/exercises/chapter_11/stack/stack_general.go @@ -0,0 +1,39 @@ +// stack.go +package stack + +import "errors" + +type Stack []interface{} + +func (stack Stack) Len() int { + return len(stack) +} + +func (stack Stack) Cap() int { + return cap(stack) +} + +func (stack Stack) IsEmpty() bool { + return len(stack) == 0 +} + +func (stack *Stack) Push(e interface{}) { + *stack = append(*stack, e) +} + +func (stack Stack) Top() (interface{}, error) { + if len(stack) == 0 { + return nil, errors.New("stack is empty") + } + return stack[len(stack)-1], nil +} + +func (stack *Stack) Pop() (interface{}, error) { + stk := *stack // dereference to a local variable stk + if len(stk) == 0 { + return nil, errors.New("stack is empty") + } + top := stk[len(stk)-1] + *stack = stk[:len(stk)-1] // shrink the stack + return top, nil +} diff --git a/eBook/exercises/chapter_11/stack/stack_general_v2.go b/eBook/exercises/chapter_11/stack/stack_general_v2.go new file mode 100755 index 0000000..d1a6770 --- /dev/null +++ b/eBook/exercises/chapter_11/stack/stack_general_v2.go @@ -0,0 +1,28 @@ +// stack_general_v2.go +// Package collection implements a generic stack. +package collection + +// The zero value for Stack is an empty stack ready to use. +type Stack struct { + data []interface{} +} + +// Push adds x to the top of the stack. +func (s *Stack) Push(x interface{}) { + s.data = append(s.data, x) +} + +// Pop removes and returns the top element of the stack. +// It's a run-time error to call Pop on an empty stack. +func (s *Stack) Pop() interface{} { + i := len(s.data) - 1 + res := s.data[i] + s.data[i] = nil // to avoid memory leak + s.data = s.data[:i] + return res +} + +// Size returns the number of elements in the stack. +func (s *Stack) Size() int { + return len(s.data) +} \ No newline at end of file diff --git a/eBook/exercises/chapter_12/calculator.go b/eBook/exercises/chapter_12/calculator.go new file mode 100755 index 0000000..87b32fc --- /dev/null +++ b/eBook/exercises/chapter_12/calculator.go @@ -0,0 +1,53 @@ +// calculator.go +// example: calculate 3 + 4 = 7 as input: 3 ENTER 4 ENTER + ENTER --> result = 7, + +package main + +import ( + "fmt" + "strconv" + "bufio" + "os" + "./stack/stack" +) + +func main() { + buf := bufio.NewReader(os.Stdin) + calc1 := new(stack.Stack) + fmt.Println("Give a number, an operator (+, -, *, /), or q to stop:") + for { + token, err := buf.ReadString('\n') + if err != nil { + fmt.Println("Input error !") + os.Exit(1) + } + token = token[0:len(token)-2] // remove "\r\n" + // fmt.Printf("--%s--\n",token) // debug statement + switch { + case token == "q": // stop als invoer = "q" + fmt.Println("Calculator stopped") + return + case token >= "0" && token <= "999999": + i, _ := strconv.Atoi(token) + calc1.Push(i) + case token == "+": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p + q) + case token == "-": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p - q) + case token == "*": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p * q) + case token == "/": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p / q) + default: + fmt.Println("No valid input") + } + } +} diff --git a/eBook/exercises/chapter_12/cat_numbered.go b/eBook/exercises/chapter_12/cat_numbered.go new file mode 100755 index 0000000..774c58d --- /dev/null +++ b/eBook/exercises/chapter_12/cat_numbered.go @@ -0,0 +1,43 @@ +package main + +import ( + "os" + "io" + "fmt" + "bufio" + "flag" +) + +var numberFlag = flag.Bool("n", false, "number each line") + +func cat(r *bufio.Reader) { + i := 1 + for { + buf, err := r.ReadBytes('\n') + if err == io.EOF { + break + } + if *numberFlag { + fmt.Fprintf(os.Stdout, "%5d %s", i, buf) + i++ + } else { + fmt.Fprintf(os.Stdout, "%s", buf) + } + } + return +} + +func main() { + flag.Parse() + if flag.NArg() == 0 { + cat(bufio.NewReader(os.Stdin)) + } + for i := 0; i < flag.NArg(); i++ { + f, err := os.Open(flag.Arg(i)) + if err != nil { + fmt.Fprintf(os.Stderr, "%s:error reading from %s: %s\n", os.Args[0], flag.Arg(i), err.Error()) + continue + } + cat(bufio.NewReader(f)) + } +} diff --git a/eBook/exercises/chapter_12/degob.go b/eBook/exercises/chapter_12/degob.go new file mode 100755 index 0000000..31df21f --- /dev/null +++ b/eBook/exercises/chapter_12/degob.go @@ -0,0 +1,41 @@ +// degob.go +package main + +import ( + "bufio" + "fmt" + "encoding/gob" + "log" + "os" +) + +type Address struct { + Type string + City string + Country string +} + +type VCard struct { + FirstName string + LastName string + Addresses []*Address + Remark string +} + +var content string +var vc VCard + +func main() { + // using a decoder: + file, _ := os.Open("vcard.gob") + defer file.Close() + inReader := bufio.NewReader(file) + dec := gob.NewDecoder(inReader) + err := dec.Decode(&vc) + if err != nil { + log.Println("Error in decoding gob") + } + fmt.Println(vc) +} +// Output: +// {Jan Kersschot [0x12642e60 0x12642e80] none} \ No newline at end of file diff --git a/eBook/exercises/chapter_12/goprogram b/eBook/exercises/chapter_12/goprogram new file mode 100755 index 0000000..531ddb9 --- /dev/null +++ b/eBook/exercises/chapter_12/goprogram @@ -0,0 +1,10 @@ +// goprogram.go +package main + +import ( + "fmt" +) + +func main() { + fmt.Println("Hello World!") +} diff --git a/eBook/exercises/chapter_12/goprogramT b/eBook/exercises/chapter_12/goprogramT new file mode 100755 index 0000000..279309a Binary files /dev/null and b/eBook/exercises/chapter_12/goprogramT differ diff --git a/eBook/exercises/chapter_12/hash_md5.go b/eBook/exercises/chapter_12/hash_md5.go new file mode 100755 index 0000000..02e987e --- /dev/null +++ b/eBook/exercises/chapter_12/hash_md5.go @@ -0,0 +1,20 @@ +// hash_md5.go +package main + +import ( + "fmt"; + "crypto/md5" + "io" +) + +func main() { + hasher := md5.New() + b := []byte{} + io.WriteString(hasher, "test") + fmt.Printf("Result: %x\n", hasher.Sum(b)) + fmt.Printf("Result: %d\n", hasher.Sum(b)) +} +/* Output: +Result: 098f6bcd4621d373cade4e832627b4f6 +Result: [9 143 107 205 70 33 211 115 202 222 78 131 38 39 180 246] +*/ diff --git a/eBook/exercises/chapter_12/hello_who.go b/eBook/exercises/chapter_12/hello_who.go new file mode 100755 index 0000000..ed11a37 --- /dev/null +++ b/eBook/exercises/chapter_12/hello_who.go @@ -0,0 +1,16 @@ +// hello_who.go +package main + +import ( + "fmt" + "os" + "strings" +) + +func main() { + who := "World" + if len(os.Args) > 1 { // os.Args[0] == hello_who + who = strings.Join(os.Args[1:], " ") + } + fmt.Println("Hello", who, "!") +} diff --git a/eBook/exercises/chapter_12/products.txt b/eBook/exercises/chapter_12/products.txt new file mode 100755 index 0000000..84a9e54 --- /dev/null +++ b/eBook/exercises/chapter_12/products.txt @@ -0,0 +1,4 @@ +"The ABC of Go";25.5;1500 +"Functional Programming with Go";56;280 +"Go for It";45.9;356 +"The Go Way";55;500 \ No newline at end of file diff --git a/eBook/exercises/chapter_12/read_csv.go b/eBook/exercises/chapter_12/read_csv.go new file mode 100755 index 0000000..213a654 --- /dev/null +++ b/eBook/exercises/chapter_12/read_csv.go @@ -0,0 +1,67 @@ +// read_csv.go +package main + +import ( + "bufio" + "fmt" + "log" + "io" + "os" + "strconv" + "strings" +) + +type Book struct { + title string + price float64 + quantity int +} + +func main() { + bks := make([]Book, 1) + file, err := os.Open("products.txt") + if err != nil { + log.Fatalf("Error %s opening file products.txt: ", err) + } + defer file.Close() + + reader := bufio.NewReader(file) + for { + // read one line from the file: + line, err := reader.ReadString('\n') + if err == io.EOF { + break + } + // remove \r and \n so 2(in Windows, in Linux only \n, so 1): + line = string(line[:len(line)-2]) + //fmt.Printf("The input was: -%s-", line) + + strSl := strings.Split(line, ";") + book := new(Book) + book.title = strSl[0] + book.price, err = strconv.ParseFloat(strSl[1], 32) + if err!=nil { + fmt.Printf("Error in file: %v", err) + } + //fmt.Printf("The quan was:-%s-", strSl[2]) + book.quantity, err = strconv.Atoi(strSl[2]) + if err!=nil { + fmt.Printf("Error in file: %v", err) + } + if bks[0].title == "" { + bks[0] = *book + } else { + bks = append(bks, *book) + } + } + fmt.Println("We have read the following books from the file: ") + for _, bk := range bks { + fmt.Println(bk) + } +} +/* Output: +We have read the following books from the file: +{"The ABC of Go" 25.5 1500} +{"Functional Programming with Go" 56 280} +{"Go for It" 45.900001525878906 356} +*/ diff --git a/eBook/exercises/chapter_12/remove_3till5char.go b/eBook/exercises/chapter_12/remove_3till5char.go new file mode 100755 index 0000000..18f9055 --- /dev/null +++ b/eBook/exercises/chapter_12/remove_3till5char.go @@ -0,0 +1,37 @@ +// remove_first6char.go +package main + +import ( + "fmt" + "io" + "bufio" + "os" +) + +func main() { + inputFile, _ := os.Open("goprogram") + outputFile, _ := os.OpenFile("goprogramT", os.O_WRONLY|os.O_CREATE, 0666) + defer inputFile.Close() + defer outputFile.Close() + inputReader := bufio.NewReader(inputFile) + outputWriter := bufio.NewWriter(outputFile) + for { + // inputString, readerError := inputReader.ReadString('\n') + inputString, _, readerError := inputReader.ReadLine() + if readerError == io.EOF { + fmt.Println("EOF") + break + } + //fmt.Printf("The input was: --%s--", inputString) + outputString := string([]byte(inputString)[2:5]) + "\r\n" + //fmt.Printf("The output was: --%s--", outputString) + _, err := outputWriter.WriteString(outputString) + //fmt.Printf("Number of bytes written %d\n", n) + if (err != nil) { + fmt.Println(err) + return + } + } + outputWriter.Flush() + fmt.Println("Conversion done") +} diff --git a/eBook/exercises/chapter_12/stack/stack_struct.go b/eBook/exercises/chapter_12/stack/stack_struct.go new file mode 100755 index 0000000..08a58e4 --- /dev/null +++ b/eBook/exercises/chapter_12/stack/stack_struct.go @@ -0,0 +1,32 @@ +// stack_struct.go +package stack + +import "strconv" +const LIMIT = 10 + +type Stack struct { + ix int // first free position, so data[ix] == 0 + data [LIMIT]int +} + +func (st *Stack) Push(n int) { + if (st.ix + 1 > LIMIT) { + return // stack is full! + } + st.data[st.ix] = n + st.ix++ +} + +func (st *Stack) Pop() int { + st.ix-- + return st.data[st.ix] +} + +func (st Stack) String() string { + str := "" + for ix:=0; ix 3 { + fmt.Println("Panicking!") + panic(fmt.Sprintf("%v", i)) + } + defer fmt.Println("Defer in g", i) + fmt.Println("Printing in g", i) + g(i + 1) +} +/* Output: +Calling g. +Printing in g 0 +Printing in g 1 +Printing in g 2 +Printing in g 3 +Panicking! +Defer in g 3 +Defer in g 2 +Defer in g 1 +Defer in g 0 +Recovered in f 4 +Returned normally from f. +*/ diff --git a/eBook/exercises/chapter_13/panic_defer_convint.go b/eBook/exercises/chapter_13/panic_defer_convint.go new file mode 100755 index 0000000..db4012f --- /dev/null +++ b/eBook/exercises/chapter_13/panic_defer_convint.go @@ -0,0 +1,44 @@ +// panic_defer_convint.go +package main + +import ( + "fmt" + "math" +) + +func main() { + l := int64(15000) + if i, err := IntFromInt64(l); err!= nil { + fmt.Printf("The conversion of %d to an int32 resulted in an error: %s", l, err.Error()) + } else { + fmt.Printf("%d converted to an int32 is %d", l, i) + } + fmt.Println() + l = int64(math.MaxInt32 + 15000) + if i, err := IntFromInt64(l); err!= nil { + fmt.Printf("The conversion of %d to an int32 resulted in an error: %s", l, err.Error()) + } else { + fmt.Printf("%d converted to an int32 is %d", l, i) + } +} + +func ConvertInt64ToInt(l int64) int { + if math.MinInt32 <= l && l <= math.MaxInt32 { + return int(l) + } + panic(fmt.Sprintf("%d is out of the int32 range", l)) +} + +func IntFromInt64(l int64) (i int, err error) { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("%v", e) + } + }() + i = ConvertInt64ToInt(l) + return i, nil +} +/* Output: +15000 converted to an int32 is 15000 +The conversion of 2147498647 to an int32 resulted in an error: 2147498647 is out of the int32 range +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_13/recover_divbyzero.go b/eBook/exercises/chapter_13/recover_divbyzero.go new file mode 100755 index 0000000..6a90d66 --- /dev/null +++ b/eBook/exercises/chapter_13/recover_divbyzero.go @@ -0,0 +1,34 @@ +// recover_divbyzero.go +package main + +import ( + "fmt" +) + +func badCall() { + a, b := 10, 0 + n := a / b + fmt.Println(n) +} + +func test() { + defer func() { + if e := recover(); e != nil { + fmt.Printf("Panicing %s\r\n", e); + } + + }() + badCall() + fmt.Printf("After bad call\r\n"); +} + +func main() { + fmt.Printf("Calling test\r\n"); + test() + fmt.Printf("Test completed\r\n"); +} +/* Output: +Calling test +Panicing runtime error: integer divide by zero +Test completed +*/ diff --git a/eBook/exercises/chapter_13/string_reverse.go b/eBook/exercises/chapter_13/string_reverse.go new file mode 100755 index 0000000..2069480 --- /dev/null +++ b/eBook/exercises/chapter_13/string_reverse.go @@ -0,0 +1,18 @@ +// string_reverse.go +package strev + +func Reverse(s string) string { + runes := []rune(s) + n, h := len(runes), len(runes)/2 + for i := 0; i < h; i++ { + runes[i], runes[n-1-i] = runes[n-1-i], runes[i] + } + return string(runes) +} + +/* +func main() { + s := "My Test String!" + fmt.Println(s, " --> ", Reverse(s)) +} +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_13/string_reverse_test.go b/eBook/exercises/chapter_13/string_reverse_test.go new file mode 100755 index 0000000..d767773 --- /dev/null +++ b/eBook/exercises/chapter_13/string_reverse_test.go @@ -0,0 +1,40 @@ +// string_reverse_test.go +package strev + +import "testing" +import "./strev" + +type ReverseTest struct { + in, out string +} + +var ReverseTests = []ReverseTest { + ReverseTest{"ABCD", "DCBA"}, + ReverseTest{"CVO-AZ", "ZA-OVC"}, + ReverseTest{"Hello 世界", "界世 olleH"}, +} + +func TestReverse(t *testing.T) { +/* + in := "CVO-AZ" + out := Reverse(in) + exp := "ZA-OVC" + if out != exp { + t.Errorf("Reverse of %s expects %s, but got %s", in, exp, out) + } +*/ +// testing with a battery of testdata: + for _, r := range ReverseTests { + exp := strev.Reverse(r.in) + if r.out != exp { + t.Errorf("Reverse of %s expects %s, but got %s", r.in, exp, r.out) + } + } +} + +func BenchmarkReverse(b *testing.B) { + s := "ABCD" + for i:=0; i < b.N; i++ { + strev.Reverse(s) + } +} diff --git a/eBook/exercises/chapter_14/blocking.go b/eBook/exercises/chapter_14/blocking.go new file mode 100755 index 0000000..3224ba1 --- /dev/null +++ b/eBook/exercises/chapter_14/blocking.go @@ -0,0 +1,19 @@ +// blocking.go +// throw: all goroutines are asleep - deadlock! +package main + +import ( + "fmt" +) + +func f1(in chan int) { + fmt.Println(<-in) +} + +func main() { + out := make(chan int) + //out := make(chan int, 1) // solution 2 + // go f1(out) // solution 1 + out <- 2 + go f1(out) +} diff --git a/eBook/exercises/chapter_14/channel_block3.go b/eBook/exercises/chapter_14/channel_block3.go new file mode 100755 index 0000000..00cfba7 --- /dev/null +++ b/eBook/exercises/chapter_14/channel_block3.go @@ -0,0 +1,22 @@ +package main + +import "fmt" +import "time" + +func main() { + c := make(chan int) + go func() { + time.Sleep(15 * 1e9) + x := <-c + fmt.Println("received", x) + }() + fmt.Println("sending", 10) + c <- 10 + fmt.Println("sent", 10) +} +/* Output: +sending 10 +(15 s later): +received 10 +sent 10 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/channel_buffer.go b/eBook/exercises/chapter_14/channel_buffer.go new file mode 100755 index 0000000..07e907b --- /dev/null +++ b/eBook/exercises/chapter_14/channel_buffer.go @@ -0,0 +1,21 @@ +package main + +import "fmt" +import "time" + +func main() { + c := make(chan int, 50) + go func() { + time.Sleep(15 * 1e9) + x := <-c + fmt.Println("received", x) + }() + fmt.Println("sending", 10) + c <- 10 + fmt.Println("sent", 10) +} +/* Output: +sending 10 +sent 10 // prints immediately +no further output, because main() then stops +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/concurrent_pi.go b/eBook/exercises/chapter_14/concurrent_pi.go new file mode 100755 index 0000000..7ea2d59 --- /dev/null +++ b/eBook/exercises/chapter_14/concurrent_pi.go @@ -0,0 +1,45 @@ +// Concurrent computation of pi. +// See http://goo.gl/ZuTZM. - Comparison with Scala! +// +// This demonstrates Go's ability to handle +// large numbers of concurrent processes. +// It is an unreasonable way to calculate pi. +package main + +import ( + "fmt" + "math" + "time" +) + +func main() { + start := time.Now() + fmt.Println(CalculatePi(5000)) + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +// CalculatePi launches n goroutines to compute an +// series-approximation of pi. +func CalculatePi(n int) float64 { + ch := make(chan float64) + for k := 0; k <= n; k++ { + // calculate k-th term in the series + go term(ch, float64(k)) + } + f := 0.0 + //wait for all goroutines to complete, get and sum up their results: + for k := 0; k <= n; k++ { + f += <-ch + } + return f +} + +func term(ch chan float64, k float64) { + ch <- 4 * math.Pow(-1, k) / (2*k + 1) +} +/* Output: +3.14179261359579 +The calculation took this amount of time: 0.028002 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/concurrent_pi2.go b/eBook/exercises/chapter_14/concurrent_pi2.go new file mode 100755 index 0000000..621f148 --- /dev/null +++ b/eBook/exercises/chapter_14/concurrent_pi2.go @@ -0,0 +1,45 @@ +// concurrent_pi2.go +package main + +import ( + "fmt" + "math" + "runtime" + "time" +) + +const NCPU = 2 + +func main() { + start := time.Now() + runtime.GOMAXPROCS(2) + fmt.Println(CalculatePi(5000)) + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +func CalculatePi(end int) float64 { + ch := make(chan float64) + for i := 0; i < NCPU; i++ { + go term(ch, i*end/NCPU, (i+1)*end/NCPU) + } + result := 0.0 + for i := 0; i < NCPU; i++ { + result += <-ch + } + return result +} + +func term(ch chan float64, start, end int) { + result := 0.0 + for i := start; i < end; i++ { + x := float64(i) + result += 4 * (math.Pow(-1, x) / (2.0*x + 1.0)) + } + ch <- result +} +/* Output: +3.1413926535917938 +The calculation took this amount of time: 0.002000 +*/ diff --git a/eBook/exercises/chapter_14/general_lazy_evalution2.go b/eBook/exercises/chapter_14/general_lazy_evalution2.go new file mode 100755 index 0000000..e51ff6c --- /dev/null +++ b/eBook/exercises/chapter_14/general_lazy_evalution2.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" +) + +type Any interface{} +type EvalFunc func(Any) (Any, Any) + +func main() { + fibFunc := func(state Any) (Any, Any) { + os := state.([]uint64) + v1 := os[0] + v2 := os[1] + ns := []uint64{v2, v1 + v2} + return v1, ns + } + fib := BuildLazyUInt64Evaluator(fibFunc, []uint64{0, 1}) + + for i := 0; i < 10; i++ { + fmt.Printf("Fib nr %v: %v\n", i, fib()) + } +} + +func BuildLazyEvaluator(evalFunc EvalFunc, initState Any) func() Any { + retValChan := make(chan Any) + loopFunc := func() { + var actState Any = initState + var retVal Any + for { + retVal, actState = evalFunc(actState) + retValChan <- retVal + } + } + retFunc := func() Any { + return <-retValChan + } + go loopFunc() + return retFunc +} + +func BuildLazyUInt64Evaluator(evalFunc EvalFunc, initState Any) func() uint64 { + ef := BuildLazyEvaluator(evalFunc, initState) + return func() uint64 { + return ef().(uint64) + } +} +/* Output: +Fib nr 0: 0 +Fib nr 1: 1 +Fib nr 2: 1 +Fib nr 3: 2 +Fib nr 4: 3 +Fib nr 5: 5 +Fib nr 6: 8 +Fib nr 7: 13 +Fib nr 8: 21 +Fib nr 9: 34 +*/ diff --git a/eBook/exercises/chapter_14/gofibonacci.go b/eBook/exercises/chapter_14/gofibonacci.go new file mode 100755 index 0000000..8dc6e0a --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci.go @@ -0,0 +1,44 @@ +// Q26_fibonacci_go.go +package main + +import ( + "fmt" + "time" + "os" +) + +func main() { + term := 25 + i := 0 + c := make(chan int) + start := time.Now() + + go fibnterms(term, c) + for { + if result, ok := <-c; ok { + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + i++ + } else { + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) + os.Exit(0) + } + } +} + +func fibnterms(term int, c chan int) { + for i := 0; i <= term; i++ { + c <- fibonacci(i) + } + close(c) +} + +func fibonacci(n int) (res int) { + if n <= 1 { + res = 1 + } else { + res = fibonacci(n-1) + fibonacci(n-2) + } + return +} diff --git a/eBook/exercises/chapter_14/gofibonacci2.go b/eBook/exercises/chapter_14/gofibonacci2.go new file mode 100755 index 0000000..46e7a59 --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci2.go @@ -0,0 +1,35 @@ +// gofibonacci2.go +package main + +import ( + "fmt" +) + +func fibonacci(n int, c chan int) { + x, y := 1, 1 + for i := 0; i < n; i++ { + c <- x + x, y = y, x+y + } + close(c) +} + +func main() { + c := make(chan int, 10) + go fibonacci(cap(c), c) + for i := range c { + fmt.Println(i) + } +} +/* Output: +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +*/ diff --git a/eBook/exercises/chapter_14/gofibonacci3.go b/eBook/exercises/chapter_14/gofibonacci3.go new file mode 100755 index 0000000..8560a3f --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci3.go @@ -0,0 +1,45 @@ +// courtesy of: http://sdh33b.blogspot.com/2009/12/fibonacci-in-go.html +package main + +import ( + "fmt" + "time" +) + +func dup3(in <-chan int) (<-chan int, <-chan int, <-chan int) { + a, b, c := make(chan int, 2), make(chan int, 2), make(chan int, 2) + go func() { + for { + x := <-in + a <- x + b <- x + c <- x + } + }() + return a, b, c +} + +func fib() <-chan int { + x := make(chan int, 2) + a, b, out := dup3(x) + go func() { + x <- 0 + x <- 1 + <-a + for { + x <- <-a + <-b + } + }() + return out +} + +func main() { + start := time.Now() + x := fib() + for i := 0; i < 10; i++ { + fmt.Println(<-x) + } + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} diff --git a/eBook/exercises/chapter_14/gofibonacci_select.go b/eBook/exercises/chapter_14/gofibonacci_select.go new file mode 100755 index 0000000..1811d14 --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci_select.go @@ -0,0 +1,42 @@ +// gofibonacci_select.go +package main + +import "fmt" + +func fibonacci(c, quit chan int) { + x, y := 1, 1 + for { + select { + case c <- x: + x, y = y, x+y + case <-quit: + fmt.Println("quit") + return + } + } +} + +func main() { + c := make(chan int) + quit := make(chan int) + go func() { + for i := 0; i < 10; i++ { + fmt.Println(<-c) + } + quit <- 0 + }() + fibonacci(c, quit) +} +/* Output: +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +quit +*/ diff --git a/eBook/exercises/chapter_14/goroutine_close.go b/eBook/exercises/chapter_14/goroutine_close.go new file mode 100755 index 0000000..56ea4e1 --- /dev/null +++ b/eBook/exercises/chapter_14/goroutine_close.go @@ -0,0 +1,26 @@ +// Q20_goroutine.go +package main + +import ( + "fmt" +) + +func tel(ch chan int) { + for i:=0; i < 15; i++ { + ch <- i + } + close(ch) // if this is ommitted: panic: all goroutines are asleep - deadlock! +} + +func main() { + var ok = true + var i int + ch := make(chan int) + + go tel(ch) + for ok { + if i, ok= <-ch; ok { + fmt.Printf("ok is %t and the counter is at %d\n", ok, i) + } + } +} diff --git a/eBook/exercises/chapter_14/goroutine_panic.go b/eBook/exercises/chapter_14/goroutine_panic.go new file mode 100755 index 0000000..a9783dd --- /dev/null +++ b/eBook/exercises/chapter_14/goroutine_panic.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" +) + +func tel(ch chan int) { + for i := 0; i < 15; i++ { + ch <- i + } +} + +func main() { + var ok = true + ch := make(chan int) + + go tel(ch) + for ok { + i := <-ch + fmt.Printf("ok is %t and the counter is at %d\n", ok, i) + } +} diff --git a/eBook/exercises/chapter_14/goroutine_select.go b/eBook/exercises/chapter_14/goroutine_select.go new file mode 100755 index 0000000..5e2c7da --- /dev/null +++ b/eBook/exercises/chapter_14/goroutine_select.go @@ -0,0 +1,31 @@ +// Q20b_goroutine.go +package main + +import ( + "fmt" + "os" +) + +func tel(ch chan int, quit chan bool) { + for i:=0; i < 15; i++ { + ch <- i + } + quit <- true +} + +func main() { + var ok = true + ch := make(chan int) + quit := make(chan bool) + + go tel(ch, quit) + for ok { + select { + case i:= <-ch: + fmt.Printf("The counter is at %d\n", i) + case <-quit: + os.Exit(0) + } + } +} + diff --git a/eBook/exercises/chapter_14/gosum.go b/eBook/exercises/chapter_14/gosum.go new file mode 100755 index 0000000..53271f8 --- /dev/null +++ b/eBook/exercises/chapter_14/gosum.go @@ -0,0 +1,16 @@ +// gosum.go +package main + +import ( + "fmt" +) + +func sum(x, y int, c chan int) { + c <- x + y +} + +func main() { + c := make(chan int) + go sum(12, 13, c) + fmt.Println(<-c) // 25 +} diff --git a/eBook/exercises/chapter_14/multiplex_server3.go b/eBook/exercises/chapter_14/multiplex_server3.go new file mode 100755 index 0000000..6d1c2e5 --- /dev/null +++ b/eBook/exercises/chapter_14/multiplex_server3.go @@ -0,0 +1,58 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package main + +import "fmt" + +type Request struct { + a, b int + replyc chan int // reply channel inside the Request +} + +type binOp func(a, b int) int + +func run(op binOp, req *Request) { + req.replyc <- op(req.a, req.b) +} + +func (r *Request) String() string { + return fmt.Sprintf("%d+%d=%d", r.a, r.b, <-r.replyc) +} + +func server(op binOp, service chan *Request, quit chan bool) { + for { + select { + case req := <-service: + go run(op, req) + case <-quit: + return // stop infinite loop + } + } +} + +func startServer(op binOp) (service chan *Request, quit chan bool) { + service = make(chan *Request) + quit = make(chan bool) + go server(op, service, quit) + return service, quit +} + +func main() { + adder, quit := startServer(func(a, b int) int { return a + b }) + // make requests: + req1 := &Request{3, 4, make(chan int)} + req2 := &Request{150, 250, make(chan int)} + // send requests on the service channel + adder <- req1 + adder <- req2 + // ask for the results: ( method String() is called ) + fmt.Println(req1, req2) + // shutdown server: + quit <- true + fmt.Print("done") +} +/* output: +3+4=7 150+250=400 +done +*/ diff --git a/eBook/exercises/chapter_14/polar_to_cartesian.go b/eBook/exercises/chapter_14/polar_to_cartesian.go new file mode 100755 index 0000000..01be44f --- /dev/null +++ b/eBook/exercises/chapter_14/polar_to_cartesian.go @@ -0,0 +1,101 @@ +// polartocartesian.go +package main + +import ( + "bufio" + "fmt" + "math" + "os" + "runtime" + "strconv" + "strings" +) + +type polar struct { + radius float64 + Θ float64 +} + +type cartesian struct { + x float64 + y float64 +} + +const result = "Polar: radius=%.02f angle=%.02f degrees -- Cartesian: x=%.02f y=%.02f\n" + +var prompt = "Enter a radius and an angle (in degrees), e.g., 12.5 90, " + "or %s to quit." + +func init() { + if runtime.GOOS == "windows" { + prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter") + } else { // Unix-like + prompt = fmt.Sprintf(prompt, "Ctrl+D") + } +} + +func main() { + questions := make(chan polar) + defer close(questions) + answers := createSolver(questions) + defer close(answers) + interact(questions, answers) +} + +func createSolver(questions chan polar) chan cartesian { + answers := make(chan cartesian) + go func() { + for { + polarCoord := <-questions + Θ := polarCoord.Θ * math.Pi / 180.0 // degrees to radians + x := polarCoord.radius * math.Cos(Θ) + y := polarCoord.radius * math.Sin(Θ) + answers <- cartesian{x, y} + } + }() + return answers +} + +func interact(questions chan polar, answers chan cartesian) { + reader := bufio.NewReader(os.Stdin) + fmt.Println(prompt) + for { + fmt.Printf("Radius and angle: ") + line, err := reader.ReadString('\n') + if err != nil { + break + } + line = line[:len(line)-1] // chop of newline character + if numbers := strings.Fields(line); len(numbers) == 2 { + polars, err := floatsForStrings(numbers) + if err != nil { + fmt.Fprintln(os.Stderr, "invalid number") + continue + } + questions <- polar{polars[0], polars[1]} + coord := <-answers + fmt.Printf(result, polars[0], polars[1], coord.x, coord.y) + } else { + fmt.Fprintln(os.Stderr, "invalid input") + } + } + fmt.Println() +} + +func floatsForStrings(numbers []string) ([]float64, error) { + var floats []float64 + for _, number := range numbers { + if x, err := strconv.ParseFloat(number, 64); err != nil { + return nil, err + } else { + floats = append(floats, x) + } + } + return floats, nil +} +/* Output: +Enter a radius and an angle (in degrees), e.g., 12.5 90, or Ctrl+Z, Enter to qui +t. +Radius and angle: 12.5 90 +Polar: radius=12.50 angle=90.00 degrees -- Cartesian: x=0.00 y=12.50 +Radius and angle: ^Z +*/ diff --git a/eBook/exercises/chapter_14/producer_consumer.go b/eBook/exercises/chapter_14/producer_consumer.go new file mode 100755 index 0000000..465dae2 --- /dev/null +++ b/eBook/exercises/chapter_14/producer_consumer.go @@ -0,0 +1,42 @@ +// goroutines2.go +package main + +import "fmt" + +// integer producer: +func numGen(start, count int, out chan<- int) { + for i := 0; i < count; i++ { + out <- start + start = start + count + } + close(out) +} + +// integer consumer: +func numEchoRange(in <-chan int, done chan<- bool) { + for num := range in { + fmt.Printf("%d\n", num) + } + done <- true +} + +func main() { + numChan := make(chan int) + done := make(chan bool) + go numGen(0, 10, numChan) + go numEchoRange(numChan, done) + + <-done +} +/* Output: +0 +10 +20 +30 +40 +50 +60 +70 +80 +90 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/producer_consumer2.go b/eBook/exercises/chapter_14/producer_consumer2.go new file mode 100755 index 0000000..353daa3 --- /dev/null +++ b/eBook/exercises/chapter_14/producer_consumer2.go @@ -0,0 +1,29 @@ +// prod_cons.go +/* producer-consumer problem in Go */ +package main + +import "fmt" + +var done = make(chan bool) +var msgs = make(chan int) + +func produce() { + for i := 0; i < 10; i++ { + msgs <- i + } + done <- true +} + +func consume() { + for { + msg := <-msgs + fmt.Print(msg, " ") + } +} + +func main() { + go produce() + go consume() + <-done +} +// Output: 0 1 2 3 4 5 6 7 8 9 \ No newline at end of file diff --git a/eBook/exercises/chapter_14/random_bitgen.go b/eBook/exercises/chapter_14/random_bitgen.go new file mode 100755 index 0000000..5a31efe --- /dev/null +++ b/eBook/exercises/chapter_14/random_bitgen.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" +) + +func main() { + c := make(chan int) + // consumer: + go func() { + for { + fmt.Print(<-c, " ") + } + }() + // producer: + for { + select { + case c <- 0: + case c <- 1: + } + } + +} diff --git a/eBook/exercises/chapter_15/client1.go b/eBook/exercises/chapter_15/client1.go new file mode 100755 index 0000000..179aee4 --- /dev/null +++ b/eBook/exercises/chapter_15/client1.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + "os" + "net" + "bufio" + "strings" +) + +func main() { + var conn net.Conn + var error error + var inputReader *bufio.Reader + var input string + var clientName string + + // maak connectie met de server: + conn, error = net.Dial("tcp", "localhost:50000") + checkError(error) + + inputReader = bufio.NewReader(os.Stdin) + fmt.Println("First, what is your name?") + clientName, _ = inputReader.ReadString('\n') + // fmt.Printf("CLIENTNAME %s",clientName) + trimmedClient := strings.Trim(clientName, "\r\n") // "\r\n" voor Windows, "\n" voor Linux + + for { + fmt.Println("What to send to the server? Type Q to quit. Type SH to shutdown server.") + input, _ = inputReader.ReadString('\n') + trimmedInput := strings.Trim(input, "\r\n") + // fmt.Printf("input:--%s--",input) + // fmt.Printf("trimmedInput:--%s--",trimmedInput) + if trimmedInput == "Q" { + return + } + _, error = conn.Write([]byte(trimmedClient + " says: " + trimmedInput)) + checkError(error) + } +} + +func checkError(error error) { + if error != nil { + panic("Error: " + error.Error()) // terminate program + } +} \ No newline at end of file diff --git a/eBook/exercises/chapter_15/hello_server.go b/eBook/exercises/chapter_15/hello_server.go new file mode 100755 index 0000000..fbeb8a3 --- /dev/null +++ b/eBook/exercises/chapter_15/hello_server.go @@ -0,0 +1,19 @@ +// hello_server.go +package main + +import ( + "fmt" + "net/http" +) + +type Hello struct{} + +func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello!") +} + +func main() { + var h Hello + http.ListenAndServe("localhost:4000",h) +} +// Output in browser-window with url http://localhost:4000: Hello! diff --git a/eBook/exercises/chapter_15/http_fetch2.go b/eBook/exercises/chapter_15/http_fetch2.go new file mode 100755 index 0000000..8ef2c0b --- /dev/null +++ b/eBook/exercises/chapter_15/http_fetch2.go @@ -0,0 +1,31 @@ +// httpfetch.go +package main + +import ( + "bufio" + "fmt" + "net/http" + "io/ioutil" + "log" + "os" + "strings" +) + +func main() { + fmt.Print("Give the url from which to read: ") + iread := bufio.NewReader(os.Stdin) + url, _ := iread.ReadString('\n') + url = strings.Trim(url," \n\r") // trimming space,etc. + // fmt.Println("***", url,"***") // debugging + res, err := http.Get(url) + CheckError(err) + data, err := ioutil.ReadAll(res.Body) + CheckError(err) + fmt.Printf("Got: %q", string(data)) +} + +func CheckError(err error) { + if err != nil { + log.Fatalf("Get: %v", err) + } +} diff --git a/eBook/exercises/chapter_15/server1.go b/eBook/exercises/chapter_15/server1.go new file mode 100755 index 0000000..5ffa2bf --- /dev/null +++ b/eBook/exercises/chapter_15/server1.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + "os" + "net" + "strings" +) + +// Map of the clients: contains: clientname - 1 (active) / 0 - (inactive) +var mapUsers map[string]int + +func main() { + var listener net.Listener + var error error + var conn net.Conn + mapUsers = make(map[string]int) + + fmt.Println("Starting the server ...") + + // create listener: + listener, error = net.Listen("tcp", "localhost:50000") + checkError(error) + // listen and accept connections from clients: + for { + conn, error = listener.Accept() + checkError(error) + go doServerStuff(conn) + } +} + +func doServerStuff(conn net.Conn) { + var buf []byte + var error error + + for { + buf = make([]byte, 512) + _, error = conn.Read(buf) + checkError(error) + input := string(buf) + if strings.Contains(input, ": SH") { + fmt.Println("Server shutting down.") + os.Exit(0) + } + // op commando WHO: write out mapUsers + if strings.Contains(input, ": WHO") { + DisplayList() + } + // extract clientname: + ix := strings.Index(input, "says") + clName := input[0:ix-1] + //fmt.Printf("The clientname is ---%s---\n", string(clName)) + // set clientname active in mapUsers: + mapUsers[string(clName)] = 1 + fmt.Printf("Received data: --%v--", string(buf)) + } +} + +// advantage: code is cleaner, +// disadvantage: the server process has to stop at any error: +// a simple return continues in the function where we came from! +func checkError(error error) { + if error != nil { + panic("Error: " + error.Error()) // terminate program + } +} + +func DisplayList() { + fmt.Println("--------------------------------------------") + fmt.Println("This is the client list: 1=active, 0=inactive") + for key, value := range mapUsers { + fmt.Printf("User %s is %d\n", key, value) + } + fmt.Println("--------------------------------------------") +} diff --git a/eBook/exercises/chapter_15/statistics.go b/eBook/exercises/chapter_15/statistics.go new file mode 100755 index 0000000..a280923 --- /dev/null +++ b/eBook/exercises/chapter_15/statistics.go @@ -0,0 +1,104 @@ +// statistics.go +package main + +import ( + "fmt" + "net/http" + "sort" + "strings" + "strconv" + "log" +) + +type statistics struct { + numbers []float64 + mean float64 + median float64 +} + +const form = `
+
+
+ +
` + +const error = `

%s

` + +var pageTop = "" +var pageBottom = "" + +func main() { + http.HandleFunc("/", homePage) + if err := http.ListenAndServe(":9001", nil); err != nil { + log.Fatal("failed to start server", err) + } +} + +func homePage(writer http.ResponseWriter, request *http.Request) { + writer.Header().Set("Content-Type", "text/html") + err := request.ParseForm() // Must be called before writing response + fmt.Fprint(writer, pageTop, form) + if err != nil { + fmt.Fprintf(writer, error, err) + } else { + if numbers, message, ok := processRequest(request); ok { + stats := getStats(numbers) + fmt.Fprint(writer, formatStats(stats)) + } else if message != "" { + fmt.Fprintf(writer, error, message) + } + } + fmt.Fprint(writer, pageBottom) +} + +func processRequest(request *http.Request) ([]float64, string, bool) { + var numbers []float64 + if slice, found := request.Form["numbers"]; found && len(slice) > 0 { + text := strings.Replace(slice[0], ",", " ", -1) + for _, field := range strings.Fields(text) { + if x, err := strconv.ParseFloat(field, 64); err != nil { + return numbers, "'" + field + "' is invalid", false + } else { + numbers = append(numbers, x) + } + } + } + if len(numbers) == 0 { + return numbers, "", false // no data first time form is shown + } + return numbers, "", true +} + +func getStats(numbers []float64) (stats statistics) { + stats.numbers = numbers + sort.Float64s(stats.numbers) + stats.mean = sum(numbers) / float64(len(numbers)) + stats.median = median(numbers) + return +} + +func sum(numbers []float64) (total float64) { + for _, x := range numbers { + total += x + } + return +} + +func median(numbers []float64) float64 { + middle := len(numbers)/2 + result := numbers[middle] + if len(numbers)%2 == 0 { + result = (result + numbers[middle-1]) / 2 + } + return result +} + +func formatStats(stats statistics) string { + return fmt.Sprintf(` + + + + + +
Results
Numbers%v
Count%d
Mean%f
Median%f
`, stats.numbers, len(stats.numbers), stats.mean, stats.median) +} diff --git a/eBook/exercises/chapter_15/template_validation_recover.go b/eBook/exercises/chapter_15/template_validation_recover.go new file mode 100755 index 0000000..2159188 --- /dev/null +++ b/eBook/exercises/chapter_15/template_validation_recover.go @@ -0,0 +1,29 @@ +// template_validation_recover.go +package main + +import ( + "text/template" + "fmt" + "log" +) + +func main() { + tOk := template.New("ok") + tErr := template.New("error_template") + defer func() { + if err := recover(); err != nil { + log.Printf("run time panic: %v", err) + } + }() + + //a valid template, so no panic with Must: + template.Must(tOk.Parse("/* and a comment */ some static text: {{ .Name }}")) + fmt.Println("The first one parsed OK.") + fmt.Println("The next one ought to fail.") + template.Must(tErr.Parse(" some static text {{ .Name }")) +} +/* Output: +The first one parsed OK. +The next one ought to fail. +2011/10/27 10:56:27 run time panic: template: error_template:1: unexpected "}" in command +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_15/twitter_status_json.go b/eBook/exercises/chapter_15/twitter_status_json.go new file mode 100755 index 0000000..2dc1319 --- /dev/null +++ b/eBook/exercises/chapter_15/twitter_status_json.go @@ -0,0 +1,33 @@ +// twitter_status_json.go +package main + +import ( + "net/http" + "fmt" + "encoding/json" + "io/ioutil" +) + +type Status struct { + Text string +} + +type User struct { + Status Status +} + +func main() { + /* perform an HTTP request for the twitter status of user: Googland */ + res, _:= http.Get("http://twitter.com/users/Googland.json") + /* initialize the structure of the JSON response */ + user := User{Status{""}} + /* unmarshal the JSON into our structures */ + temp, _ := ioutil.ReadAll(res.Body) + body := []byte(temp) + json.Unmarshal(body, &user) + fmt.Printf("status: %s", user.Status.Text) +} +/* Output: +status: Robot cars invade California, on orders from Google: +Google has been testing self-driving cars ... http://bit.ly/cbtpUN http://retwt.me/97p +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_15/webhello2.go b/eBook/exercises/chapter_15/webhello2.go new file mode 100755 index 0000000..b026a59 --- /dev/null +++ b/eBook/exercises/chapter_15/webhello2.go @@ -0,0 +1,24 @@ +// webhello2.go +package main + +import ( + "net/http" + "fmt" + "strings" +) + +func helloHandler(w http.ResponseWriter, r *http.Request) { + remPartOfURL := r.URL.Path[len("/hello/"):] //get everything after the /hello/ part of the URL + fmt.Fprintf(w, "Hello %s!", remPartOfURL) +} + +func shouthelloHandler(w http.ResponseWriter, r *http.Request) { + remPartOfURL := r.URL.Path[len("/shouthello/"):] //get everything after the /shouthello/ part of the URL + fmt.Fprintf(w, "Hello %s!", strings.ToUpper(remPartOfURL)) +} + +func main() { + http.HandleFunc("/hello/", helloHandler) + http.HandleFunc("/shouthello/", shouthelloHandler) + http.ListenAndServe("localhost:9999", nil) +} diff --git a/eBook/exercises/chapter_4/count_characters.go b/eBook/exercises/chapter_4/count_characters.go old mode 100644 new mode 100755 index 8df046b..1fc0ce2 --- a/eBook/exercises/chapter_4/count_characters.go +++ b/eBook/exercises/chapter_4/count_characters.go @@ -1,22 +1,22 @@ -package main - -import ( - "fmt" - "unicode/utf8" -) - -func main() { - // count number of characters: - str1 := "asSASA ddd dsjkdsjs dk" - fmt.Printf("The number of bytes in string str1 is %d\n",len(str1)) - fmt.Printf("The number of characters in string str1 is %d\n",utf8.RuneCountInString(str1)) - str2 := "asSASA ddd dsjkdsjsこん dk" - fmt.Printf("The number of bytes in string str2 is %d\n",len(str2)) - fmt.Printf("The number of characters in string str2 is %d",utf8.RuneCountInString(str2)) -} -/* Output: -The number of bytes in string str1 is 22 -The number of characters in string str1 is 22 -The number of bytes in string str2 is 28 -The number of characters in string str2 is 24 +package main + +import ( + "fmt" + "unicode/utf8" +) + +func main() { + // count number of characters: + str1 := "asSASA ddd dsjkdsjs dk" + fmt.Printf("The number of bytes in string str1 is %d\n",len(str1)) + fmt.Printf("The number of characters in string str1 is %d\n",utf8.RuneCountInString(str1)) + str2 := "asSASA ddd dsjkdsjsこん dk" + fmt.Printf("The number of bytes in string str2 is %d\n",len(str2)) + fmt.Printf("The number of characters in string str2 is %d",utf8.RuneCountInString(str2)) +} +/* Output: +The number of bytes in string str1 is 22 +The number of characters in string str1 is 22 +The number of bytes in string str2 is 28 +The number of characters in string str2 is 24 */ \ No newline at end of file diff --git a/eBook/exercises/chapter_4/divby0.go b/eBook/exercises/chapter_4/divby0.go old mode 100644 new mode 100755 index 5a87c36..36cfe6c --- a/eBook/exercises/chapter_4/divby0.go +++ b/eBook/exercises/chapter_4/divby0.go @@ -1,8 +1,8 @@ -package main - -func main() { - a, b := 10, 0 - c := a / b // panic: runtime error: integer divide by zero - - print(c) -} +package main + +func main() { + a, b := 10, 0 + c := a / b // panic: runtime error: integer divide by zero + + print(c) +} diff --git a/eBook/exercises/chapter_4/function_calls_function.go b/eBook/exercises/chapter_4/function_calls_function.go old mode 100644 new mode 100755 index f405dae..62711a4 --- a/eBook/exercises/chapter_4/function_calls_function.go +++ b/eBook/exercises/chapter_4/function_calls_function.go @@ -1,18 +1,18 @@ -package main - -var a string // global scope - -func main() { - a = "G" - print(a) - f1() -} -func f1() { - a := "O" // new local variable a, only scoped within f1() ! - print(a) - f2() -} -func f2() { - print(a) // global variable is taken -} +package main + +var a string // global scope + +func main() { + a = "G" + print(a) + f1() +} +func f1() { + a := "O" // new local variable a, only scoped within f1() ! + print(a) + f2() +} +func f2() { + print(a) // global variable is taken +} // GOG \ No newline at end of file diff --git a/eBook/exercises/chapter_4/global_scope.go b/eBook/exercises/chapter_4/global_scope.go old mode 100644 new mode 100755 index 9973d90..080a295 --- a/eBook/exercises/chapter_4/global_scope.go +++ b/eBook/exercises/chapter_4/global_scope.go @@ -1,19 +1,19 @@ -package main - -var a = "G" // global scope - -func main() { - n() - m() - n() -} - -func n() { - print(a) -} - -func m() { - a = "O" // simple assignment: global a gets a new value - print(a) -} +package main + +var a = "G" // global scope + +func main() { + n() + m() + n() +} + +func n() { + print(a) +} + +func m() { + a = "O" // simple assignment: global a gets a new value + print(a) +} // GOO \ No newline at end of file diff --git a/eBook/exercises/chapter_4/local_scope.go b/eBook/exercises/chapter_4/local_scope.go old mode 100644 new mode 100755 index 4f8bc03..785bf7e --- a/eBook/exercises/chapter_4/local_scope.go +++ b/eBook/exercises/chapter_4/local_scope.go @@ -1,17 +1,17 @@ -package main - -var a = "G" // global (package) scope - -func main() { - n() - m() - n() -} -func n() { - print(a) -} -func m() { - a := "O" // new local variable a is declared - print(a) -} +package main + +var a = "G" // global (package) scope + +func main() { + n() + m() + n() +} +func n() { + print(a) +} +func m() { + a := "O" // new local variable a is declared + print(a) +} // GOG \ No newline at end of file diff --git a/eBook/exercises/chapter_5/bitwise_complement.go b/eBook/exercises/chapter_5/bitwise_complement.go old mode 100644 new mode 100755 index c2c2c56..d113263 --- a/eBook/exercises/chapter_5/bitwise_complement.go +++ b/eBook/exercises/chapter_5/bitwise_complement.go @@ -1,22 +1,22 @@ -package main - -import "fmt" - -func main() { - for i:=0; i <= 10; i ++ { - fmt.Printf("the complement of %b is: %b\n", i, ^i) - } -} -/* Output: -the complement of 0 is: -1 -the complement of 1 is: -10 -the complement of 10 is: -11 -the complement of 11 is: -100 -the complement of 100 is: -101 -the complement of 101 is: -110 -the complement of 110 is: -111 -the complement of 111 is: -1000 -the complement of 1000 is: -1001 -the complement of 1001 is: -1010 -the complement of 1010 is: -1011 +package main + +import "fmt" + +func main() { + for i:=0; i <= 10; i ++ { + fmt.Printf("the complement of %b is: %b\n", i, ^i) + } +} +/* Output: +the complement of 0 is: -1 +the complement of 1 is: -10 +the complement of 10 is: -11 +the complement of 11 is: -100 +the complement of 100 is: -101 +the complement of 101 is: -110 +the complement of 110 is: -111 +the complement of 111 is: -1000 +the complement of 1000 is: -1001 +the complement of 1001 is: -1010 +the complement of 1010 is: -1011 */ \ No newline at end of file diff --git a/eBook/exercises/chapter_5/fizzbuzz.go b/eBook/exercises/chapter_5/fizzbuzz.go old mode 100644 new mode 100755 index 8b30374..ffa16dc --- a/eBook/exercises/chapter_5/fizzbuzz.go +++ b/eBook/exercises/chapter_5/fizzbuzz.go @@ -1,24 +1,24 @@ -package main - -import "fmt" - -const ( - FIZZ=3 - BUZZ=5 - FIZZBUZZ=15 -) - -func main() { - for i:=0; i <= 100; i++ { - switch { - case i%FIZZBUZZ==0: - fmt.Println("FizzBuzz") - case i%FIZZ==0: - fmt.Println("Fizz") - case i%BUZZ==0: - fmt.Println("Buzz") - default: - fmt.Println(i) - } - } +package main + +import "fmt" + +const ( + FIZZ=3 + BUZZ=5 + FIZZBUZZ=15 +) + +func main() { + for i:=0; i <= 100; i++ { + switch { + case i%FIZZBUZZ==0: + fmt.Println("FizzBuzz") + case i%FIZZ==0: + fmt.Println("Fizz") + case i%BUZZ==0: + fmt.Println("Buzz") + default: + fmt.Println(i) + } + } } \ No newline at end of file diff --git a/eBook/exercises/chapter_5/for_character.go b/eBook/exercises/chapter_5/for_character.go old mode 100644 new mode 100755 index 98979a4..2653f38 --- a/eBook/exercises/chapter_5/for_character.go +++ b/eBook/exercises/chapter_5/for_character.go @@ -1,17 +1,17 @@ -package main - -func main() { - // 1 - use 2 nested for loops - for i:=1; i <= 25; i++ { - for j:=1; j <=i; j++ { - print("G") - } - println() - } - // 2 - use only one for loop and string concatenation - str := "G" - for i:=1; i <= 25; i++ { - println(str) - str += "G" - } +package main + +func main() { + // 1 - use 2 nested for loops + for i:=1; i <= 25; i++ { + for j:=1; j <=i; j++ { + print("G") + } + println() + } + // 2 - use only one for loop and string concatenation + str := "G" + for i:=1; i <= 25; i++ { + println(str) + str += "G" + } } \ No newline at end of file diff --git a/eBook/exercises/chapter_5/for_loop.go b/eBook/exercises/chapter_5/for_loop.go old mode 100644 new mode 100755 index b7eeb95..a484f65 --- a/eBook/exercises/chapter_5/for_loop.go +++ b/eBook/exercises/chapter_5/for_loop.go @@ -1,16 +1,16 @@ -package main - -import "fmt" - -func main() { - // 1: - for i:=0; i < 15; i++ { - fmt.Printf("The counter is at %d\n", i) - } - // 2: - i := 0 -START: - fmt.Printf("The counter is at %d\n", i) - i++ - if i < 15 { goto START } +package main + +import "fmt" + +func main() { + // 1: + for i:=0; i < 15; i++ { + fmt.Printf("The counter is at %d\n", i) + } + // 2: + i := 0 +START: + fmt.Printf("The counter is at %d\n", i) + i++ + if i < 15 { goto START } } \ No newline at end of file diff --git a/eBook/exercises/chapter_5/i_undefined.go b/eBook/exercises/chapter_5/i_undefined.go old mode 100644 new mode 100755 index d4b47e9..d0c8840 --- a/eBook/exercises/chapter_5/i_undefined.go +++ b/eBook/exercises/chapter_5/i_undefined.go @@ -1,14 +1,14 @@ -// i_undefined.go -package main - -import ( - "fmt" -) - -func main() { - var i int - for i=0; i<10; i++ { - fmt.Printf("%v\n", i) - } - fmt.Printf("%v\n", i) //<-- compile error: undefined i -} +// i_undefined.go +package main + +import ( + "fmt" +) + +func main() { + var i int + for i=0; i<10; i++ { + fmt.Printf("%v\n", i) + } + fmt.Printf("%v\n", i) //<-- compile error: undefined i +} diff --git a/eBook/exercises/chapter_5/multiple_for.go b/eBook/exercises/chapter_5/multiple_for.go old mode 100644 new mode 100755 index 2e7f3d9..b9b0649 --- a/eBook/exercises/chapter_5/multiple_for.go +++ b/eBook/exercises/chapter_5/multiple_for.go @@ -1,17 +1,17 @@ -// multiple_for.go -package main - -import "fmt" - -func main() { - //multiple initialization; a consolidated bool expression with && and ||; multiple ‘incrementation’ - for i, j, s := 0, 5, "a"; i < 3 && j < 100 && s != "aaaaa"; i, j, s = i+1, - j+1, s + "a" { - fmt.Println("Value of i, j, s:", i, j, s) - } -} -/* Output: -Value of i, j, s: 0 5 a -Value of i, j, s: 1 6 aa -Value of i, j, s: 2 7 aaa +// multiple_for.go +package main + +import "fmt" + +func main() { + //multiple initialization; a consolidated bool expression with && and ||; multiple ‘incrementation’ + for i, j, s := 0, 5, "a"; i < 3 && j < 100 && s != "aaaaa"; i, j, s = i+1, + j+1, s + "a" { + fmt.Println("Value of i, j, s:", i, j, s) + } +} +/* Output: +Value of i, j, s: 0 5 a +Value of i, j, s: 1 6 aa +Value of i, j, s: 2 7 aaa */ \ No newline at end of file diff --git a/eBook/exercises/chapter_5/rectangle_stars.go b/eBook/exercises/chapter_5/rectangle_stars.go old mode 100644 new mode 100755 index bb5def0..a5eb7cb --- a/eBook/exercises/chapter_5/rectangle_stars.go +++ b/eBook/exercises/chapter_5/rectangle_stars.go @@ -1,26 +1,26 @@ -// rectangle_stars.go -package main - -import "fmt" - -func main() { - w, h := 20, 10 - for y := 0; y < h; y++ { - for x := 0; x < w; x++ { - fmt.Print("*") - } - fmt.Println() - } -} -/* Output: -******************** -******************** -******************** -******************** -******************** -******************** -******************** -******************** -******************** -******************** -*/ +// rectangle_stars.go +package main + +import "fmt" + +func main() { + w, h := 20, 10 + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + fmt.Print("*") + } + fmt.Println() + } +} +/* Output: +******************** +******************** +******************** +******************** +******************** +******************** +******************** +******************** +******************** +******************** +*/ diff --git a/eBook/exercises/chapter_5/season.go b/eBook/exercises/chapter_5/season.go old mode 100644 new mode 100755 index 1a21bed..ba200d5 --- a/eBook/exercises/chapter_5/season.go +++ b/eBook/exercises/chapter_5/season.go @@ -1,17 +1,17 @@ -package main - -import "fmt" - -func main() { - fmt.Printf(Season(3)) -} - -func Season(month int) string { - switch month { - case 12,1,2: return "Winter" - case 3,4,5: return "Spring" - case 6,7,8: return "Summer" - case 9,10,11: return "Autumn" - } - return "Season unknown" +package main + +import "fmt" + +func main() { + fmt.Printf(Season(3)) +} + +func Season(month int) string { + switch month { + case 12,1,2: return "Winter" + case 3,4,5: return "Spring" + case 6,7,8: return "Summer" + case 9,10,11: return "Autumn" + } + return "Season unknown" } \ No newline at end of file diff --git a/eBook/exercises/chapter_6/10to1_recursive.go b/eBook/exercises/chapter_6/10to1_recursive.go new file mode 100755 index 0000000..fa0d40b --- /dev/null +++ b/eBook/exercises/chapter_6/10to1_recursive.go @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + printrec(1) +} + +func printrec(i int) { + if i>10 { return } + printrec(i+1) + fmt.Printf("%d ", i) +} \ No newline at end of file diff --git a/eBook/exercises/chapter_6/compose.go b/eBook/exercises/chapter_6/compose.go new file mode 100755 index 0000000..dfaa491 --- /dev/null +++ b/eBook/exercises/chapter_6/compose.go @@ -0,0 +1,17 @@ +// compose.go +package main + +import ( + "fmt" + "math" +) + +func Compose(f, g func(x float64) float64) func(x float64) float64 { + return func(x float64) float64 { // closure + return f(g(x)) + } +} + +func main() { + fmt.Print(Compose(math.Sin, math.Cos)(0.5)) // output: 0.7691963548410085 +} diff --git a/eBook/exercises/chapter_6/error_returnval.go b/eBook/exercises/chapter_6/error_returnval.go old mode 100644 new mode 100755 index 87a3ed2..6ef8cc7 --- a/eBook/exercises/chapter_6/error_returnval.go +++ b/eBook/exercises/chapter_6/error_returnval.go @@ -1,43 +1,56 @@ -package main - -import ( - "errors" - "fmt" - "math" -) - -func MySqrt1(a float64) (Sqrt float64, Err error) { - if a < 0 { - Err = errors.New("Fuck!") - Sqrt = 0 - return - } - Sqrt = math.Sqrt(a) - return -} - -func MySqrt2(a float64) (float64, error) { - var Sqrt float64 - var Err error - if a < 0 { - Err = errors.New("Fuck!") - Sqrt = 0 - return Sqrt, Err - } - Sqrt = math.Sqrt(a) - return Sqrt, Err -} - -func main() { - var a float64 = 99.99 - var b float64 = -99.99 - Sqrt11, Err11 := MySqrt1(a) - Sqrt12, Err12 := MySqrt1(b) - Sqrt21, Err21 := MySqrt2(a) - Sqrt22, Err22 := MySqrt2(b) - - fmt.Println(Sqrt11, Err11) - fmt.Println(Sqrt12, Err12) - fmt.Println(Sqrt21, Err21) - fmt.Println(Sqrt22, Err22) -} +// error_returnval.go +package main + +import ( + "errors" + "fmt" + "math" +) + +func main() { + fmt.Print("First example with -1: ") + ret1, err1 := MySqrt(-1) + if err1 != nil { + fmt.Println("Error! Return values are: ", ret1, err1) + } else { + fmt.Println("It's ok! Return values are: ", ret1, err1) + } + + fmt.Print("Second example with 5: ") + //you could also write it like this + if ret2, err2 := MySqrt(5); err2 != nil { + fmt.Println("Error! Return values are: ", ret2, err2) + } else { + fmt.Println("It's ok! Return values are: ", ret2, err2) + } + // named return variables: + fmt.Println(MySqrt2(5)) +} + +func MySqrt(f float64) (float64, error) { + //return an error as second parameter if invalid input + if (f < 0) { + return float64(math.NaN()), errors.New("I won't be able to do a sqrt of negative number!") + } + //otherwise use default square root function + return math.Sqrt(f), nil +} + +//name the return variables - by default it will have 'zero-ed' values i.e. numbers are 0, string is empty, etc. +func MySqrt2(f float64) (ret float64, err error) { + if (f < 0) { + //then you can use those variables in code + ret = float64(math.NaN()) + err = errors.New("I won't be able to do a sqrt of negative number!") + } else { + ret = math.Sqrt(f) + //err is not assigned, so it gets default value nil + } + //automatically return the named return variables ret and err + return +} +/* Output: +First example with -1: Error! Return values are: NaN I won't be able to do a sqrt of negative number! +Second example with 5: It's ok! Return values are: 2.23606797749979 +2.23606797749979 +*/ diff --git a/eBook/exercises/chapter_6/factorial.go b/eBook/exercises/chapter_6/factorial.go new file mode 100755 index 0000000..eeaac81 --- /dev/null +++ b/eBook/exercises/chapter_6/factorial.go @@ -0,0 +1,34 @@ +// factorial.go +package main + +import ( + "fmt" +) + +func main() { + for i := uint64(0); i < uint64(30); i++ { + fmt.Printf("Factorial of %d is %d\n", i, Factorial(i)) + } +} + +/* unnamed return variables: +func Factorial(n uint64) uint64 { + if n > 0 { + return n * Factorial(n-1) + } + return 1 +} +*/ + +// named return variables: +func Factorial(n uint64) (fac uint64) { + fac = 1 + if n > 0 { + fac = n * Factorial(n-1) + return + } + return +} + +// int: correct results till 12! +// uint64: correct results till 21! diff --git a/eBook/exercises/chapter_6/fibonacci2.go b/eBook/exercises/chapter_6/fibonacci2.go new file mode 100755 index 0000000..6fde9be --- /dev/null +++ b/eBook/exercises/chapter_6/fibonacci2.go @@ -0,0 +1,24 @@ +package main + +import "fmt" + +func main() { + pos := 4 + result, pos := fibonacci(pos) + fmt.Printf("the %d-th fibonacci number is: %d\n", pos, result) + pos = 10 + result, pos = fibonacci(pos) + fmt.Printf("the %d-th fibonacci number is: %d\n", pos, result) +} + +func fibonacci(n int) (val, pos int) { + if n <= 1 { + val = 1 + } else { + v1, _ := fibonacci(n-1) + v2, _ := fibonacci(n-2) + val = v1 + v2 + } + pos = n + return +} diff --git a/eBook/exercises/chapter_6/fibonacci_closure.go b/eBook/exercises/chapter_6/fibonacci_closure.go new file mode 100755 index 0000000..cc29b96 --- /dev/null +++ b/eBook/exercises/chapter_6/fibonacci_closure.go @@ -0,0 +1,20 @@ +package main + +// fib returns a function that returns +// successive Fibonacci numbers. +func fib() func() int { + a, b := 1, 1 + return func() int { + a, b = b, a+b + return b + } +} + +func main() { + f := fib() + // Function calls are evaluated left-to-right. + // println(f(), f(), f(), f(), f()) + for i:=0; i<=9; i++ { + println(i+2, f() ) + } +} diff --git a/eBook/exercises/chapter_6/function_filter2.go b/eBook/exercises/chapter_6/function_filter2.go new file mode 100755 index 0000000..30a2dd7 --- /dev/null +++ b/eBook/exercises/chapter_6/function_filter2.go @@ -0,0 +1,37 @@ +// function_filter2.go +package main + +import "fmt" + +type flt func(int) bool + +// func isEven(n int) bool { if n%2 == 0 { return true }; return false } +func isEven(n int) bool { + if n%2 == 0 { + return true + } + return false +} + +func filter(sl []int, f flt) (yes, no []int) { + for _, val := range sl { + if f(val) { + yes = append(yes, val) + } else { + no = append(no, val) + } + } + return +} + +func main() { + slice := []int{1, 2, 3, 4, 5, 7} + fmt.Println("slice = ", slice) + even, odd := filter(slice, isEven) + fmt.Println("The even elements of slice are: ", even) + fmt.Println("The odd elements of slice are: ", odd) +} + +/* + +*/ diff --git a/eBook/exercises/chapter_6/lambda_value.go b/eBook/exercises/chapter_6/lambda_value.go new file mode 100755 index 0000000..0b0d803 --- /dev/null +++ b/eBook/exercises/chapter_6/lambda_value.go @@ -0,0 +1,18 @@ +// lambda_value.go +package main + +import ( + "fmt" +) + +func main() { + fv := func() { + fmt.Println("Hello World!") + } + fv() + fmt.Printf("The type of fv is %T", fv) +} +/* Output: +Hello World! +The type of fv is func() +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_6/mult_returnval.go b/eBook/exercises/chapter_6/mult_returnval.go old mode 100644 new mode 100755 index b6e62da..fbdde34 --- a/eBook/exercises/chapter_6/mult_returnval.go +++ b/eBook/exercises/chapter_6/mult_returnval.go @@ -1,27 +1,24 @@ -package main - -import "fmt" - -func MultReturn1(a, b int) (Sum, Mul, Dif int) { - Sum = a + b - Mul = a * b - Dif = a - b - return -} - -func MultReturn2(a, b int) (int, int, int) { - Sum := a + b - Mul := a * b - Dif := a - b - return Sum, Mul, Dif - -} - -func main() { - a := 100 - b := 78 - Sum1, Mul1, Dif1 := MultReturn1(a, b) - Sum2, Mul2, Dif2 := MultReturn2(a, b) - fmt.Println("Named:", Sum1, Mul1, Dif1) - fmt.Println("Unnamed:", Sum2, Mul2, Dif2) -} +// mult_returnval.go +package main + +import ( + "fmt" +) + +func SumProductDiff(i, j int) (int, int, int) { + return i+j, i*j, i-j +} + +func SumProductDiffN(i, j int) (s int, p int, d int) { + s, p, d = i+j, i*j, i-j + return +} + +func main() { + sum, prod, diff := SumProductDiff(3,4) + fmt.Println("Sum:", sum, "| Product:",prod, "| Diff:", diff) + sum, prod, diff = SumProductDiffN(3,4) + fmt.Println("Sum:", sum, "| Product:",prod, "| Diff:", diff) +} +// Sum: 7 | Product: 12 | Diff: -1 +// Sum: 7 | Product: 12 | Diff: -1 \ No newline at end of file diff --git a/eBook/exercises/chapter_6/strings_map.go b/eBook/exercises/chapter_6/strings_map.go new file mode 100755 index 0000000..ea82d8a --- /dev/null +++ b/eBook/exercises/chapter_6/strings_map.go @@ -0,0 +1,13 @@ +// strings_map.go +package main + +import ( + "fmt" + "strings" +) + +func main() { + asciiOnly := func(c rune) rune { if c > 127 { return ' ' }; return c } + fmt.Println(strings.Map(asciiOnly, "Jérôme Österreich")) +} +// J r me sterreich \ No newline at end of file diff --git a/eBook/exercises/chapter_6/varargs.go b/eBook/exercises/chapter_6/varargs.go new file mode 100755 index 0000000..0c2eb70 --- /dev/null +++ b/eBook/exercises/chapter_6/varargs.go @@ -0,0 +1,23 @@ +// Q10_varargs.go +package main + +import ( + "fmt" +) + +func main() { + printInts() + println() + printInts(2, 3) + println() + printInts(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) +} + +func printInts(list ...int) { +// for i:=0; i sl[i+1] { + sl[i], sl[i+1] = sl[i+1], sl[i] + } + } + } +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/fibonacci_array.go b/eBook/exercises/chapter_7/fibonacci_array.go new file mode 100755 index 0000000..50c065b --- /dev/null +++ b/eBook/exercises/chapter_7/fibonacci_array.go @@ -0,0 +1,18 @@ +package main + +import "fmt" + +var fibs [50]int64 + +func main() { + fibs[0] = 1 + fibs[1] = 1 + + for i:= 2; i < 50; i++ { + fibs[i] = fibs[i-1] + fibs[i-2] + } + + for i:=0; i < 50; i++ { + fmt.Printf("The %d-th Fibonacci number is: %d\n", i, fibs[i]) + } +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/fibonacci_funcarray.go b/eBook/exercises/chapter_7/fibonacci_funcarray.go new file mode 100755 index 0000000..b5cd653 --- /dev/null +++ b/eBook/exercises/chapter_7/fibonacci_funcarray.go @@ -0,0 +1,22 @@ +package main + +import "fmt" + +var term = 15 + +func main() { + result := fibarray(term) + for ix, fib := range result { + fmt.Printf("The %d-th Fibonacci number is: %d\n", ix, fib) + } +} + +func fibarray(term int) []int { + farr := make([]int, term) + farr[0], farr[1] = 1, 1 + + for i:= 2; i < term; i++ { + farr[i] = farr[i-1] + farr[i-2] + } + return farr +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/filter_slice.go b/eBook/exercises/chapter_7/filter_slice.go new file mode 100755 index 0000000..59ff196 --- /dev/null +++ b/eBook/exercises/chapter_7/filter_slice.go @@ -0,0 +1,32 @@ +// filter_slice.go +package main + +import ( + "fmt" +) + +func main() { + s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + s = Filter(s, even) + fmt.Println(s) +} + +// Filter returns a new slice holding only +// the elements of s that satisfy f() +func Filter(s []int, fn func(int) bool) []int { + var p []int // == nil + for _, i := range s { + if fn(i) { + p = append(p, i) + } + } + return p +} + +func even(n int) bool { + if n%2 == 0 { + return true + } + return false +} +/* [0 2 4 6 8] */ diff --git a/eBook/exercises/chapter_7/for_array.go b/eBook/exercises/chapter_7/for_array.go new file mode 100755 index 0000000..b93c3af --- /dev/null +++ b/eBook/exercises/chapter_7/for_array.go @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + var arr [15]int + for i:=0; i < 15; i++ { + arr[i] = i + } + fmt.Println(arr) // [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] + + +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/insert_slice.go b/eBook/exercises/chapter_7/insert_slice.go new file mode 100755 index 0000000..5d35d31 --- /dev/null +++ b/eBook/exercises/chapter_7/insert_slice.go @@ -0,0 +1,23 @@ +// insert_slice.go +package main + +import ( + "fmt" +) + +func main() { + s := []string{"M", "N", "O", "P", "Q", "R"} + in := []string{"A", "B", "C"} + res := InsertStringSlice(s, in, 0) // at the front + fmt.Println(res) // [A B C M N O P Q R] + res = InsertStringSlice(s, in, 3) // [M N O A B C P Q R] + fmt.Println(res) +} + +func InsertStringSlice(slice, insertion []string, index int) []string { + result := make([]string, len(slice) + len(insertion)) + at := copy(result, slice[:index]) + at += copy(result[at:], insertion) + copy(result[at:], slice[index:]) + return result +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/magnify_slice.go b/eBook/exercises/chapter_7/magnify_slice.go new file mode 100755 index 0000000..4b6e13c --- /dev/null +++ b/eBook/exercises/chapter_7/magnify_slice.go @@ -0,0 +1,25 @@ +package main + +import "fmt" + +var s []int + +func main() { + s = []int{1, 2, 3} + fmt.Println("The length of s before enlarging is:", len(s)) + fmt.Println(s) + s = enlarge(s, 5) + fmt.Println("The length of s after enlarging is:", len(s)) + fmt.Println(s) +} + +func enlarge(s []int, factor int) []int { + ns := make([]int, len(s) * factor) + // fmt.Println("The length of ns is:", len(ns)) + copy(ns, s) + //fmt.Println(ns) + s = ns + //fmt.Println(s) + //fmt.Println("The length of s after enlarging is:", len(s)) + return s +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/map_function.go b/eBook/exercises/chapter_7/map_function.go new file mode 100755 index 0000000..30b3ab9 --- /dev/null +++ b/eBook/exercises/chapter_7/map_function.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +func main() { + list := []int{0, 1, 2, 3, 4, 5, 6, 7} + mf := func(i int) int { + return i * 10 + } + /* + result := mapFunc(mf, list) + for _, v := range result { + fmt.Println(v) + } + */ + println() + // shorter: + fmt.Printf("%v", mapFunc(mf, list) ) +} + +func mapFunc(mf func(int) int, list []int) ([]int) { + result := make([]int, len(list)) + for ix, v := range list { + result[ix] = mf(v) + } + /* + for ix := 0; ix max { + max = v + } + } + return +} + +func minSlice(sl [] int) (min int) { + // min = int(^uint(0) >> 1) + min = math.MaxInt32 + for _, v := range sl { + if v < min { + min = v + } + } + return +} +/* Output: +The maximum is 643 +The minimum is 2 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_7/remove_slice.go b/eBook/exercises/chapter_7/remove_slice.go new file mode 100755 index 0000000..d5c93d1 --- /dev/null +++ b/eBook/exercises/chapter_7/remove_slice.go @@ -0,0 +1,19 @@ +// remove_slice.go +package main + +import ( + "fmt" +) + +func main() { + s := []string{"M", "N", "O", "P", "Q", "R"} + res := RemoveStringSlice(s, 2, 4) + fmt.Println(res) // [M N Q R] +} + +func RemoveStringSlice(slice []string, start, end int) []string { + result := make([]string, len(slice) - (end - start)) + at := copy(result, slice[:start]) + copy(result[at:], slice[end:]) + return result +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/split_string.go b/eBook/exercises/chapter_7/split_string.go new file mode 100755 index 0000000..24634fb --- /dev/null +++ b/eBook/exercises/chapter_7/split_string.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func main() { + str := "Google" + for i:=0; i <= len(str); i++ { + a, b := Split(str, i) + fmt.Printf("The string %s split at position %d is: %s / %s\n", str, i, a, b) + } + +} + +func Split(s string, pos int) (string, string) { + return s[0:pos], s[pos:] +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/string_reverse.go b/eBook/exercises/chapter_7/string_reverse.go new file mode 100755 index 0000000..053fc2d --- /dev/null +++ b/eBook/exercises/chapter_7/string_reverse.go @@ -0,0 +1,41 @@ +package main + +import "fmt" + +func reverse(s string) string { + runes := []rune(s) + n, h := len(runes), len(runes)/2 + for i:= 0; i < h; i ++ { + runes[i], runes[n-1-i] = runes[n-1-i], runes[i] + } + return string(runes) +} + +func main() { +// reverse a string: + str := "Google" + sl := []byte(str) + var rev [100]byte + j := 0 + for i:=len(sl)-1; i >= 0; i-- { + rev[j] = sl[i] + j++ + } + str_rev := string(rev[:]) + fmt.Printf("The reversed string is -%s-\n", str_rev) +// variant: "in place" using swapping + str2 := "Google" + sl2 := []byte(str2) + for i, j := 0, len(sl2) - 1; i < j; i, j = i+1, j-1 { + sl2[i], sl2[j] = sl2[j], sl2[i] + } + fmt.Printf("The reversed string is -%s-\n", string(sl2)) +// variant: using [] int for runes (necessary for Unicode-strings!): + s := "My Test String!" + fmt.Println(s, " --> ", reverse(s)) +} +/* Output: +The reversed string is -elgooG- +The reversed string is -elgooG- +My Test String! --> !gnirtS tseT yM +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_7/string_split2.go b/eBook/exercises/chapter_7/string_split2.go new file mode 100755 index 0000000..77e812e --- /dev/null +++ b/eBook/exercises/chapter_7/string_split2.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + str := "Google" + str2 := Split2(str) + fmt.Printf("The string %s transformed is: %s\n", str, str2) +} + +func Split2(s string) string { + mid := len(s) / 2 + return s[mid:] + s[:mid] +} +// Output: The string Google transformed is: gleGoo \ No newline at end of file diff --git a/eBook/exercises/chapter_7/sum_array.go b/eBook/exercises/chapter_7/sum_array.go new file mode 100755 index 0000000..d1cb723 --- /dev/null +++ b/eBook/exercises/chapter_7/sum_array.go @@ -0,0 +1,39 @@ +// leaving out the length 4 in [4] uses slice instead of an array +// which is generally better for performance +package main + +import "fmt" + +func main() { + // var a = [4]float32 {1.0,2.0,3.0,4.0} + var a = []float32 {1.0,2.0,3.0,4.0} + fmt.Printf("The sum of the array is: %f\n", Sum(a)) + var b = []int {1, 2, 3, 4, 5} + sum, average := SumAndAverage(b) + fmt.Printf("The sum of the array is: %d, and the average is: %f", sum, average) +} + +/* +func Sum(a [4]float32) (sum float32) { + for _, item := range a { + sum += item + } + return +} +*/ + +func Sum(a []float32) (sum float32) { + for _, item := range a { + sum += item + } + return +} + +func SumAndAverage (a []int) (int, float32) { + sum := 0 + for _, item := range a { + sum += item + } + return sum, float32(sum/len(a)) +} + diff --git a/eBook/exercises/chapter_7/uniq.go b/eBook/exercises/chapter_7/uniq.go new file mode 100755 index 0000000..b4c2aed --- /dev/null +++ b/eBook/exercises/chapter_7/uniq.go @@ -0,0 +1,23 @@ +// Q29_uniq.go +package main + +import ( + "fmt" +) + +var arr []byte = []byte{'a','b','a','a','a','c','d','e','f','g'} + +func main() { + arru := make([]byte,len(arr)) // this will contain the unique items + ixu := 0 // index in arru + tmp := byte(0) + for _, val := range arr { + if val!=tmp { + arru[ixu] = val + fmt.Printf("%c ", arru[ixu]) + ixu++ + } + tmp = val + } + // fmt.Println(arru) +} diff --git a/eBook/exercises/chapter_8/map_days.go b/eBook/exercises/chapter_8/map_days.go new file mode 100755 index 0000000..7c4fa70 --- /dev/null +++ b/eBook/exercises/chapter_8/map_days.go @@ -0,0 +1,35 @@ +// map_days.go +package main + +import ( + "fmt" +) + +var Days = map[int]string{1:"monday", + 2:"tuesday", + 3: "wednesday", + 4: "thursday", + 5: "friday", + 6: "saturday", + 7: "sunday"} + +func main() { + fmt.Println(Days) + // fmt.Printf("%v", Days) + flagHolliday := false + for k, v := range Days { + if v == "thursday" || v == "holliday" { + fmt.Println(v, " is the ", k , "th day in the week") + if v == "holliday" { + flagHolliday = true + } + } + } + if !flagHolliday { + fmt.Println("holliday is not a day!") + } +} +/* Output: +thursday is the 4 th day in the week +holliday is not a day! +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_8/map_drinks.go b/eBook/exercises/chapter_8/map_drinks.go new file mode 100755 index 0000000..e048055 --- /dev/null +++ b/eBook/exercises/chapter_8/map_drinks.go @@ -0,0 +1,73 @@ +// map_drinks.go +package main + +import ( + "fmt" + "sort" +) + +func main() { + drinks := map[string]string{ + "beer": "bière", + "wine": "vin", + "water": "eau", + "coffee": "café", + "thea": "thé"} + sdrinks := make([]string, len(drinks)) + ix := 0 + + fmt.Printf("The following drinks are available:\n") + for eng := range drinks { + sdrinks[ix] = eng + ix++ + fmt.Println(eng) + } + + fmt.Println("") + for eng, fr := range drinks { + fmt.Printf("The french for %s is %s\n", eng, fr) + } + + // SORTING: + fmt.Println("") + fmt.Println("Now the sorted output:") + sort.Strings(sdrinks) + + fmt.Printf("The following sorted drinks are available:\n") + for _, eng := range sdrinks { + fmt.Println(eng) + } + + fmt.Println("") + for _, eng := range sdrinks { + fmt.Printf("The french for %s is %s\n", eng, drinks[eng]) + } +} +/* Output: +The following drinks are available: +wine +beer +water +coffee +thea + +The french for wine is vin +The french for beer is bière +The french for water is eau +The french for coffee is café +The french for thea is thé + +Now the sorted output: +The following sorted drinks are available: +beer +coffee +thea +water +wine + +The french for beer is bière +The french for coffee is café +The french for thea is thé +The french for water is eau +The french for wine is vin +*/ diff --git a/eBook/exercises/chapter_9/dlinked_list.go b/eBook/exercises/chapter_9/dlinked_list.go new file mode 100755 index 0000000..10eaff2 --- /dev/null +++ b/eBook/exercises/chapter_9/dlinked_list.go @@ -0,0 +1,28 @@ +// Q20_linked_list.go +package main + +import ( + "fmt" + "container/list" +) + +func main() { + lst := list.New() + lst.PushBack(100) + lst.PushBack(101) + lst.PushBack(102) + // fmt.Println("Here is the double linked list:\n", lst) + for e := lst.Front(); e != nil; e = e.Next() { + // fmt.Println(e) + fmt.Println(e.Value) + } +} +/* Example output: +&{0x12542bc0 0x12547590 1} +&{0x12542ba0 0x12542be0 0x12547590 2} +&{ 0x12542bc0 0x12547590 4} + +100 +101 +102 +*/ diff --git a/eBook/exercises/chapter_9/even/even.go b/eBook/exercises/chapter_9/even/even.go new file mode 100755 index 0000000..142da1b --- /dev/null +++ b/eBook/exercises/chapter_9/even/even.go @@ -0,0 +1,6 @@ +// even.go +package even + +func Even(i int) bool { // exported function + return i%2 == 0 +} diff --git a/eBook/exercises/chapter_9/fibo/fibonacci.go b/eBook/exercises/chapter_9/fibo/fibonacci.go new file mode 100755 index 0000000..e95f900 --- /dev/null +++ b/eBook/exercises/chapter_9/fibo/fibonacci.go @@ -0,0 +1,33 @@ +package fibo + +/* +func Fibonacci(n int) (res int) { + if n <= 1 { + res = 1 + } else { + res = Fibonacci(n-1) + Fibonacci(n-2) + } + return +} +*/ +// accepts a general operation op: +func Fibonacci(op string, n int) (res int) { + if n <= 1 { + switch op { + case "+": + res = 1 + case "*": + res = 2 + default: res = 0 + } + } else { + switch op { + case "+": + res = Fibonacci(op, n-1) + Fibonacci(op, n-2) + case "*": + res = Fibonacci(op, n-1) * Fibonacci(op, n-2) + default: res = 0 + } + } + return +} diff --git a/eBook/exercises/chapter_9/greetings/greetings.go b/eBook/exercises/chapter_9/greetings/greetings.go new file mode 100755 index 0000000..c7a72e0 --- /dev/null +++ b/eBook/exercises/chapter_9/greetings/greetings.go @@ -0,0 +1,27 @@ +package greetings + +import "time" + +func GoodDay(name string) string { + return "Good Day " + name +} + +func GoodNight(name string) string{ + return "Good Night " + name +} + +func IsAM() bool { + localTime := time.Now() + return localTime.Hour() <= 12 +} + +func IsAfternoon() bool { + localTime := time.Now() + return localTime.Hour() <= 18 +} + +func IsEvening() bool { + localTime := time.Now() + return localTime.Hour() <= 22 +} + diff --git a/eBook/exercises/chapter_9/main_fibo.go b/eBook/exercises/chapter_9/main_fibo.go new file mode 100755 index 0000000..b92423d --- /dev/null +++ b/eBook/exercises/chapter_9/main_fibo.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "./fibo/fibo" +) + +var nextFibo int +var op string + +func main() { + /* + result := 0 + for i:=0; i <= 10; i++ { + result = fibo.Fibonacci(i) + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + } + */ + op = "+" + calls() + fmt.Println("Change of operation from + to *") + nextFibo = 0 + op = "*" + calls() +} + +func calls() { + next() + fmt.Println("...") + next() + fmt.Println("...") + next() + fmt.Println("...") + next() +} + +func next() { + result := 0 + nextFibo++ + result = fibo.Fibonacci(op, nextFibo) + fmt.Printf("fibonacci(%d) is: %d\n", nextFibo, result) +} +/* ***************************************************************** +Output is: +fibonacci(1) is: 1 +... +fibonacci(2) is: 2 +... +fibonacci(3) is: 3 +... +fibonacci(4) is: 5 +Change of operation from + to * +fibonacci(1) is: 2 +... +fibonacci(2) is: 4 +... +fibonacci(3) is: 8 +... +fibonacci(4) is: 32 +********************************************************************/ + + diff --git a/eBook/exercises/chapter_9/main_greetings.go b/eBook/exercises/chapter_9/main_greetings.go new file mode 100755 index 0000000..bd29198 --- /dev/null +++ b/eBook/exercises/chapter_9/main_greetings.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "./greetings/greetings" +) + +func main() { + name := "James" + fmt.Println(greetings.GoodDay(name)) + fmt.Println(greetings.GoodNight(name)) + + if greetings.IsAM() { + fmt.Println("Good morning", name) + } else if greetings.IsAfternoon(){ + fmt.Println("Good afternoon", name) + } else if greetings.IsEvening(){ + fmt.Println("Good evening", name) + } else { + fmt.Println("Good night", name) + } +} diff --git a/eBook/exercises/chapter_9/main_oddeven.go b/eBook/exercises/chapter_9/main_oddeven.go new file mode 100755 index 0000000..a3e8991 --- /dev/null +++ b/eBook/exercises/chapter_9/main_oddeven.go @@ -0,0 +1,13 @@ +// test_oddeven.go +package main + +import ( + "fmt" + "./even/even" +) + +func main() { + for i:=0; i<=100; i++ { + fmt.Printf("Is the integer %d even? %v\n", i, even.Even(i)) + } +} diff --git a/eBook/exercises/chapter_9/size_int.go b/eBook/exercises/chapter_9/size_int.go new file mode 100755 index 0000000..2fd9f88 --- /dev/null +++ b/eBook/exercises/chapter_9/size_int.go @@ -0,0 +1,14 @@ +// size_int.go +package main + +import ( + "fmt" + "unsafe" +) + +func main() { + var i int = 10 + size := unsafe.Sizeof(i) + fmt.Println("The size of an int is: ", size) +} +// The size of an int is: 4