Skip to content

Instantly share code, notes, and snippets.

@vorandrew
Last active April 8, 2016 16:35
Show Gist options
  • Save vorandrew/90fe030829a8f8c3b7fb429b429da4f8 to your computer and use it in GitHub Desktop.
Save vorandrew/90fe030829a8f8c3b7fb429b429da4f8 to your computer and use it in GitHub Desktop.
Channels
package main
func main() {
var c chan string
c <- "let's get started" // deadlock
<-c // deadlock
c := make(chan string)
close(c)
c <- "let's get started" // panic
val, open := <-c // val = zero, open = false
}
package main
import (
"fmt"
"net/http"
)
type job struct {
url string
resp chan *http.Response
}
type worker struct {
jobs chan *job
count int
}
func (w *worker) getter(done chan *worker) {
for {
j := <-w.jobs
resp, _ := http.Get(j.url)
j.resp <- resp
done <- w
}
}
func get(jobs chan *job, url string, answer chan string) {
resp := make(chan *http.Response)
jobs <- &job{url, resp}
r := <-resp
answer <- r.Request.URL.String()
}
func balancer(count int, depth int) chan *job {
jobs := make(chan *job)
done := make(chan *worker)
workers := make([]*worker, count)
for i := 0; i < count; i++ {
workers[i] = &worker{make(chan *job, depth), 0}
go workers[i].getter(done)
}
go func() {
for {
var free *worker
min := depth
for _, w := range workers {
if w.count < min {
free = w
min = w.count
}
}
var jobsource chan *job
if free != nil {
jobsource = jobs
}
select {
case j := <-jobsource:
free.jobs <- j
free.count++
case w := <-done:
w.count--
}
}
}()
return jobs
}
func main() {
jobs := balancer(10, 10)
answer := make(chan string)
for {
var url string
if _, err := fmt.Scanln(&url); err != nil {
break
}
go get(jobs, url, answer)
}
for u := range answer {
fmt.Printf("%s\n", u)
}
}
package main
import "net/http"
type work struct {
url string
resp chan *http.Response
}
func getter(w chan work) {
for {
do := <-w
resp, _ := http.Get(do.url)
do.resp <- resp
}
}
func main() {
w := make(chan work)
go getter(w)
resp := make(chan *http.Response)
w <- work{"http://cdnjs.cloudflare.com/jquery/1.9.1/jquery.min.js", resp}
r := <-resp
// ... do something
}
package main
func worker(start chan bool) {
<-start
// ... do stuff
}
func main() {
start := make(chan bool)
for i := 0; i < 100; i++ {
go worker(start)
}
close(start)
// ... all workers running now
}
package main
func worker(start chan bool) {
<-start
// ... do stuff
}
func main() {
start := make(chan bool)
for i := 0; i < 100; i++ {
go worker(start)
}
close(start)
// ... all workers running now
}
package main
import "fmt"
func main() {
c1 := make(chan bool)
c2 := make(chan bool)
go func() {
for {
select {
case x, ok := <-c1:
if !ok {
c1 = nil
}
fmt.Println(x)
case x, ok := <-c2:
if !ok {
c2 = nil
}
fmt.Println(x)
}
if c1 == nil && c2 == nil {
return
}
}
}()
c1 <- true
// Disable the c1 case in the above select.
close(c1)
c2 <- true
}
package main
import (
"fmt"
"math/rand"
)
func main() {
c := make(chan int)
d := make(chan bool)
go func(src chan int) {
for {
select {
case src <- rand.Intn(100):
case <-d:
src = nil
}
}
}(c)
// Print some random numbers.
fmt.Printf("%d\n", <-c)
fmt.Printf("%d\n", <-c)
// Disable random number generation.
d <- true
// Halts because c is now nil.
fmt.Printf("%d\n", <-c)
}
package main
import "net/http"
type response struct {
resp *http.Response
url string
}
func get(url string, r chan response) {
if resp, err := http.Get(url); err == nil {
r <- response{resp, url}
}
}
func main() {
first := make(chan response)
for _, url := range []string{"http://code.jquery.com/jquery-1.9.1.min.js",
"http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js",
"http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js",
"http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"} {
go get(url, first)
}
r := <-first
// ... do something
}
package main
import "time"
func worker() {
heartbeat := time.Tick(30 * time.Second)
for {
select {
// ... do some stuff
case <-heartbeat:
// ... do heartbeat stuff
}
}
}
func main() {
go worker()
}
package main
import "net"
func worker(messages chan string) {
for {
var msg string // ... generate a message
messages <- msg
}
}
func main() {
messages := make(chan string)
conn, _ := net.Dial("tcp", "example.com")
for i := 0; i < 100; i++ {
go worker(messages)
}
for {
msg := <-messages
conn.Write([]byte(msg))
}
}
package main
import "container/list"
func main() {
give := make(chan []byte)
get := make(chan []byte)
go func() {
q := new(list.List)
for {
if q.Len() == 0 {
q.PushFront(make([]byte, 100))
}
e := q.Front()
select {
case s := <-give:
q.PushFront(s)
case get <- e.Value.([]byte):
q.Remove(e)
}
}
}()
// Gets a new buffer from the recycler.
buffer := <-get
// Give it back to the recycler.
give <- buffer
// Get the recycled buffer again.
buffer = <-get
}
package main
func get(store chan []byte) []byte {
select {
case b := <-store:
return b
default:
return make([]byte, 100)
}
}
func give(store chan []byte, b []byte) {
select {
case store <- b:
default:
return
}
}
func main() {
// Create a store for the buffers.
store := make(chan []byte, 5)
// Gets a new buffer from the store.
buffer := get(store)
// Give it back to the store.
give(store, buffer)
// Get the recycled buffer again from the store.
buffer = get(store)
}
https://www.youtube.com/watch?v=SmoM1InWXr0
http://www.slideshare.net/cloudflare/a-channel-compendium
package main
import "fmt"
func main() {
id := make(chan string)
go func() {
var counter int64 = 1
for {
id <- fmt.Sprintf("%x", counter)
counter += 1
}
}()
fmt.Printf("%s\n", <-id) // will be 1
fmt.Printf("%s\n", <-id) // will be 2
}
package main
import "time"
func worker() {
for {
timeout := time.After(5 * time.Second)
select {
// ... do some stuff
case <-timeout:
// Close this go routine after the specified timeout.
return
}
}
}
func main() {
go worker()
}
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan bool)
go func() {
// ... do some stuff
time.Sleep(time.Second * 5)
close(c)
}()
// Halt for communication of data via the channel or for it to be closed.
<-c
fmt.Println("Done")
}
package main
func worker(die chan bool) {
for {
select {
// ... do stuff cases
case <-die:
// ... do termination tasks
die <- true
return
}
}
}
func main() {
die := make(chan bool)
go worker(die)
die <- true
// Wait until the goroutine has terminated.
<-die
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment