Skip to content
jinyangcruise edited this page Sep 7, 2018 · 1 revision

Welcome to the chantask wiki!

Q&A

Q: What is Sender/Receiver so called?

A: Sender/Receiver is a func that has a signature as func(task *ChanTask, args ...interface{}). In Sender func, you can (not must) call task.Send(); In Receiver func, you can (not must) call task.Receive(). A Receiver will receive the data by task.Receive() at once a Sender send a data by task.Send().

Q: Why Sender/Receiver has a signature as func(task *ChanTask, args ...interface{})?

A: This signature can remind developers that when your Sender/Receiver need a variable from outside, it should be passed into the func unless you can make sure the variable will never change. Here is an example:

WRONG!!!

package main

import (
	"github.com/jinyangcruise/chantask"
	"fmt"
)

func main() {
	ids := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	task := chantask.CreateChanTask(10, 10)
	for i := 0; i < 5; i++ {
		task.AddSender(func(task *chantask.ChanTask, args ...interface{}) {
			task.Send(ids[i]) // directly use ids[i]
		})
	}
	task.AddReceiver(func(task *chantask.ChanTask, args ...interface{}) {
		for {
			v, ok := task.Receive()
			if !ok {
				return
			}
			fmt.Println("id:", v)
		}
	})
	task.Start()
}

output:

id: 5
id: 5
id: 5
id: 5
id: 5

The Right Way As Below:

...
func main() {
	...
	for i := 0; i < 5; i++ {
		task.AddSender(func(task *chantask.ChanTask, args ...interface{}) {
			task.Send(args[0].(int)) // use args
		}, ids[i]) // pass outside variable like this
	}
	...
}

output may like(the order can be different):

id: 0
id: 4
id: 1
id: 2
id: 3

Q: Can I call task->Send(...) in Receiver and why?

A: No! A panic (ie panic: send on closed channel) is most likely to occur when you do this. task->Send(...) is achieved by calling chan<- .... The chantask automatically checks if all the Senders are done then close the chan. If all the Senders are done and the chan is closed but your Receiver is still running and try to send something to the chan, a panic occurs.