Skip to content

Instantly share code, notes, and snippets.

@davidkellis
Created August 8, 2017 16:57
Show Gist options
  • Save davidkellis/a022bc3a430575d6353b1fa9863b1b80 to your computer and use it in GitHub Desktop.
Save davidkellis/a022bc3a430575d6353b1fa9863b1b80 to your computer and use it in GitHub Desktop.
Fibers in Go (found at https://play.golang.org/p/NSIlZ327sC)
// I found the following implementation (verbatim) of Fibers in Go at https://play.golang.org/p/NSIlZ327sC
// I'm capturing it here for future reference.
package main
import (
"errors"
"fmt"
)
var errResumeDeadFiber = errors.New("resume dead fiber")
type fiberDeadPanic struct{}
type Fiber struct {
resume chan int
close chan int
}
func NewFiber() *Fiber {
f := Fiber{
resume: make(chan int),
close: make(chan int),
}
go f.run()
return &f
}
func (f *Fiber) handleBreak() {
if r := recover(); r != nil {
if _, ok := r.(fiberDeadPanic); !ok {
panic(r)
}
}
fmt.Println("exit goroutine")
}
func (f *Fiber) run() {
defer f.handleBreak()
i := 0
for {
f.Yield(i)
f.Yield(i)
i++
}
}
func (f *Fiber) Yield(i int) {
select {
case <-f.close:
panic(fiberDeadPanic{})
case f.resume <- i:
}
}
func (f *Fiber) Resume() (int, error) {
select {
case <-f.close:
return 0, errResumeDeadFiber
default:
return <-f.resume, nil
}
}
func (f *Fiber) Close() {
select {
case <-f.close:
default:
close(f.close)
}
}
func main() {
for i := 0; i < 5; i++ {
f := NewFiber()
fmt.Println(f.Resume())
fmt.Println(f.Resume())
fmt.Println(f.Resume())
fmt.Println(f.Resume())
f.Close()
fmt.Println(f.Resume())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment