1. golang程序运行时间显示
packagemain import( "fmt" "time" "math/rand" ) funcmain(){ rand.Seed(time.Now().Unix()) varnamestring fori:=0;i<3;i++{ name=fmt.Sprintf("go_%02d",i) gorunroutine(name,time.Duration(rand.Intn(5))*time.Second) } varinputstring //forwaitinggoroutine,unlessitexit. fmt.Scanln(&input) fmt.Println("Done") } funcrunroutine(namestring,ttime.Duration){ t0:=time.Now() fmt.Println(name,"startat",t0) time.Sleep(t) t1:=time.Now() fmt.Println(name,"endat",t1) fmt.Println(name,"lasted",t1.Sub(t0)) fmt.Println() }
运行结果:
go_00startat2013-12-0517:22:34.5337149+0800+0800 go_01startat2013-12-0517:22:34.5367151+0800+0800 go_02startat2013-12-0517:22:34.5367151+0800+0800 go_02endat2013-12-0517:22:36.5548305+0800+0800 go_02lasted2.0181154s go_00endat2013-12-0517:22:37.5558878+0800+0800 go_00lasted3.0221729s go_01endat2013-12-0517:22:38.5549449+0800+0800 go_01lasted4.0182298s j Done
2. 利用mutex控制goroutine的执行
packagemain import"fmt" import"time" import"math/rand" import"sync" import"runtime" //vartotal_ticketsint32=10 varmutex=&sync.Mutex{}//可简写成:varmutexsync.Mutex funcsell_tickets(iint,ttime.Duration){ vartotal_ticketsint32=10 for{ mutex.Lock() iftotal_tickets>0{ time.Sleep(t) total_tickets-- fmt.Println("id:",i,"ticket:",total_tickets) } mutex.Unlock() } } funcmain(){ runtime.GOMAXPROCS(4)//我的电脑是4核处理器,所以我设置了4 rand.Seed(time.Now().Unix())//生成随机种子 fori:=0;i<5;i++{//并发5个goroutine来卖票 gosell_tickets(i,time.Duration(rand.Intn(5))*time.Millisecond) } //等待线程执行完 varinputstring fmt.Scanln(&input) //fmt.Println(total_tickets,"done")//退出时打印还有多少票 }
3. 利用select监听channel
packagemain import"time" import"fmt" funcmain(){ //创建两个channel-c1c2 c1:=make(chanstring) c2:=make(chanstring) //创建两个goruntine来分别向这两个channel发送数据 gofunc(){ time.Sleep(time.Second*1) c1<-"Hello" }() gofunc(){ time.Sleep(time.Second*1) c2<-"World" }() //使用select来侦听两个channel for{ select{ casemsg1:=<-c1: fmt.Println("received",msg1) casemsg2:=<-c2: fmt.Println("received",msg2) case<-time.After(time.Second*30): fmt.Println("TimeOut") break } } }
上面代码执行time.After时总是报错:invalid identifier。不知道为什么。如果改成default,加入sleep和break,由于break写在最后,导致sleep后继续监听而使break永远也得不到执行。
package main import "time" import "fmt" func main() { //创建两个channel - c1 c2 c1 := make(chan string) c2 := make(chan string) //创建两个goruntine来分别向这两个channel发送数据 go func() { time.Sleep(time.Second * 1) c1 <- "Hello" }() go func() { time.Sleep(time.Second * 1) c2 <- "World" }() //使用select来侦听两个channel for { select { case msg1 := <-c1: fmt.Println("received",msg1) case msg2 := <-c2: fmt.Println("received",msg2) default: //default会导致无阻塞 fmt.Println("nothing received!") time.Sleep(time.Second)
//break永远也不会执行 break } } }
packagemain import"fmt" import"time" import"math/rand" funcmain(){ channel:=make(chanstring) rand.Seed(time.Now().Unix()) //向channel发送随机个数的message gofunc(){ cnt:=rand.Intn(10) fmt.Println("messagecnt:",cnt) fori:=0;i<cnt;i++{ channel<-fmt.Sprintf("message-%2d",i) } close(channel)//关闭Channel }() varmorebool=true varmsgstring formore{ select{ //channel会返回两个值,一个是内容,一个是bool casemsg,more=<-channel: ifmore{ fmt.Println(msg) }else{ fmt.Println("channelclosed!") } } } }
4. golang的定时器
Go语言中可以使用time.NewTimer或time.NewTicker来设置一个定时器,这个定时器会绑定在你的当前channel中,通过channel的阻塞通知机器来通知你的程序。
packagemain import"time" import"fmt" funcmain(){ ticker:=time.NewTicker(time.Second) gofunc(){ fort:=rangeticker.C{ fmt.Println(t) } }() //设置一个timer,10钞后停掉ticker timer:=time.NewTimer(10*time.Second) <-timer.C ticker.Stop() fmt.Println("timerexpired!") }
5. 利用os/exec中的Cmd执行命令
packagemain import( "bytes" "fmt" "log" "os/exec" "strings" ) funcmain(){ cmd:=exec.Command("tr","a-z","A-Z") cmd.Stdin=strings.NewReader("someinput") varoutbytes.Buffer cmd.Stdout=&out err:=cmd.Run() iferr!=nil{ log.Fatal(err) } fmt.Printf("inallcaps:%q\n",out.String()) }
6. golang命令行参数解析
packagemain import( "bytes" "fmt" "log" "os/exec" "strings" ) funcmain(){ cmd:=exec.Command("tr",out.String()) }
这样执行:
#如果没有指定参数名,则使用默认值 $gorunflagtest.go host:coolshell.cn port:80 debug:false #指定了参数名后的情况 $gorunflagtest.go-host=localhost-port=22-d host:localhost port:22 debug:true #用法出错了(如:使用了不支持的参数,参数没有=) $gobuildflagtest.go $./flagtest-debug-hostlocalhost-port=22 flagprovidedbutnotdefined:-debug Usageofflagtest: -d=false:enable/disabledebugmode -host="coolshell.cn":ahostname -port=80:aportnumber exitstatus2
7. 使用append要注意的问题
1. 先看段简单的代码。
a := []int{1,2,3,4,5}
b = append(a[1:3],8,9)
这时fmt.Println(a)的结果是什么?
答案是: a = [1,9]
原因解答:a[1:3]返回的是一个new slice: b。不过这个b沿用了 a原有的空间。
2. 再看个新的
原因解答: 因为这次append的数据超过了a的空间大小。所以系统重新开辟了一段空间给b。所以a的数据就不会修改了。
3. 在来一个
a := make([]int,6)
a = append(a,1,5)
答案是:(你大概应该猜到了) 是 a = [1,9]
原因吗: 看看上一条解答,就明白了。也就是slice以cap空间为标准,没有超过cap的空间,不会触发空间的重新分配。
4. 补充一个
b := a[:3] // 这个语句合法吗?
答案是合法的,虽然len(a) == 0,不过slice取的是cap(a)。 只不过是b = [0,0]