keer_zu 发表于 2019-1-17 09:59

【原创】一个go语言小项目实例:通过select监控channel并阻塞

本帖最后由 keer_zu 于 2019-1-17 15:13 编辑

(利用这个简单小原理实现的一个小项目,监控最新创建的,拥有多级深度的文件夹变化内容,并将最新产生的文件通过tcp或者http发送给连上来的tcp客户端和http服务端:
这个小项目源码




这是一个简单的例子:


package main

import (
"fmt"
"time"
)

func generateString(strings chan string) {
    time.Sleep(3*time.Second)
    strings <- "Monday"
    time.Sleep(5*time.Second)
    strings <- "Tuesday"
    time.Sleep(3*time.Second)
    strings <- "Wednesday"
    time.Sleep(5*time.Second)
    strings <- "Thursday"
    strings <- "Friday"
    strings <- "Saturday"
    strings <- "Sunday"
    close(strings)
}


func monitor(cancel chan string) {

    var stop bool = false
      for {
            time.Sleep(1*time.Second)
            fmt.Println("i am alive!")
            select {
                case can := <- cancel:
                  if can == "cancel" {
                        fmt.Println("break!")
                        stop = true
                        break
                  }
                  
            }

            if stop {
                break
            }
      }


    fmt.Println("good bye!")
}

func main() {
    //strings := make(chan string) // 无缓冲channel
    cancel_sig := make(chan string)

    //go generateString(strings)

    //for s := range strings {
    //    fmt.Println(s)
    //}

    go monitor(cancel_sig)

    time.Sleep(10*time.Second)

    cancel_sig <- "cancel"

    for {
      time.Sleep(5*time.Second)
      fmt.Println("go away!")
      break
    }
}



如果有多个channel,也可以被一个select监听,例如:


package notify;

import (
    "github.com/fsnotify/fsnotify"
    "github.com/smtp-http/filemonitor_macmini/conn"
    "github.com/smtp-http/filemonitor_macmini/config"
    "log"
    "fmt"
    "path/filepath"
    "path"
    "io/ioutil"
    "sync"
)

type FileMonitor struct {
    m_tcpserver *conn.TcpServer
}

var instance *FileMonitor
var once sync.Once

func GetFileMonitorInstance() *FileMonitor {
    once.Do(func() {
      instance = &FileMonitor{}
    })
    return instance
}

func (f *FileMonitor)SetTcpserver(server *conn.TcpServer) {
    f.m_tcpserver = server
}

func (f *FileMonitor)Monitor(cancel chan string) {

    var stop bool = false

    //创建一个监控对象
    watch, err := fsnotify.NewWatcher();
    if err != nil {
      log.Fatal(err);
    }
    defer watch.Close();
    //
    err = watch.Add(config.GetConfig().Path);
    if err != nil {
      log.Fatal(err);
    }
    //我们另启一个goroutine来处理监控对象的事件

    for {
      fmt.Println("--- 1")
      if stop {
            break
      }
      select {
            case ev := <-watch.Events:
                {
                  //判断事件发生的类型,如下5种
                  // Create 创建
                  // Write 写入
                  // Remove 删除
                  // Rename 重命名
                  // Chmod 修改权限
                  if ev.Op&fsnotify.Create == fsnotify.Create {
                        fmt.Println("创建文件 : ", ev.Name);
                  }
                  if ev.Op&fsnotify.Write == fsnotify.Write {
                        fmt.Println("写入文件 : ", ev.Name);
                        paths, fileName := filepath.Split(ev.Name)
                        fmt.Println(paths, fileName) //获取路径中的目录及文件名 E:\data\ test.txt
                        fmt.Println(filepath.Base(ev.Name)) //获取路径中的文件名test.txt
                        

                        if path.Ext(ev.Name) == config.GetConfig().FileExtension {
                            fmt.Println(path.Ext(ev.Name)) //获取路径中的文件的后缀 .txt
                            b, err := ioutil.ReadFile(ev.Name)
                            if err != nil {
                              fmt.Print(err)
                            }
                            fmt.Println(b)
                            //str := string(b)
                        
                            f.m_tcpserver.Notify(b)
                            configure := config.GetConfig()
                            if configure.HttpEnable == true {
                              httpClient := conn.GetHttpClientInstance()
                              httpClient.HttpPost(b)
                            }

                        }

                        
                  }

                  if ev.Op&fsnotify.Remove == fsnotify.Remove {
                        fmt.Println("删除文件 : ", ev.Name);
                  }

                  if ev.Op&fsnotify.Rename == fsnotify.Rename {
                        fmt.Println("重命名文件 : ", ev.Name);
                  }
                  
                  if ev.Op&fsnotify.Chmod == fsnotify.Chmod {
                        fmt.Println("修改权限 : ", ev.Name);
                  }
                }

            case can := <- cancel:
                if can == "cancel" {
                  fmt.Println("break!")
                  stop = true
                  break
                }
            case err := <-watch.Errors:
                {
                  log.Println("error : ", err);
                  return;
                }
      }
    }

    fmt.Println("good bye!")
}









keer_zu 发表于 2019-1-17 11:19

github代码持续更新中。。。。。


代码参考:monitor.go

icecut 发表于 2019-1-18 10:07

strings是一个标准包名.尽量避免使用

keer_zu 发表于 2019-1-18 13:28

icecut 发表于 2019-1-18 10:07
strings是一个标准包名.尽量避免使用

{:handshake:}

zzdsj2 发表于 2019-1-19 14:02

666{:lol:}

jndnhdndfn 发表于 2019-6-18 20:09

也有啊,前天不是你也到一个很狂的贴里去了吗?
页: [1]
查看完整版本: 【原创】一个go语言小项目实例:通过select监控channel并阻塞