基于:https://www.topgoer.cn/整理提取
操作文件
文件操作api
- func Create(name string) (file *File, err Error)
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666 - func NewFile(fd uintptr, name string) *File 根据文件描述符创建相应的文件,返回一个文件对象
- func Open(name string) (file *File, err Error) 只读方式打开一个名称为name的文件
- func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限 - func (file *File) Write(b []byte) (n int, err Error) 写入byte类型的信息到文件
- func (file *File) WriteAt(b []byte, off int64) (n int, err Error) 在指定位置开始写入byte类型的信息
- func (file *File) WriteString(s string) (ret int, err Error) 写入string信息到文件
- func (file *File) Read(b []byte) (n int, err Error) 读取数据到b中
- func (file *File) ReadAt(b []byte, off int64) (n int, err Error) 从off开始读取数据到b中 func Remove(name string) Error 删除文件名为name的文件
拷贝文件
srcFile, err := os.Open("./xxx.txt") //打开文件
if err != nil{
fmt.Println(err)
return
}
dstFile, err := os.Create("./abc2.txt") //创建文件
if err != nil{
fmt.Println(err)
return
}
buf := make([]byte,1024)
for{
length, err := srcFile.Read(buf)
if err == io.EOF { //到尾部
fmt.Println("读取完毕")
break
}
if err != nil{
fmt.Println(err)
break
}
dstFile.Write(buf[:length])
}
srcFile.Close()
dstFile.Close()
ioutil工具包,更简单操作
//创建并写入
err := ioutil.WriteFile("./yyy.txt", []byte("www.5lmh.com"), 0666) //0666是个权限值
if err != nil {
fmt.Println(err)
}
//读取
content, err := ioutil.ReadFile("./yyy.txt")
if err != nil {
fmt.Println(err)
}
fmt.Println(string(content))
定时器
内置包time
倒计时
利用管道做的倒计时,管道一致阻塞,直到timer.c有数据或关闭,select捕获管道数据,执行
timer := time.NewTimer(5 * time.Second)
//timer.Stop() 停止定时器
//timer.Reset() 重置倒计时
select {
case <-timer.C:
fmt.Println("五秒结束")
}
定时器
ticker := time.NewTicker(1 * time.Second)
for {
select {
case <- ticker.C:
log.Println("定时器")
}
}
//ticker.Stop()
//for range ticker.C{
// log.Println("定时器")
//}
有时,我们希望把一些任务打包进行批量处理。比如,公交车发车场景:
- 公交车每隔5分钟发一班,不管是否已坐满乘客;
- 已坐满乘客情况下,不足5分钟也发车;
下面代码演示公交车发车场景:
func TickerLaunch() {
ticker := time.NewTicker(5 * time.Minute)
maxPassenger := 30 // 每车最大装载人数
passengers := make([]string, 0, maxPassenger)
for {
passenger := GetNewPassenger() // 获取一个新乘客
if passenger != "" {
passengers = append(passengers, passenger)
} else {
time.Sleep(1 * time.Second)
}
select {
case <- ticker.C: // 时间到,发车
Launch(passengers)
passengers = []string{}
default:
if len(passengers) >= maxPassenger { // 时间没到,车已座满,发车
Launch(passengers)
passengers = []string{}
}
}
}
}
上面代码中for循环负责接待乘客上车,并决定是否要发车。每当乘客上车,select语句会先判断ticker.C中是否有数据,有数据则代表发车时间已到,如果没有数据,则判断车是否已坐满,坐满后仍然发车。
Cron(定时器)
基本格式
字段说明:
-
星号(*) 表示 cron 表达式能匹配该字段的所有值。如在第5个字段使用星号(month),表示每个月
-
斜线(/) 表示增长间隔,如第1个字段(minutes) 值是 3-59/15,表示每小时的第3分钟开始执行一次,之后每隔 15 分钟执行一次(即 3、18、33、48 这些时间点执行),这里也可以表示为:3/15
-
逗号(,) 用于枚举值,如第6个字段值是 MON,WED,FRI,表示 星期一、三、五 执行
-
连字号(-) 表示一个范围,如第3个字段的值为 9-17 表示 9am 到 5pm 直接每个小时(包括9和17)
-
问号(?) 只用于日(Day of month)和星期(Day of week),\表示不指定值,可以用于代替
举例:
- 每隔5秒执行一次:*/5 * * * * ?
- 每隔1分钟执行一次:0 */1 * * * ?
- 每天23点执行一次:0 0 23 * * ?
- 每天凌晨1点执行一次:0 0 1 * * ?
- 每月1号凌晨1点执行一次:0 0 1 1 * ?
- 在26分、29分、33分执行一次:0 26,29,33 * * * ?
- 每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?
使用:
import (
"fmt"
"github.com/robfig/cron"
)
i := 0
c := cron.New()
spec := "*/5 * * * * ?"
err:=c.AddFunc(spec, func() {
i++
log.Println("cron running:", i)
})
fmt.Println(err)
c.Start()
select {}//用于阻塞主程序,或者一直重置倒计时,不让主程序退出
多个定时任务
import (
"fmt"
"log"
"github.com/robfig/cron"
)
type TestJob struct {
}
func (this TestJob) Run() {
fmt.Println("testJob1...")
}
type Test2Job struct {
}
func (this Test2Job) Run() {
fmt.Println("testJob2...")
}
func main() {
i := 0
c := cron.New()
//AddFunc
spec := "*/5 * * * * ?"
c.AddFunc(spec, func() {
i++
log.Println("cron running:", i)
})
//AddJob方法
c.AddJob(spec, TestJob{})
c.AddJob(spec, Test2Job{})
//启动计划任务
c.Start()
//关闭着计划任务, 但是不能关闭已经在执行中的任务.
defer c.Stop()
select {}
}
Http
resty包
github.com/go-resty/resty/v2
可以直接post一个接口,而不是byte
var data interface{}
uri = "www.baidu.com"
client := resty.New()
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(data).Post(uri)
检查请求返回的code
res, err := http.Get(uri)
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body) //读取byte
var result map[string]interface{}
json.Unmarshal(body,&result) //解码成设计的map[string]interface{}
codeValue, ok := result["code"]
var code int
switch codeValue.(type) { //断言
case float32:
code = int(codeValue.(float32))
case float64:
code = int(codeValue.(float64))
case int8:
code = int(codeValue.(int8))
case int16:
code = int(codeValue.(int8))
case int32:
code = int(codeValue.(int8))
default:
code = 404
}
插件
viper(读取配置文件)
"github.com/spf13/viper"
//默认yaml文件
viper.SetConfigName("cfg") //读取配置文件名
viper.AddConfigPath("conf") //目录
err := viper.ReadInConfig()
if err != nil{
panic(err)
}
DbUser := viper.GetString("mysql.DbUser") //读取字段