go☞012常用模块的记录

阅读量: zyh 2020-11-20 15:24:12
Categories: > Tags:

log

log 是内置模块,无需导入

# 直接打印
log.Print("Hey, I'm a log!")
2020/12/19 13:39:17 Hey, I'm a log!

# 设置前缀
log.SetPrefix("main():")
main(): 2021/01/05 13:59:58 Hey, I'm a log!

# 输出日志的同时退出程序,就如同执行os.Exit(1)
log.Fatal("Hey, I'm an error log!")

# 输出日志的同时执行 panic()
log.Panic("Hey, I'm an error log!")

# 输出日志到文件,file是打开的文件描述符
log.SetOutput(file) 
log.Print("Hey, I'm a log!")

zerolog

https://github.com/rs/zerolog

日志框架,扩展log模块。通过日志框架可以设置日志级别或者配置不同的日志输出。

go get -u github.com/rs/zerolog/log
package main

import (
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"
)

func main(){
    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
    log.Print("Hey!I'm a log message")
    log.Debug().
        Int("EmployeeID", 1001).
        Msg("Getting Employee Information")
    log.Debug().Str("Name", "John").Send()
}

输出:

{"level":"debug","time":1645513637,"message":"Hey!I'm a log message"}
{"level":"debug","EmployeeID":1001,"time":1645513637,"message":"Getting Employee Information"}
{"level":"debug","Name":"John","time":1645513637}

os

os package - os - pkg.go.dev

文件

os.OpenFile

func OpenFile(name string, flag int, perm FileMode) (*File, error)

os.OpenFile根据flag模式来创建/打开一个文件

这里的返回值*File其实也是io.Reader,都是textual I/O这一类. 因此,*File也可以被用于bufioio模块

常用的flag组合:

os.O_CREATE|os.O_RDWR 创建并可读可写

os.O_CREATE|os.O_RDWR|os.O_APPEND创建并可读可写可追加

⚠️需要注意的是,os.O_APPEND将始终如一的将指针定位到尾部,因此*File.Seek无法使用,所以你也无法实现计算文件行数之类的方法(因为你无法定位到首部)。

全路径

os.Executable() 返回可执行程序的全路径

func Executable() (string, error)

⚠️ 但在符号链接的情况下,可能返回的是符号链接的路径或者其指向的路径

命令行参数

os.Args []string ,其os.Args[0]是程序名

退出程序

os.Exit(code int) ,以指定的code退出程序,按照通常做法,你应该以0表示正常退出,非0表示异常

⚠️它会导致defer不执行

os/user

获取当前用户信息

userInfo, err := user.Current()
if err != nil {
    fmt.Println("Error: get current user")
} else {
    userName := userInfo.Username
}

os/exec

执行命令

cmd := appPath + " " + appArgs
if _, err := exec.LooPath(appPath); err != nil {
    fmt.Printf("Error: %s not found\n", appPath)
} else {
    c := exec.Command("bash", "-c", cmd)
    output, err := c.CombineOutput()
    if err != nil {
        fmt.Printf("Error: %s\n", output)
    } else {
        fmt.Printf("Success: %s\n", output)
    }
}

bytes

字节对比

if bytes.Equal(aByte, bByte) {
    fmt.Println("两者相同")
}

path/filepath

获取文件名和路径

if fullPath, err := os.Executable()	; err != nil {
	fmt.Printf("Error executing")	
} else {
	basePath, baseName := filepath.Split(fullPath)    
}

bufio

实现带缓存的I/O

io 和 os

读写文件或者文件描述符的内容

💁另外,io/ioutil 也可以实现io和os里的一些文件相关的方法,但是他们已经迁移到了io和os

fd, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0755)
defer fd.Close()
if err != nil {
    fmt.Printf("Error(open): %s\n", filePath)
} else {
    fByte, err := io.ReadAll(fd)
    if err != nil {
        fmt.Printf("Error(read): %s\n", err)
    } else {
        fmt.Printf("file content:\n %s\n", fByte)
    }
}

mysql

sql package - database/sql - pkg.go.dev

import (
    "database/sql"
	_ "github.com/go-sql-driver/mysql"
)

