分别使用sync.WaitGroup和context
使用sync.WaitGroup, 可控制循环次数

package main

import (
	"fmt"
	"sync"
)

//控制循环次数
var count = 5

func main() {
	wg := sync.WaitGroup{}

	chanA := make(chan struct{}, 1)
	chanB := make(chan struct{}, 1)
	chanC := make(chan struct{}, 1)

	chanA <- struct{}{}

	wg.Add(3)

	go printA(&wg, chanA, chanB)
	go printB(&wg, chanB, chanC)
	go printC(&wg, chanC, chanA)

	wg.Wait()
}

func printA(wg *sync.WaitGroup, chanA, chanB chan struct{}) {
	defer wg.Done()
	for i := 0; i < count; i++ {
		<-chanA
		fmt.Println("A")

		chanB <- struct{}{}
	}
}

func printB(wg *sync.WaitGroup, chanB, chanC chan struct{}) {
	defer wg.Done()
	for i := 0; i < count; i++ {
		<-chanB
		fmt.Println("B")

		chanC <- struct{}{}
	}
}

func printC(wg *sync.WaitGroup, chanC, chanA chan struct{}) {
	defer wg.Done()
	for i := 0; i < count; i++ {
		<-chanC
		fmt.Println("C")

		chanA <- struct{}{}
	}
}

使用context.WithCancel,通过time.Sleep控制打印数量

package main

import (
	"context"
	"fmt"
	"time"
)

func main() {

	chanA := make(chan struct{}, 1)
	chanB := make(chan struct{}, 1)
	chanC := make(chan struct{}, 1)

	chanA <- struct{}{}

	ctx1, cancel1 := context.WithCancel(context.Background())
	ctx2, cancel2 := context.WithCancel(context.Background())
	ctx3, cancel3 := context.WithCancel(context.Background())

	go printA(ctx1, chanA, chanB)
	go printB(ctx2, chanB, chanC)
	go printC(ctx3, chanC, chanA)

	time.Sleep(100 * time.Microsecond)
	cancel1()
	cancel2()
	cancel3()

}

func printA(ctx context.Context, chanA, chanB chan struct{}) {

	for {
		select {
		case <-ctx.Done():
			fmt.Println("cancel by parent") // 不会输出
			return
		case <-chanA:
			fmt.Println("A")
			chanB <- struct{}{}
		}
	}
}

func printB(ctx context.Context, chanB, chanC chan struct{}) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("cancel by parent") // 不会输出
			return
		case <-chanB:
			fmt.Println("B")
			chanC <- struct{}{}
		}
	}
}

func printC(ctx context.Context, chanC, chanA chan struct{}) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("cancel by parent") // 不会输出
			return
		case <-chanC:
			fmt.Println("C")
			chanA <- struct{}{}
		}
	}
}