golang小程序试验(二)

golang小程序试验(二),第1张

概述1. golang程序运行时间显示 package mainimport ( "fmt" "time" "math/rand")func main(){ rand.Seed(time.Now().Unix()) var name string for i:=0; i<3; i++{ name=fmt.Sprintf("go_%02d", i) go runroutine 1. golang程序运行时间显示
packagemainimport(	"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+0800go_01startat2013-12-0517:22:34.5367151+0800+0800go_02startat2013-12-0517:22:34.5367151+0800+0800go_02endat2013-12-0517:22:36.5548305+0800+0800go_02lasted2.0181154sgo_00endat2013-12-0517:22:37.5558878+0800+0800go_00lasted3.0221729sgo_01endat2013-12-0517:22:38.5549449+0800+0800go_01lasted4.0182298sjDone
2. 利用mutex控制goroutine的执行
packagemainimport"fmt"import"time"import"math/rand"import"sync"import"runtime"//vartotal_ticketsint32=10varmutex=&sync.Mutex{}//可简写成:varmutexsync.Mutexfuncsell_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
packagemainimport"time"import"fmt"funcmain(){//创建两个channel-c1c2c1:=make(chanstring)c2:=make(chanstring)//创建两个goruntine来分别向这两个channel发送数据gofunc(){time.Sleep(time.Second*1)c1<-"Hello"}()gofunc(){time.Sleep(time.Second*1)c2<-"World"}()//使用select来侦听两个channelfor{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 } } }

关闭channel,总是在发送端关闭:

packagemainimport"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的阻塞通知机器来通知你的程序。

packagemainimport"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执行命令
packagemainimport(	"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命令行参数解析
packagemainimport(	"bytes"	"fmt"	"log"	"os/exec"	"strings")funcmain(){	cmd:=exec.Command("tr",out.String())}

这样执行:

#如果没有指定参数名,则使用默认值$gorunflagtest.gohost:coolshell.cnport:80deBUG:false#指定了参数名后的情况$gorunflagtest.go-host=localhost-port=22-dhost:localhostport:22deBUG:true#用法出错了(如:使用了不支持的参数,参数没有=)$gobuildflagtest.go$./flagtest-deBUG-hostlocalhost-port=22flagprovIDedbutnotdefined:-deBUGUsageofflagtest:-d=false:enable/DisabledeBUGmode-host="coolshell.cn":ahostname-port=80:aportnumberexitstatus2
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]

总结

以上是内存溢出为你收集整理的golang小程序试验(二)全部内容,希望文章能够帮你解决golang小程序试验(二)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1292266.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存