7 May 2014
:=
for assignment and type inferencefor
(includes range loops)break
in
switch
)*Have native threads but use a global interpreter lock.
package main
import (
"fmt"
"time"
)
func hello(s string) {
for {
fmt.Println("hello", s)
time.Sleep(time.Second / 10)
}
}
func main() {
go hello("world")
time.Sleep(time.Second)
}
"hello world"
about 10 times.main
finishes.Basic channel communication:
func other(c chan string) {
c <- "Hello."
}
func main() {
c := make(chan string)
go other(c)
value := <-c
fmt.Println(value)
}
func main() {
c := make(chan string)
c <- "Hello." // Deadlock here.
value := <-c
fmt.Println(value)
}
throw: all goroutines are asleep - deadlock!
make
.c := make(chan string, 10)
func pass(from, to chan int) {
to <- 1 + <-from
}
func main() {
length := 1000000
var start = make(chan int)
var a = start
var b chan int
for i := 0; i < length; i++ {
b = make(chan int)
go pass(a, b)
a = b
}
start <- 0
fmt.Println(<-b)
}
time ./daisy-chain
1000000
real 0m2.225s
user 0m1.232s
sys 0m0.980s
func worker(id int, c chan string) {
for {
fmt.Println("worker", id, <-c)
}
}
func main() {
c := make(chan string)
go worker(0, c)
go worker(1, c)
for i := 0; i < 10; i++ {
c <- fmt.Sprintf("message %d", i)
}
}
worker 0 message 0
worker 0 message 2
worker 1 message 1
worker 0 message 3
worker 0 message 5
worker 1 message 4
worker 0 message 6
worker 1 message 7
worker 0 message 8
switch
statement, except cases refer to receive
or send operations.select {
case v := <-c1:
fmt.Println("received:", v);
case c2 <- "hello":
fmt.Println("sent hello to c2");
case c3 <- 55:
fmt.Println("sent 55 to c3");
}
Example pseudorandom send:
func send(c chan int) {
for {
select {
case c <- 0:
case c <- 1:
}
}
}
func main() {
c := make(chan int)
go send(c)
for i := 0; i < 40; i++ {
fmt.Printf("%d", <-c)
}
}
1110100000001011011000010100101000101110
func gen(total int) chan string {
c := make(chan string)
go func() {
for i := 0; i < total; i++ {
c <- fmt.Sprintf("result %d", i)
}
close(c)
}()
return c
}
func main() {
c := gen(10)
for {
if r, ok := <-c; ok {
fmt.Println(r)
} else {
return
}
}
}
Simplified by using the range clause for channels.
func gen(total int) chan string {
c := make(chan string)
go func() {
for i := 0; i < total; i++ {
c <- fmt.Sprintf("result %d", i)
}
close(c)
}()
return c
}
func main() {
for r := range gen(10) {
fmt.Println(r)
}
}
func fn(msg string) (out chan string, quit chan bool) {
out, quit = make(chan string), make(chan bool)
go func() {
for i := 0; ; i++ {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
select {
case out <- fmt.Sprintf("%s %d", msg, i):
case <-quit: return
}
}
}()
return
}
func main() {
result, quit := fn("result")
for {
fmt.Println(<-result)
if rand.Intn(2) == 0 {
quit <- true
break
}
}
}
Advantages:
Disadvantages: