golang closure - foolmacky/DevelopDocs GitHub Wiki
■Goの関数はclosureです
for _, val := range values {
go func() {
fmt.Println(val)
}()
}
//このloopでは中の関数がgoroutineになっているので、さきにloopが終了してしまい、valの値は最後の値(ここでは9)になる
//goroutineにスイッチされ、実際に実行されるが、各goroutineはこの最後の値を使って処理を行うため、期待した動作にならない。
//なので、この場合はvalをfuncの引数に渡すようにする
for _, val := range values {
go func(val2) {
fmt.Println(val2)
}(val) //<-------これはfor loopからfuncの呼び出しの引数
}
//クロージャー的に変数を参照できてしまうが、それはgoroutine生成時に渡されたものではない、ということ
import (
"bufio"
"log"
"os"
)
type Task interface {
Exec (arg interface{}) (interface{}, error)
}
type InLoop struct {
Fexec func(arg interface{}) (interface{}, error)
}
func NewInLoop() InLoop {
return InLoop(
Fexec: buildExec()}
}
func buildExec() func(interface{}) (interface{}, error) {
var ctext []string
log.Println(ctext)
return func (arg interface{}) (interface{}, error) {
ctext = append(ctext, arg.(string))
return ctext, nil
}
}
func (inloop InLoop) Exec(arg interface{}) (interface{}, error) {
log.Println("In Exec")
return inloop.Fexec(arg)
}
func main() {
pfile, perr := os.Opne("looptext")
if perr != nil {
log.Println(perr)
}
defer pfile.Close()
pscanner := bufio.NewScanner(pfile)
var mtext interface{}
inloop := NewInLoop()
tasks := []Task(inloop)
for repet := 0; repet < 500; repet++ {
if !pscanner.Scan() {
log.Println("Pscanner error.")
break
}
if perr = pscanner.Err(); perr != nil {
log.Println(perr)
break
}
for _, task := range tasks {
mtext, _ = task.Exec(pscanner.Text())
}
}
}
- goroutineはchannelをclosureの仕組みで参照している。あんまり意識していないけど、とても大切