使用golang的timer
定時(shí)任務(wù)
func demo(input chan interface{}) {
t1 := time.NewTimer(time.Second * 5)
t2 := time.NewTimer(time.Second * 10)
for {
select {
case msg <- input:
println(msg)
case <-t1.C:
println("5s timer")
t1.Reset(time.Second * 5)
case <-t2.C:
println("10s timer")
t2.Reset(time.Second * 10)
}
}
}
斷續(xù)器
func main(){
ticker := time.NewTicker(time.Second)
for t := range ticker.C {
fmt.Println("ticker", t)
}
}
超時(shí)
func main(){
ch1 := make(chan int, 1)
ch2 := make(chan int, 1)
select {
case e1 := <-ch1:
//如果ch1通道成功讀取數(shù)據(jù),則執(zhí)行該case處理語句
fmt.Printf("1th case is selected. e1=%v",e1)
case e2 := <-ch2:
//如果ch2通道成功讀取數(shù)據(jù),則執(zhí)行該case處理語句
fmt.Printf("2th case is selected. e2=%v",e2)
case <- time.After(2 * time.Second):
fmt.Println("Timed out")
}
}
自定義定時(shí)器
func main(){
var t *time.Timer
f := func(){
fmt.Printf("Expiration time : %v.\n", time.Now())
fmt.Printf("C`s len: %d\n", len(t.C))
}
t = time.AfterFunc(1*time.Second, f)
//讓當(dāng)前Goroutine 睡眠2s歼疮,確保大于內(nèi)容的完整
//這樣做原因是板鬓,time.AfterFunc的調(diào)用不會(huì)被阻塞灸芳。它會(huì)以一部的方式在到期事件來臨執(zhí)行我們自定義函數(shù)f侵续。
time.Sleep(2 * time.Second)
}
使用時(shí)間控制停止ticker
func main(){
//初始化斷續(xù)器,間隔2s
var ticker *time.Ticker = time.NewTicker(1 * time.Second)
go func() {
for t := range ticker.C {
fmt.Println("Tick at", t)
}
}()
time.Sleep(time.Second * 5) //阻塞,則執(zhí)行次數(shù)為sleep的休眠時(shí)間/ticker的時(shí)間
ticker.Stop() //停止ticker
fmt.Println("Ticker stopped")
}
并發(fā)讀取文件夾所有文件的長度(使用通道)
func test1() {
// 遍歷文件夾渊抄,獲取文件名
dir := "./db"
paths, err := ioutil.ReadDir(dir)
check(err)
var files []string
for _, path := range paths {
if !path.IsDir() {
files = append(files, path.Name())
}
}
type FileInfo struct {
FileName string
Len int
Err error
}
way := make(chan FileInfo, 100)
for _, file := range files {
go func(fileName string) {
content, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", dir, fileName))
// 無論對(duì)錯(cuò)足淆,都交給通道收取方
way <- FileInfo{
FileName: fileName,
Len: len(content),
Err: err,
}
}(file)
}
// 我們知道需要從通道中取多少條數(shù)據(jù)
for i := 0; i < len(files); i++ {
fileInfo := <-way
if fileInfo.Err != nil {
fmt.Printf("[err] file:%s, err: %s \n", fileInfo.FileName, fileInfo.Err.Error())
return
}
fmt.Printf("file:%s, len: %d \n", fileInfo.FileName, fileInfo.Len)
}
}
并發(fā)讀取文件夾所有文件的長度(使用sync.WaitGroup)
這個(gè)使用的其實(shí)就是計(jì)數(shù)器的道理
func test1() {
dir := "./db"
paths, err := ioutil.ReadDir(dir)
check(err)
var files []string
for _, path := range paths {
if !path.IsDir() {
files = append(files, path.Name())
}
}
// sizes用來計(jì)算總長度和阻塞直至所有g(shù)oroutine走完
sizes := make(chan int64)
// 計(jì)數(shù)器
var wg sync.WaitGroup
for _, file := range files {
wg.Add(1)
go func(fileName string) {
defer wg.Done()
fileInfo, _ := os.Stat(fmt.Sprintf("%s/%s", dir, fileName))
sizes <- fileInfo.Size()
}(file)
}
go func() {
wg.Wait()
close(sizes)
}()
var total int64
for size := range sizes {
fmt.Printf("size:%d\n", size)
total += size
}
fmt.Printf("total size: %d\n", total)
}
令牌-另一種信號(hào)計(jì)數(shù)器
func check(err error) {
if err != nil {
panic(err)
}
}
func main() {
// 鏈接列表
workList := make(chan []string)
// 存儲(chǔ)已經(jīng)處理的鏈接巢块,使用map是為了去重
seen := make(map[string]bool)
// n是為了保證爬蟲一直爬
n := 1
// 初始化
go func() { workList <- []string{"http://www.reibang.com"} }()
for i := n; i > 0; i++ {
list := <-workList
for _, link := range list {
if !seen[link] {
seen[link] = true
n++
go func(link string) {
workList <- crawl(link)
}(link)
}
}
}
}
var tokens = make(chan struct{}, 20)
// 獲取網(wǎng)頁的鏈接 通過令牌
func crawl(url string) (list []string) {
fmt.Println(url)
tokens <- struct{}{}
list, err := Extract(url)
<-tokens
if err != nil {
log.Print(err)
return
}
return
}
// 獲取網(wǎng)頁的鏈接
func Extract(url string) (list []string, err error) {
resp, err := http.Get(url)
if err != nil {
return
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
return nil, fmt.Errorf("getting %s, err %s", url, err.Error())
}
doc, err := html.Parse(resp.Body)
resp.Body.Close()
if err != nil {
return nil, fmt.Errorf("parsing %s as HTML, err %s", url, err.Error())
}
visitNode := func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key != "href" {
continue
}
link, err := resp.Request.URL.Parse(a.Val)
if err != nil {
continue
}
list = append(list, link.String())
}
}
}
// 將函數(shù)作為參數(shù)傳入(匿名函數(shù))
forEachNode(doc, visitNode, nil)
return
}
func forEachNode(n *html.Node, pre, next func(node *html.Node)) {
if pre != nil {
pre(n)
}
for n := n.FirstChild; n != nil; n = n.NextSibling {
forEachNode(n, pre, next)
}
if next != nil {
next(n)
}
}
個(gè)人博客:http://blog.xbug.site