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() } }