package main
/**
    用两个通道:questions 和 answers 实现一问一答无限循环的小程序
*/
import (
	"fmt"
	"math"
)

type cartesian struct {
	x float64
	y float64
}

type polar struct {
	radius float64
	angle  float64 //角度
}

/**
	c <-answers(chan) <- (cartesian struct) goroutine (polarCoord struct) <- questions(chan) <- polar{5, 30.5}
 */

func main() {

	questions := make(chan polar)

	// make(chan<- type)  make a  sendonly type chain , only send data to the chain

	defer close(questions)

	answers := make(chan cartesian)

	// '<-chan' receiveonly chain . only receive data from the chain
	
	defer close(answers)

	//启动一个无限的 有数据就计算发送,没数据就阻塞等待的 goroutine
	go func() {

		for {
			p := <-questions //从questions通道取问题:一个极坐标的结构体

			x := p.radius * math.Cos(p.angle*math.Pi/180.0) //角度转为弧度
			y := p.radius * math.Sin(p.angle*math.Pi/180.0)

			answers <- cartesian{x, y} //将计算结果(一个笛卡尔坐标结构体)发送到 answers 通道中
		}
	}()

	//虽然 goroutine 是无限循环 但是 控制台程序执行到最后一条后,如果没有一个挂起主线程的语句 main 函数会退出返回给操作系统

	for {
		var radius, angle float64

		fmt.Print("enter radius and angle(eg: 12.5 90): ")
		//键盘输入方法和C语言非常类似,\n 用于吸收结尾的换行符
		_, err := fmt.Scanf("%f %f\n", &radius, &angle);
		if err != nil { //输入格式错误等待下一次输入
			continue
		}

		//将问题发送到 questions 通道,
		questions <- polar{radius, angle} //questions:键盘输入发送;goroutine获取所以是一个双向通道
		c := <-answers

		fmt.Printf("(%.3f,%.3f)", c.x, c.y)
		fmt.Println()
	}

}
posted on 2018-09-02 23:18  scala  阅读(182)  评论(0编辑  收藏  举报