Go 语言简介(下)— 特性

Go 语言简介(下)— 特性

希望你看到这篇文章的时候还是在公交车和地铁上正在上下班的时间,我希望我的这篇文章可以让你利用这段时间了解一门语言。当然,希望你不会因为看我的文章而错过站。呵呵。

如果你还不了解Go语言的语法,还请你移步先看一下上篇——《Go语言简介(上):语法

goroutine

GoRoutine主要是使用go关键字来调用函数,你还可以使用匿名函数,如下所示:

package main
import "fmt"

func f(msg string) {
    fmt.Println(msg)
}

func main(){
    go f("goroutine")

    go func(msg string) {
        fmt.Println(msg)
    }("going")
}

我们再来看一个示例,下面的代码中包括很多内容,包括时间处理,随机数处理,还有goroutine的代码。如果你熟悉C语言,你应该会很容易理解下面的代码。

你可以简单的把go关键字调用的函数想像成pthread_create。下面的代码使用for循环创建了3个线程,每个线程使用一个随机的Sleep时间,然后在routine()函数中会输出一些线程执行的时间信息。

package main

import "fmt"
import "time"
import "math/rand"

func routine(name string, delay time.Duration) {

    t0 := time.Now()
    fmt.Println(name, " start at ", t0)

    time.Sleep(delay)

    t1 := time.Now()
    fmt.Println(name, " end at ", t1)

    fmt.Println(name, " lasted ", t1.Sub(t0))
}

func main() {

    //生成随机种子
    rand.Seed(time.Now().Unix())

    var name string
    for i:=0; i<3; i++{
        name = fmt.Sprintf("go_%02d", i) //生成ID
        //生成随机等待时间,从0-4秒
        go routine(name, time.Duration(rand.Intn(5)) * time.Second)
    }

    //让主进程停住,不然主进程退了,goroutine也就退了
    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

运行的结果可能是:

go_00  start at  2012-11-04 19:46:35.8974894 +0800 +0800
go_01  start at  2012-11-04 19:46:35.8974894 +0800 +0800
go_02  start at  2012-11-04 19:46:35.8974894 +0800 +0800
go_01  end at  2012-11-04 19:46:36.8975894 +0800 +0800
go_01  lasted  1.0001s
go_02  end at  2012-11-04 19:46:38.8987895 +0800 +0800
go_02  lasted  3.0013001s
go_00  end at  2012-11-04 19:46:39.8978894 +0800 +0800
go_00  lasted  4.0004s

goroutine的并发安全性

关于goroutine,我试了一下,无论是Windows还是Linux,基本上来说是用操作系统的线程来实现的。不过,goroutine有个特性,也就是说,如果一个goroutine没有被阻塞,那么别的goroutine就不会得到执行。这并不是真