《go语言程序设计》学习(五)

mruoli · · 2059 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一,并发

package main
import (
    "bufio"
    "fmt"
    "math"
    "os"
)
const result = "Polar radius=%.02f θ=%.02f° → Cartesian x=%.02f y=%.02f\n"
var prompt = "Enter a radius and an angle (in degrees), e.g., 12.5 90, " +
    "or %s to quit."
type polar struct {
    radius float64
    tt     float64
}
type cartesian struct {
    x float64
    y float64
}
func init() {
    prompt = fmt.Sprintf(prompt, "Ctrl+D")
}
func main() {
    questions := make(chan polar)
    defer close(questions)
    answers := CreateSolver(questions)
    defer close(answers)
    interact(questions, answers)
}
func CreateSolver(questions chan polar) chan cartesian {
    answers := make(chan cartesian)
    go func() {
        for {
            polarCoord := <-questions
            tt := polarCoord.tt * math.Pi / 180
            x := polarCoord.radius * math.Cos(tt)
            y := polarCoord.radius * math.Sin(tt)
            answers <- cartesian{x, y}
        }
    }()
    return answers
}
func interact(questions chan polar, answers chan cartesian) {
    reader := bufio.NewReader(os.Stdin)
    fmt.Println(prompt)
    for {
        fmt.Printf("radius and angle :")
        line, err := reader.ReadString('\n')
        if err != nil {
            break
        }
        var radius, tt float64
        if _, err := fmt.Sscanf(line, "%f %f", &radius, &tt); err != nil {
            fmt.Println(os.Stderr, "invalid input")
            continue
        }
        questions <- polar{radius, tt}
        coord := <-answers
        fmt.Printf(result, radius, tt, coord.x, coord.y)
    }
    fmt.Println()
}

main函数做了几个事情

1.创建questions通道

2.创建solver通道,启动计算协程

3.进行主循环(使用了没有条件的for)

 

这个程序使用了go的协程,协程的创建方法:go 函数。协程要和主进程通信,所以创建了两个通道,一个通道是主进程写入数据,协程来读取,一个通道协程创建,主进程读取。

 

二,协程。

goroutine是程序中与其他goroutine完全相互独立而并发执行的函数活着方法调用。每一个go程序都至少有一个goroutine,即会执行main包中main函数的主goroutine。goroutine非常像轻量级的线程或者协程,他们可以批量的创建。所有的goroutine享有相同的地址空间,同时go语言提供了锁原语来保证数据能够安全的跨goroutine共享。然而go语言推荐的并发编程方式是通信,而非数据共享。

关于通道,如果给定了一个缓冲区的容量,那么通信就是异步的,只要缓冲区有未使用的空间用于发送数据,或还包含可以接收的数据,那么其通信酒会无阻塞的进行。如果是没有缓冲区的通道,或者通道满了,那么就将变成同步的通信。

goroutine接收数据的时候,可以使用select同时监听多个通道,任意一个通道有数据,就会激活对应通道的处理。


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:mruoli

查看原文:《go语言程序设计》学习(五)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2059 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传