func main(){
	mysqlConnect := fmt.Sprintf("%s:%s@tcp(%s)/mysql", conf.Database.Username, conf.Database.Password, 	conf.Database.Host)
    if err != nil {
        errors.New("Error mysql connect")
        return
    }
    db.SetConnMaxLifetime(100*time.Second)  //最大连接周期,超过时间的连接就close
    db.SetMaxOpenConns(10) //设置最大连接数
    db.SetMaxIdleConns(5) //设置闲置连接
    rows, err := db.Query("show full processlist")
    if err != nil {
        errors.New("Error db Query")
        return
    }  
    var Id,Time int64
    var User, Host, Command, State string
    var Db, Info sql.NullString
    for rows.Next() {
        rows.Scan(&Id, &User, &Host, &Db, &Command, &Time, &State, &Info)
    	fmt.Printf("%d,%s,%s,%s,%s,%d,%s,\"%s\"\n", Id, User, Host, Db.String, Command, Time, State, Info.String
}

rows.Next()读取一行,并指向行尾

rows.Scan(dest ...interface{})将当前行的值逐个字段的复制给dest,dest是指针类型。dest顺序和当前行的字段顺序需要一一对应。

gopkg.in/gomail.v2

gomail package - gopkg.in/gomail.v2 - pkg.go.dev

func sendEmail(smtpServer string, smtpPort int, smtpUser string, smtpPassword string, receiveUser []string, subject string, content string, attach string) error {
    m := gomail.NewMessage()
    m.SetHeader("From", smtpUser)
    m.SetHeader("To", receiveUser...)
    m.SetHeader("Subject", subject)
    m.SetBody("text/html", content)
    m.Attach(attach)

    d := gomail.NewDialer(smtpServer, smtpPort, smtpUser, smtpPassword)
    err := d.DialAndSend(m)
    return err
}

gopkg.in/yaml.v3

yaml package - gopkg.in/yaml.v3 - pkg.go.dev

配置文件示例

email:
  smtpserver: smtp.feishu.cn
  smtpport: 465
  smtpuser: 
  smtppassword: 
  receiveuser: 
    - [email protected]
  subject: 
  content: 
database:
  host: 
  username: 
  password: 
  timeout: 
//映射配置文件的结构体
type Config struct {
    Email struct {
        Smtpserver string `yaml:"smtpserver"`
        Smtpport int `yaml:"smtpport"`
        Smtpuser string `yaml:"smtpuser"`
        Smtppassword string `yaml:"smtppassword"`
        Receiveuser []string `yaml:"receiveuser"`
        Subject string `yaml:"subject"`
        Content string `yaml:"content"`
    }
    Database struct {
        Host string `yaml:"host"`
        Username string `yaml:"username"`
        Password string `yaml:"password"`
        Timeout int64 `yaml:"timeout"`
    }
}

//实现结构体方法 getConf
func (config *Config) getConf(confPath string) (*Config) {
    yamlFile, err := ioutil.ReadFile(confPath)
    if err != nil {
        fmt.Println("Error reading config")
    }
    err = yaml.Unmarshal(yamlFile, config)
    if err != nil {
        fmt.Println("Error unmarshaling config")
    }
    return config
}

func main(){
    var config Config
    conf := config.getConf("/to_path/config.yaml")
    fmt.Println(conf.Email.Smtpserver)
}

⚠️定义配置文件映射的结构体的时候,属性首字母要大写

encoding/json

https://pkg.go.dev/encoding/json

https://json2struct.mervine.net/ json转struct

构造json对象,用来传递参数

import "encoding/json"	
postMap := map[string]string{"username": username, "password": password}
postJson, err := json.Marshal(postMap) // postJson 已经是[]byte
if err != nil {
    fmt.Println("Error:json.Marshal")
}

解析json对象,获取对象值

import (
    "encoding/json"
    "fmt"
)

func main(){
    var bodyByte = []byte(`[
        {"Name": "Platypus", "Order": "Monotremata"},
        {"Name": "Quoll",    "Order": "Dasyuromorphia"}
    ]`)
    type Animal struct {
        Name  string
        Order string
    }
    var animals []Animal
    if err := json.Unmarshal(bodyByte, &animals); err != nil {
        fmt.Println(err)
    } else {
        for _, val := range animals {
            fmt.Printf("Name:%s, Order:%s\n", val.Name, val.Order)
        }
    }
}

输出:

Name:Platypus, Order:Monotremata
Name:Quoll, Order:Dasyuromorphia

注意点

以小写字母开头的结构体字段不会被编码进去

package main

import (  
    "fmt"
    "encoding/json"
)

type MyData struct {  
    One int
    two string
}

func main() {  
    in := MyData{1,"two"}
    fmt.Printf("%#v\n",in) //prints main.MyData{One:1, two:"two"}

    encoded,_ := json.Marshal(in)
    fmt.Println(string(encoded)) //prints {"One":1}  这里可以看出two:"two"没有被编码进去

    var out MyData
    json.Unmarshal(encoded,&out)

    fmt.Printf("%#v\n",out) //prints main.MyData{One:1, two:""}
}

time

time package - time - pkg.go.dev

go采用一种很独特的方式来格式化时间,即:

2006数字代表年,如同常见的%Y

01数字代表月,如同常见的%m

02数字代表日

15数字代表时(24小时的下午三点)

04数字代表分

05数字代表秒

Z07数字代表时区(-07也可以)

整体记忆方法就是:01、02、15(03)、04、05、2006(06)、Z07(07)

time.Now().Format("2006.01.02 15:04:05 Z07")

转时区

package main

import (
    "fmt"
    "time"
)

func main(){
    currenttime := time.Now()
    time_zone, _ := time.LoadLocation("Asia/Shanghai")
    fmt.Println(currenttime.In(time_zone).Format("2006-01-02-15-04-05"))
}

net/http

https://pkg.go.dev/net/http

import "net/http"
func GetUser(url, path, username string, password string) (UserJson, error) {
	client := &http.Client{} // 创建客户端
	postMap := map[string]string{"username": username, "password": password}
	postJson, err := json.Marshal(postMap)
	if err != nil {
		fmt.Println("Error json.Marshal")
	}
	request, err := http.NewRequest(http.MethodPost, url+path, bytes.NewBuffer(postJson)) // 创建请求体
	if err != nil {
		fmt.Println("Error http.NewRequest")
	}
	request.Header.Set("Content-Type", "application/json") // 添加类型
	response, err := client.Do(request)
	if err != nil {
		fmt.Println("Error client do request")
	}
	bodyByte, err := io.ReadAll(response.Body)
	defer response.Body.Close()
	var user UserJson
	if err := json.Unmarshal(bodyByte, &user); err != nil {
		fmt.Println("Error json unmarshal response userjson")
	}
	return user, err
}

func main() {
    myuser, err := GetUser(acmeServer, "/api/user/", authuser, authpasswd)
}

https://pkg.go.dev/github.com/ghodss/[email protected]