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语言非常类似,
用于吸收结尾的换行符
_, err := fmt.Scanf("%f %f
", &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()
}
}