goroutineから、サブgoroutineを消滅させる方法
これは、結構オーソドックスな手法で、いろいろなところに使われています。
/*
	お題: personが終了したらsubPerson1も subPerson2も強制的に終了させるには?
*/
package main
import (
	"fmt"
	"sync"
	"time"
)
func subPerson1(i int, wg *sync.WaitGroup, ch chan struct{}) {
	defer wg.Done()
	<-ch // close(ch)が発行されるまでロック (普通はselect待ちにする)
	fmt.Println("		End of sub_person1(", i, ")")
}
func subPerson2(i int, wg *sync.WaitGroup, ch chan struct{}) {
	defer wg.Done()
	<-ch // close(ch)が発行されるまでロック (普通はselect待ちにする)
	fmt.Println("		End of sub_person2(", i, ")")
}
func person(i int, wg *sync.WaitGroup) {
	fmt.Println("	Start... person(", i, ")")
	defer wg.Done()
	subWG := sync.WaitGroup{}
	subWG.Add(2)
	ch := make(chan struct{})
	go subPerson1(i, &subWG, ch)
	go subPerson2(i, &subWG, ch)
	time.Sleep(10 * time.Second)
	close(ch)
	subWG.Wait()
	fmt.Println("	End... person(", i, ")")
}
func main() {
	fmt.Println("start... main()")
	wg := sync.WaitGroup{}
	for i := 0; i < 5; i++ {
		wg.Add(1) // goルーチンを実行する関数分だけAddする
		go person(i, &wg)
	}
	wg.Wait()
	fmt.Println("end of ... main()")
}
出力結果はこんな感じです。
ちょっと変な感じがしますが、多分Printlnを記載している時間タイミングに因るものだろう、と思います。
$ go run main.go
start... main()
        Start... person( 4 )
        Start... person( 2 )
        Start... person( 3 )
        Start... person( 0 )
        Start... person( 1 )
                End of sub_person2( 2 )
                End of sub_person2( 0 )
                End of sub_person1( 0 )
        End... person( 0 )
                End of sub_person2( 4 )
                End of sub_person1( 4 )
        End... person( 4 )
                End of sub_person2( 3 )
                End of sub_person1( 3 )
        End... person( 3 )
                End of sub_person1( 2 )
        End... person( 2 )
                End of sub_person2( 1 )
                End of sub_person1( 1 )
        End... person( 1 )
end of ... main()