update book code

This commit is contained in:
Unknwon
2015-03-03 12:25:25 -05:00
parent b8c82ba4e5
commit eab1d98ba8
465 changed files with 15392 additions and 1572 deletions

View File

@@ -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)
}

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
}

View File

@@ -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
*/

View File

@@ -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)
}

View File

@@ -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
*/

View File

@@ -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)
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}

View File

@@ -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
}

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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:
}
}
}