Skip to content

Instantly share code, notes, and snippets.

@jnwhiteh
Created September 5, 2011 17:57
Show Gist options
  • Save jnwhiteh/1195562 to your computer and use it in GitHub Desktop.
Save jnwhiteh/1195562 to your computer and use it in GitHub Desktop.
Problem with channel receive
package foo
import (
"log"
)
// A simple server that will respond to request messages
type Server struct {
in chan m_req
out chan m_res
done chan bool
}
func NewServer() *Server {
server := &Server{
make(chan m_req),
make(chan m_res),
make(chan bool),
}
go server.loop()
return server
}
func (s *Server) loop() {
var in <-chan m_req = s.in
var out chan<- m_res = s.out
// Get requests from 'in' and then respond accordingly on 'out'
for req := range in {
switch req := req.(type) {
case m_req_square:
log.Printf("Got an square message")
result := req.x * req.x
out <- m_res_square{result}
case m_req_cube:
log.Printf("Got a cube message")
result := req.x * req.x * req.x
out <- m_res_cube{result}
case m_req_close:
log.Printf("Got a close message")
out <- m_res_close{}
// ignore for the moment that s.in and s.out never get closed here
goto stop
}
}
stop:
s.done <- true
}
func (s *Server) Square(x int) int {
s.in <- m_req_square{x}
res := (<-s.out).(m_res_square)
return res.x
}
func (s *Server) Cube(x int) int {
s.in <- m_req_cube{x}
res := (<-s.out).(m_res_cube)
return res.x
}
func (s *Server) Close() {
s.in <- m_req_close{}
// The following code works fine:
//<-s.out
// FIXME: This code blocks indefinitely if the m_res_close struct is empty
res := (<-s.out).(m_res_close)
_ = res
// This works as well
// msg := <-s.out
// res := msg.(m_res_close)
// _ = res
}
// define some message types
type m_req interface {
is_m_req()
}
type m_res interface {
is_m_res()
}
type m_req_square struct{ x int }
type m_req_cube struct{ x int }
type m_req_close struct{}
type m_res_square struct{ x int }
type m_res_cube struct{ x int }
type m_res_close struct{}
func (m m_req_square) is_m_req() {}
func (m m_req_cube) is_m_req() {}
func (m m_req_close) is_m_req() {}
func (m m_res_square) is_m_res() {}
func (m m_res_cube) is_m_res() {}
func (m m_res_close) is_m_res() {}
package foo
import (
"testing"
)
func TestShutdown(test *testing.T) {
server := NewServer()
res := server.Square(3)
if res != 9 {
test.Errorf("Expected 9, got %d", res)
}
res = server.Cube(2)
if res != 8 {
test.Errorf("Expected 8, got %d", res)
}
server.Close()
<-server.done
}
include $(GOROOT)/src/Make.inc
TARG=foo
GOFILES=\
foo.go \
include $(GOROOT)/src/Make.pkg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment