1、goroutine线程
goroutine
是一个轻量级的执行线程。假设有一个函数调用f(s)
,要在goroutine
中调用此函数,请使用go f(s)
。 这个新的goroutine
将与调用同时执行。
示例代码如下:
package main import "fmt" func f(from string) {
for i := ; i < ; i++ {
fmt.Println(from, ":", i)
}
} func main() { // Suppose we have a function call `f(s)`. Here's how
// we'd call that in the usual way, running it
// synchronously.
f("direct") // To invoke this function in a goroutine, use
// `go f(s)`. This new goroutine will execute
// concurrently with the calling one.
go f("goroutine") // You can also start a goroutine for an anonymous
// function call.
go func(msg string) {
fmt.Println(msg)
}("going") // Our two function calls are running asynchronously in
// separate goroutines now, so execution falls through
// to here. This `Scanln` code requires we press a key
// before the program exits.
var input string
fmt.Scanln(&input)
fmt.Println("done")
}
执行上面代码,将得到以下输出结果
direct :
direct :
direct :
goroutine :
goroutine :
goroutine :
going
2、通道
通道是连接并发goroutine
的管道。可以从一个goroutine
向通道发送值,并在另一个goroutine
中接收到这些值。
package main import "fmt" func main() { // Create a new channel with `make(chan val-type)`.
// Channels are typed by the values they convey.
messages := make(chan string) // _Send_ a value into a channel using the `channel <-`
// syntax. Here we send `"ping"` to the `messages`
// channel we made above, from a new goroutine.
go func() { messages <- "ping" }()//使用"<-"向通道发送消息 // The `<-channel` syntax _receives_ a value from the
// channel. Here we'll receive the `"ping"` message
// we sent above and print it out.
msg := <-messages//"从通道读取数据"
fmt.Println(msg)
}
默认情况下,通道是未缓冲的,意味着如果有相应的接收(<- chan
)准备好接收发送的值,它们将只接受发送(chan <-
)。使用make的第二个参数指定缓冲大小
package main import "fmt" func main() { // Here we `make` a channel of strings buffering up to
// 2 values.
messages := make(chan string, ) // Because this channel is buffered, we can send these
// values into the channel without a corresponding
// concurrent receive.
messages <- "buffered"
messages <- "channel" // Later we can receive these two values as usual.
fmt.Println(<-messages)
fmt.Println(<-messages)
}
3、通道同步
package main import "fmt"
import "time" // This is the function we'll run in a goroutine. The
// `done` channel will be used to notify another
// goroutine that this function's work is done.
func worker(done chan bool) {
fmt.Print("working...")
time.Sleep(time.Second)
fmt.Println("done") // Send a value to notify that we're done.
done <- true
} func main() { // Start a worker goroutine, giving it the channel to
// notify on.
done := make(chan bool, )
go worker(done) // Block until we receive a notification from the
// worker on the channel.
<-done
}
当使用通道作为函数参数时,可以指定通道是否仅用于发送或接收值。这种特殊性增加了程序的类型安全性。chan<-
表示发送,<-chan
表示接收
4、select
每个通道将在一段时间后开始接收值,以模拟阻塞在并发goroutines
中执行的RPC
操作。我们将使用select
同时等待这两个值,在每个值到达时打印它们。
package main import "time"
import "fmt" func main() { // For our example we'll select across two channels.
c1 := make(chan string)
c2 := make(chan string) // Each channel will receive a value after some amount
// of time, to simulate e.g. blocking RPC operations
// executing in concurrent goroutines.
go func() {
time.Sleep(time.Second * )
c1 <- "one"
}()
go func() {
time.Sleep(time.Second * )
c2 <- "two"
}() // We'll use `select` to await both of these values
// simultaneously, printing each one as it arrives.
for i := ; i < ; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
5、相关文章
Go非阻塞通道操作实例:使用select
和default
子句来实现非阻塞发送,接收
Go关闭通道实例:close直接关闭通道
Go通道范围实例:通道关闭了,还可以接收通道中的数据