Go操作MySQL
安裝: go get -u github.com/go-sql-driver/mysql
GO語(yǔ)言的操作數(shù)據(jù)庫(kù)的驅(qū)動(dòng)原生支持連接池, 并且是并發(fā)安全的 標(biāo)準(zhǔn)庫(kù)沒(méi)有具體的實(shí)現(xiàn) 只是列出了一些需要的第三方庫(kù)實(shí)現(xiàn)的具體內(nèi)容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//第一次連接MySQL成功 package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" // _想當(dāng)于init()初始化 "log" ) func main() { // root 用戶名 1qa2ws3ed是密碼 后邊的書ip:port gouse 庫(kù)名 dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } // ping是嘗試連接MySQL數(shù)據(jù)庫(kù) if err = db.Ping(); err != nil{ panic(err) } log.Fatalln("Mysql數(shù)據(jù)庫(kù)連接成功") } |
Go調(diào)用MySQL封裝成函數(shù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package main import ( "database/sql" "encoding/json" "fmt" _ "github.com/go-sql-driver/mysql" ) var db *sql.DB func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err = sql.Open("mysql", dsn) CheckErr(err) err = db.Ping() CheckErr(err) fmt.Println("數(shù)據(jù)庫(kù)連接成功...") // 設(shè)置數(shù)據(jù)庫(kù)連接池最大連接數(shù) db.SetConnMaxLifetime(10) //設(shè)置最大閑置連接數(shù) db.SetMaxIdleConns(5) return } type data struct { Username string `json:"username"` Password string `json:"password"` } func main() { err := InitDB() CheckErr(err) query, err := db.Query("select username, password from test") CheckErr(err) for query.Next(){ line := data{} // 查詢數(shù)據(jù)的時(shí)候必須要調(diào)用scan方法如果 沒(méi)有 使用scan 連接通道一直保持連接 無(wú)法釋放連接 _ = query.Scan(&line.Username, &line.Password) fmt.Println(line) dataDic := map[string]string{ "username": line.Username, "password": line.Password, } marshal, _ := json.Marshal(dataDic) fmt.Println(string(marshal)) } } func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } |
GO—MySQL的增刪改查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package main import ( "database/sql" "encoding/json" "fmt" "time" _ "github.com/go-sql-driver/mysql" ) var db *sql.DB // InitDB 數(shù)據(jù)庫(kù)連接初始化 func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err = sql.Open("mysql", dsn) CheckErr(err) err = db.Ping() CheckErr(err) fmt.Println("數(shù)據(jù)庫(kù)連接成功...") // 設(shè)置數(shù)據(jù)庫(kù)連接池最大連接數(shù) db.SetConnMaxLifetime(10) //設(shè)置最大閑置連接數(shù) db.SetMaxIdleConns(5) return } type data struct { Username string `json:"username"` Password string `json:"password"` } // SelectQuery 查詢函數(shù) func SelectQuery() { sqlStr := "select username, password from test where id > ?" query, err := db.Query(sqlStr, 1) CheckErr(err) defer query.Close() fmt.Printf("現(xiàn)在是北京時(shí)間 %s , 你今天進(jìn)步了嗎?\n", time.Now().Format("2006-01-02 15:04:05")) for query.Next() { line := data{} // 查詢數(shù)據(jù)的時(shí)候必須要調(diào)用scan方法如果 沒(méi)有 使用scan 連接通道一直保持連接 無(wú)法釋放連接 _ = query.Scan(&line.Username, &line.Password) //fmt.Println(line) dataDic := map[string]string{ "username": line.Username, "password": line.Password, } marshal, _ := json.Marshal(dataDic) fmt.Printf("查詢到的數(shù)據(jù)為 %s\n", string(marshal)) } } // InsertQuery 插入數(shù)據(jù) func InsertQuery() { // sql 語(yǔ)句 sqlStr := `insert into test (username,password) values ("kuQi", "123qwe")` result, err := db.Exec(sqlStr) CheckErr(err) id, err := result.LastInsertId() CheckErr(err) fmt.Printf("插入成功數(shù)據(jù)的id為 %v", id) } // UpdateQuery 更新數(shù)據(jù)函數(shù) func UpdateQuery(dataField string, user string) { sqlStr := `update test set password=? where username=?` result, err := db.Exec(sqlStr, dataField, user) CheckErr(err) rowsAffected, err := result.RowsAffected() CheckErr(err) fmt.Printf("被更新字段的id為%d\n", rowsAffected) } // DeleteQuery 刪除 func DeleteQuery(id int) { sqlStr := `delete from test where id=?` result, err := db.Exec(sqlStr, id) CheckErr(err) rowsAffected, err := result.RowsAffected() CheckErr(err) if rowsAffected == 0 { fmt.Printf("沒(méi)有匹配到要?jiǎng)h除的id=%d數(shù)據(jù)", id) return } fmt.Printf("刪除數(shù)據(jù)庫(kù)的id為%d", id) } //CheckErr 異常捕獲函數(shù) func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } // main 主函數(shù) 所有函數(shù)的入口 func main() { err := InitDB() CheckErr(err) //InsertQuery() UpdateQuery("hahaGolang123", "kuQi") SelectQuery() DeleteQuery(5) } |
MySQL的預(yù)處理
什么是預(yù)處理?
普通SQL語(yǔ)句執(zhí)行過(guò)程:
1.客戶端對(duì)SQL語(yǔ)句進(jìn)行占位符的替換得到了完整的SQL語(yǔ)句
2.客戶端發(fā)送完整SQL語(yǔ)句到MySQL服務(wù)端
3.MySQL服務(wù)端執(zhí)行完整的SQL語(yǔ)句并將結(jié)果返回終端
預(yù)處理的執(zhí)行過(guò)程
1.先把SQL語(yǔ)句拆分成兩部分,SQL語(yǔ)句部分和參數(shù)部分
2.先把SQL語(yǔ)句部分發(fā)送給MySQL服務(wù)端進(jìn)行SQL預(yù)處理
3.然后參數(shù)部分發(fā)送給MySQL服務(wù)端,MySQL對(duì)SQL語(yǔ)句進(jìn)行拼接
4.MySQL服務(wù)端執(zhí)行完整的SQL語(yǔ)句返回結(jié)果
為什么要進(jìn)行預(yù)處理?
1.為了優(yōu)化MySQL服務(wù)器重復(fù)執(zhí)行SQL的方法。可以執(zhí)行服務(wù)器的性能,提前讓服務(wù)器編譯,一次編譯多次執(zhí)行,節(jié)省后續(xù)重復(fù)編譯的成本
2.并且避免SQL注入
Go實(shí)現(xiàn)MySQL預(yù)處理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// prepare方法現(xiàn)將SQL發(fā)送到MySQL服務(wù)端, 返回一個(gè)準(zhǔn)備好的狀態(tài)用于之后的查詢和命令。返回值可以同時(shí)執(zhí)行多個(gè)查詢和命令 ; 命令也就是SQL語(yǔ)句 // PrepareInsert 預(yù)處理執(zhí)行插入語(yǔ)句 func PrepareInsert() { defer wg.Done() sqlStr := `insert into test (username, password) values (?, ?)` // - 預(yù)處理 stmt 就是編譯好的sql語(yǔ)句 之后直接傳遞參數(shù)即可 stmt, err := db.Prepare(sqlStr) var u1 = uuid.Must(uuid.NewV4()) CheckErr(err) defer stmt.Close() i := rand.Int() username := fmt.Sprintf("yonghuming%d", i) result, err := stmt.Exec(username, u1.String()[:10]) CheckErr(err) rowsAffected, err := result.LastInsertId() CheckErr(err) fmt.Printf("成功插入id=%d條數(shù)據(jù)\n", rowsAffected) } |
Go語(yǔ)言實(shí)現(xiàn)MySQL實(shí)現(xiàn)事務(wù)操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
// go語(yǔ)言中使用一下三個(gè)方法實(shí)現(xiàn)MySQL中的事務(wù)操作, 開始事務(wù) func (db *DB) Begin()(*Tx, error) // 提交事務(wù) 相當(dāng)與Python中的conn.commit() func (tx *Tx) Commit() error // 回滾事務(wù) func (tx *Tx) Rollback() error package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) var db *sql.DB type data struct { Username string `json:"username"` Password string `json:"password"` } // InitDB 數(shù)據(jù)庫(kù)連接初始化 func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err = sql.Open("mysql", dsn) CheckErr(err) err = db.Ping() CheckErr(err) fmt.Println("數(shù)據(jù)庫(kù)連接成功...") // 設(shè)置數(shù)據(jù)庫(kù)連接池最大連接數(shù) db.SetMaxOpenConns(100) //設(shè)置最大閑置連接數(shù) db.SetMaxIdleConns(5) return } //CheckErr 異常捕獲函數(shù) func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } // TranSaCtIon MySQL的事務(wù)操作 func TranSaCtIon() { // 開啟事務(wù) tx, err := db.Begin() CheckErr(err) // 執(zhí)行多個(gè)SQL操作 sqlStr := `update test set id=id+100000 where password=?` result, err := tx.Exec(sqlStr, "07f70f7e-4") CheckErr(err) id, err := result.LastInsertId() if err != nil { // 語(yǔ)句回滾 err := tx.Rollback() fmt.Println("事務(wù)回滾") CheckErr(err) } fmt.Printf("修改后的id為%d\n", id) } func main() { err := InitDB() CheckErr(err) TranSaCtIon() } |
sqlx使用
第三方庫(kù)sqlx能夠簡(jiǎn)化操作,提高開發(fā)效率
安裝go get github.com/jmoiron/sqlx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) var db *sqlx.DB // InitDB 數(shù)據(jù)庫(kù)初始化 func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err = sqlx.Connect("mysql", dsn) CheckErr(err) db.SetMaxOpenConns(50) db.SetMaxIdleConns(10) fmt.Println("goUse 數(shù)據(jù)庫(kù)連接成功") return } //CheckErr 異常捕獲函數(shù) func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } func main() { err := InitDB() CheckErr(err) } |
sqlx相較于原生的sql庫(kù)好處在于 查詢的時(shí)候sql原生的需要next scan 回調(diào)獲取結(jié)果
sqlx 查詢只需要定義一個(gè)存儲(chǔ)的變量 然后自動(dòng)就會(huì)將查詢的出來(lái)的值放入變量中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
package main import ( "encoding/json" "fmt" _ "github.com/go-sql-driver/mysql" "github.com/jmoiron/sqlx" ) var db *sqlx.DB type user struct { ID int `json:"id"` Username string `json:"username"` Password string `json:"password"` } // InitDB 數(shù)據(jù)庫(kù)初始化 func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" // Connect 就是連接的同時(shí)db.ping()一下 db, err = sqlx.Connect("mysql", dsn) CheckErr(err) db.SetMaxOpenConns(50) db.SetMaxIdleConns(10) fmt.Println("goUse 數(shù)據(jù)庫(kù)連接成功") return } // SelectDB 查詢單條數(shù)據(jù)的方法 func SelectDB() { sqlStr := `select * from test where id=?` var data user _ = db.Get(&data, sqlStr, 990) //CheckErr(err) fmt.Printf("%#v\n", data) marshal, err := json.Marshal(data) CheckErr(err) fmt.Println(string(marshal)) } // ManySelect 查詢多條數(shù)據(jù)方法 func ManySelect() { sqlStr := `select * from test where id < ?` var dataList []user err := db.Select(&dataList, sqlStr, 1000) CheckErr(err) //fmt.Println(dataList) marshal, err := json.Marshal(dataList) CheckErr(err) fmt.Println(string(marshal)) } //CheckErr 異常捕獲函數(shù) func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } func main() { err := InitDB() CheckErr(err) SelectDB() ManySelect() } |
Go操作Redis
安裝go get -u github.com/go-redis/redis
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package main import ( "fmt" "github.com/go-redis/redis" ) var redisDB *redis.Client // InitRedisDB redis數(shù)據(jù)庫(kù)初始化 func InitRedisDB() (err error) { redisDB = redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", Password: "", DB: 0, }) _, err = redisDB.Ping(redisDB.Context()).Result() CheckErr(err) fmt.Println("redis 連接成功") return } //CheckErr 異常捕獲函數(shù) func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } func main() { _ = InitRedisDB() } |
- set(key, value):給數(shù)據(jù)庫(kù)中名稱為key的string賦予值value
- get(key):返回?cái)?shù)據(jù)庫(kù)中名稱為key的string的value
- getset(key, value):給名稱為key的string賦予上一次的value
- mget(key1, key2,…, key N):返回庫(kù)中多個(gè)string的value
- setnx(key, value):添加string,名稱為key,值為value
- setex(key, time, value):向庫(kù)中添加string,設(shè)定過(guò)期時(shí)間time
- mset(key N, value N):批量設(shè)置多個(gè)string的值
- msetnx(key N, value N):如果所有名稱為key i的string都不存在
- incr(key):名稱為key的string增1操作
- incrby(key, integer):名稱為key的string增加integer
- decr(key):名稱為key的string減1操作
- decrby(key, integer):名稱為key的string減少integer
- append(key, value):名稱為key的string的值附加value
- substr(key, start, end):返回名稱為key的string的value的子串
NSQ分布式消息隊(duì)列
NSQ是目前比較流行的一個(gè)分布式消息隊(duì)列,下面主要是NSQ及GO語(yǔ)言如何操作NSQ
NSQ是GO語(yǔ)言編寫的一個(gè)開源的實(shí)時(shí)分布式內(nèi)存消息隊(duì)列, 其性能十分優(yōu)異, NSQ的優(yōu)勢(shì)有:
? 1.NSQ提倡分布式和擴(kuò)散的拓?fù)洌瑳](méi)有單點(diǎn)故障,支持容錯(cuò)和高可用性,并提供可靠的消息交付保證
? 2.NSQ支持橫向擴(kuò)展, 沒(méi)有任何集中式代理
? 3.NSQ易于配置和部署,并且內(nèi)置了管理界面
安裝go get -u github.com/nsqio/go-nsq
Context
在Go HTTP 包的server中,每一個(gè)請(qǐng)求都在對(duì)應(yīng)著一個(gè)響應(yīng),請(qǐng)求處理函數(shù)通常會(huì)啟動(dòng)額外的goroutine用來(lái)訪問(wèn)后端的服務(wù),比如數(shù)據(jù)庫(kù)和rpc服務(wù),用來(lái)處理一個(gè)請(qǐng)求的goroutine通常需要訪問(wèn)一些與請(qǐng)求特定的數(shù)據(jù),比如終端的身份認(rèn)證信息、驗(yàn)證相關(guān)的token、請(qǐng)求和截止時(shí)間。當(dāng)一個(gè)請(qǐng)求被取消或超時(shí)時(shí),所有用來(lái)處理該請(qǐng)求的goroutine都應(yīng)該迅速退出,然后系統(tǒng)才能釋放這些goroutine
如何優(yōu)雅的結(jié)束goroutine釋放資源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// 通道版本 package main import ( "fmt" "sync" "time" ) var wg sync.WaitGroup func worker(exitChan <-chan struct{}) { defer wg.Done() Test: for { fmt.Println("worker") time.Sleep(time.Second) select { case <-exitChan: break Test default: } } } func main() { wg.Add(1) c := make(chan struct{}) go worker(c) time.Sleep(10 * time.Second) c <- struct{}{} close(c) wg.Wait() fmt.Println("Over") } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// Context版本 package main import ( "context" "fmt" "sync" "time" ) var wg sync.WaitGroup func worker(ctx context.Context) { defer wg.Done() Test: for { fmt.Println("worker") time.Sleep(time.Second) select { case <-ctx.Done(): break Test default: } } } func main() { wg.Add(1) ctx, cancelFunc := context.WithCancel(context.Background()) go worker(ctx) time.Sleep(10 * time.Second) cancelFunc() wg.Wait() fmt.Println("Over") } |
如果goroutine開啟了新的goroutine,只需要將ctx傳入到新的goroutine中即可
Background() 和 TODO()
go內(nèi)置兩個(gè)函數(shù): Background() 和TUDO(),這兩個(gè)函數(shù)分別返回了一個(gè)實(shí)現(xiàn)了context接口的background和todo. 我們代碼中最開始都是以這兩個(gè)內(nèi)置的上下文對(duì)象作為最頂層的partent context,衍生出更多的子上下文對(duì)象。
backgroud() 主要用于main函數(shù),初始化以及代碼測(cè)試,作為context這個(gè)樹結(jié)構(gòu)的最頂層context,也就是跟context。
todo(),他目前還不知道能干點(diǎn)啥?
使用context的注意事項(xiàng)
- 推薦以參數(shù)顯示傳遞context
- 以context作為參數(shù)的函數(shù)方法,應(yīng)該把context作為第一個(gè)參數(shù)
- 給一個(gè)函數(shù)傳遞context的時(shí)候,不要nil,如果不知道傳遞什么,就使用context.TODO()
- context是并發(fā)安全的,可以隨意在多個(gè)goroutine中傳遞
log標(biāo)準(zhǔn)庫(kù)
log包定義了Logger類型, 該類型提供了一些格式化輸出的方法。本包也提供了一個(gè)預(yù)定義的標(biāo)準(zhǔn)logger,可以通過(guò)調(diào)用函數(shù)Print系列,fatal系列和panic系列來(lái)使用,比自行創(chuàng)建的logger對(duì)象更容易使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package main import "log" func main() { log.Println("這是第一條工作日志") v := "THIS is worker log" log.Printf("%#v\n", v) // Fatal將會(huì)值寫入信息之后,執(zhí)行exit(1) log.Fatal("之后寫一萬(wàn)行代碼 我也不執(zhí)行了哦") // 可以通過(guò)log.Panic 引發(fā)異常 會(huì)將日志寫入之后引發(fā)異常 log.Panic("測(cè)試panic的日志") } |
flag選項(xiàng)(日志輸出內(nèi)容設(shè)置)
log標(biāo)準(zhǔn)庫(kù)提供了如下的flag選項(xiàng),他們是一系列定義好的常量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
const ( Ldate = 1 << iota Ltime Lmicroseconds Llongfile Lshortfile LUTC LstdFlags = Ldate | Ltime ) package main import "log" func main() { // 設(shè)置默認(rèn)附加的內(nèi)容 log.SetFlags(log.Llongfile | log.Ltime) // 設(shè)置日志前綴 log.SetPrefix("[go_log] ") log.Println("測(cè)試日志") } output>>> [go_log] 19:02:14 /Users/mac/GolandProjects/src/day02/go_log庫(kù)/main.go:19: 測(cè)試日志 |
配置日志輸出位置
setoutput函數(shù)用來(lái)設(shè)置logger的輸出目的地,默認(rèn)是標(biāo)準(zhǔn)錯(cuò)誤輸出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package main import ( "log" "os" ) func main() { file, err := os.OpenFile("test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { log.Panic("文件打開失敗") } // 設(shè)置了寫入文件 日志內(nèi)容就不會(huì)打印到終端了 log.SetOutput(file) log.SetFlags(log.Llongfile | log.Ltime) log.SetPrefix("[go_log] ") log.Println("測(cè)試日志") } |
我們可以定義一個(gè)init初始化函數(shù) 將log全部配置好 這樣更加標(biāo)準(zhǔn)化
第三方日志庫(kù)logrus的使用
logrus是GO結(jié)構(gòu)化的logger 與上邊的logger標(biāo)準(zhǔn)庫(kù)完全兼容
安裝logrusgo get github.com/sirupsen/logrus
1
2
3
4
5
6
7
8
9
10
11
12
|
package main import ( log "github.com/sirupsen/logrus" ) func main() { log.WithFields(log.Fields{ "animals": "dog", "time": log.FieldKeyTime, }).Info("這是啥") } |
日志級(jí)別
Trace、debug、info、warning、error、fatal、panic
1
2
3
4
5
6
7
8
9
|
log.Trace("跟蹤?") log.Debug("Debug?") log.Info("信息") log.Warn("警告?") log.Error("Something failed but I'm not quitting.") // 記完日志后會(huì)調(diào)用os.Exit(1) log.Fatal("Bye.") // 記完日志后會(huì)調(diào)用 panic() log.Panic("I'm bailing.") |
日志記錄
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package main import ( "os" "time" log "github.com/sirupsen/logrus" ) func main() { file, err := os.OpenFile("logrustest.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) if err != nil { log.Panicln(err) } log.SetOutput(file) for i := 0; i < 100; i++ { log.WithFields(log.Fields{ "animals": "dog", "Countey": "China", "City": "BeiJing", }).Info("這是啥") time.Sleep(time.Second) } log.Trace("跟蹤?") log.Info("信息") log.Warn("警告?") // 設(shè)置日志級(jí)別, 會(huì)記錄info以上級(jí)別(warn error fatal panic) log.SetLevel(log.InfoLevel) } >>>結(jié)果 time="2021-02-04T12:00:15+08:00" level=info msg="這是啥" City=BeiJing Countey=China animals=dog time="2021-02-04T12:00:17+08:00" level=info msg="這是啥" City=BeiJing Countey=China animals=dog time="2021-02-04T12:00:18+08:00" level=info msg="這是啥" City=BeiJing Countey=China animals=dog time="2021-02-04T12:00:19+08:00" level=info msg="這是啥" City=BeiJing Countey=China animals=dog |
日志的條目除了使用withfield 和withfields添加的相關(guān)日志,還有一些默認(rèn)添加的日志字段
time 記錄日志的時(shí)間戳 msg 記錄日志信息 level記錄日志級(jí)別
日志格式化
logrus內(nèi)置一下兩種日志格式化程序
logrus.TextFormatter logrus.JSONFormatter
1
|
log.SetFormatter(&log.JSONFormatter{}) |
追蹤函數(shù)
1
|
log.SetReportCaller(true) |
這樣就會(huì)將哪個(gè)文件哪一行 都記錄下來(lái) 但是不是特殊需求無(wú)需開啟這個(gè) 因?yàn)闀?huì)增加性能開
到此這篇關(guān)于Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼的文章就介紹到這了,更多相關(guān)Go語(yǔ)言操作數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://www.cnblogs.com/zjaiccn/p/14667326.html