golang小程序试验(二)
2019獨角獸企業重金招聘Python工程師標準>>>
1. golang程序運行時間顯示
package?main import?("fmt""time""math/rand" )func?main(){rand.Seed(time.Now().Unix())var?name?stringfor?i:=0;?i<3;?i++{name=fmt.Sprintf("go_%02d",?i)go?runroutine(name,?time.Duration(rand.Intn(5))*time.Second)}var?input?string//for?waiting?goroutine,?unless?it?exit.fmt.Scanln(&input)fmt.Println("Done") }func?runroutine(name?string,?t?time.Duration){t0:=time.Now()fmt.Println(name,?"?start?at?",?t0)time.Sleep(t)t1:=time.Now()fmt.Println(name,?"?end?at?",?t1)fmt.Println(name,?"?lasted?",?t1.Sub(t0))fmt.Println() }運行結果:
go_00??start?at??2013-12-05?17:22:34.5337149?+0800?+0800 go_01??start?at??2013-12-05?17:22:34.5367151?+0800?+0800 go_02??start?at??2013-12-05?17:22:34.5367151?+0800?+0800 go_02??end?at??2013-12-05?17:22:36.5548305?+0800?+0800 go_02??lasted??2.0181154sgo_00??end?at??2013-12-05?17:22:37.5558878?+0800?+0800 go_00??lasted??3.0221729sgo_01??end?at??2013-12-05?17:22:38.5549449?+0800?+0800 go_01??lasted??4.0182298sj Done2. 利用mutex控制goroutine的執行
package?mainimport?"fmt" import?"time" import?"math/rand" import?"sync" import?"runtime"//var?total_tickets?int32?=?10 var?mutex?=?&sync.Mutex{}?//可簡寫成:var?mutex?sync.Mutexfunc?sell_tickets(i?int,?t?time.Duration)?{var?total_tickets?int32?=?10for?{mutex.Lock()if?total_tickets?>?0?{time.Sleep(t)total_tickets--fmt.Println("id:",?i,?"??ticket:",?total_tickets)}mutex.Unlock()} }func?main()?{runtime.GOMAXPROCS(4)????????//我的電腦是4核處理器,所以我設置了4rand.Seed(time.Now().Unix())?//生成隨機種子for?i?:=?0;?i?<?5;?i++?{?//并發5個goroutine來賣票go?sell_tickets(i,?time.Duration(rand.Intn(5))*time.Millisecond)}//等待線程執行完var?input?stringfmt.Scanln(&input)//fmt.Println(total_tickets,?"done")?//退出時打印還有多少票 }3. 利用select監聽channel
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)?case?<-time.After(time.Second?*?30):fmt.Println("Time?Out")?break?}?}? }?上面代碼執行time.After時總是報錯:invalid identifier。不知道為什么。如果改成default,加入sleep和break,由于break寫在最后,導致sleep后繼續監聽而使break永遠也得不到執行。
package mainimport "time" import "fmt"func main() {//創建兩個channel - c1 c2c1 := 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來偵聽兩個channelfor {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}} }
?關閉channel,總是在發送端關閉:
package?mainimport?"fmt" import?"time" import?"math/rand"func?main()?{channel?:=?make(chan?string)rand.Seed(time.Now().Unix())//向channel發送隨機個數的messagego?func?()?{cnt?:=?rand.Intn(10)fmt.Println("message?cnt?:",?cnt)for?i:=0;?i<cnt;?i++{channel?<-?fmt.Sprintf("message-%2d",?i)}close(channel)?//關閉Channel}()var?more?bool?=?truevar?msg?stringfor?more?{select{//channel會返回兩個值,一個是內容,一個是boolcase?msg,?more?=?<-?channel:if?more?{fmt.Println(msg)}else{fmt.Println("channel?closed!")}}} }4. golang的定時器
Go語言中可以使用time.NewTimer或time.NewTicker來設置一個定時器,這個定時器會綁定在你的當前channel中,通過channel的阻塞通知機器來通知你的程序。
5. 利用os/exec中的Cmd執行命令
package?mainimport?("bytes""fmt""log""os/exec""strings" )func?main()?{cmd?:=?exec.Command("tr",?"a-z",?"A-Z")cmd.Stdin?=?strings.NewReader("some?input")var?out?bytes.Buffercmd.Stdout?=?&outerr?:=?cmd.Run()if?err?!=?nil?{log.Fatal(err)}fmt.Printf("in?all?caps:?%q\n",?out.String()) }6. golang命令行參數解析
package?mainimport?("bytes""fmt""log""os/exec""strings" )func?main()?{cmd?:=?exec.Command("tr",?"a-z",?"A-Z")cmd.Stdin?=?strings.NewReader("some?input")var?out?bytes.Buffercmd.Stdout?=?&outerr?:=?cmd.Run()if?err?!=?nil?{log.Fatal(err)}fmt.Printf("in?all?caps:?%q\n",?out.String()) }這樣執行:
7. 使用append要注意的問題
1. 先看段簡單的代碼。
a := []int{1, 2, 3, 4, 5}
b = append(a[1:3], 8, 9)
這時fmt.Println(a)的結果是什么?
答案是: a = [1, 2, 3, 8, 9]
原因解答:a[1:3]返回的是一個new slice: b。不過這個b沿用了 a原有的空間。
2. 再看個新的
a := []int{1, 2, 3, 4, 5}
b = append(a[1:3], 8, 9, 10)
這時fmt.Println(a)的結果是什么?
答案是: a = [1, 2, 3, 4, 5]
原因解答: 因為這次append的數據超過了a的空間大小。所以系統重新開辟了一段空間給b。所以a的數據就不會修改了。
3. 在來一個
a := make([]int, 0, 6)
a = append(a, 1, 2, 3, 4, 5)
b = append(a[1:3], 8, 9, 10)
這時fmt.Println(a)的結果是什么?
答案是:(你大概應該猜到了) 是 a = [1, 2, 3, 8, 9]
原因嗎: 看看上一條解答,就明白了。也就是slice以cap空間為標準,沒有超過cap的空間,不會觸發空間的重新分配。
4. 補充一個
a := make([]int, 0, 6)
b := a[:3] // 這個語句合法嗎?
答案是合法的,雖然len(a) == 0, 不過slice取的是cap(a)。 只不過是b = [0, 0, 0]
轉載于:https://my.oschina.net/renguijiayi/blog/181822
總結
以上是生活随笔為你收集整理的golang小程序试验(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转) xcodebuild和xcrun
- 下一篇: shutdown,halt,reboot