網站首頁 編程語言 正文
從本文開始,我們來看一下如何從零搭建一個 Go 項目。
回顧一下基礎的 Go 項目運行過程
首先,新建一個?sports
?的文件,然后鍵入此文件目錄下,選擇在終端中打開,使用如下命令初始化項目:
go mod init sports
然后,我們創建一個?main.go
?的文件,寫入如下代碼:
package main import "fmt" func writeMessage() { fmt.Println("Let's Go") } func main() { writeMessage() }
回到終端,編譯并執行我們的項目:
go run .
就像之前第一次寫一個?HelloWorld
?項目一樣,run
?命令會成功編譯并執行我們的?Println()
?內的字符串 Let's Go,輸出結果如下:
$ go run . Let's Go
創建一些基本的項目功能
眾所周知,Web 應用有一些基礎的服務和功能如日志、文件配置等等。所以我們可以為?sports
?項目提供一些基本的服務,這些服務將為運行網絡應用程序提供基礎。
創建日志接口 Logger
先來實現第一個服務器功能——日志。Go 標準庫中的?log
?包為創建日志提供了一套非常用戶友好的基本功能,但在實際開發過程中,仍需要一些額外的功能來篩選一些信息詳情。
創建?sports/logging
?文件夾,然后在這個文件夾下面創建一個?logging.go
?文件,然后寫入如下代碼:
package logging type LogLevel int const ( Trace LogLevel = iota Debug Information Warning Fatal None ) type Logger interface { Trace(string) Tracef(string, ...interface{}) Debug(string) Debugf(string, ...interface{}) Info(string) Infof(string, ...interface{}) Warn(string) Warnf(string, ...interface{}) Panic(string) Panicf(string, ...interface{}) }
上面的代碼定義了?Logger
?接口,并具體聲明了具體的日志消息的具體方法,分別有著不同的日志級別,LogLevel
?從?Trace
?到?Fatal
?。值得注意的是也有一個無級別的?None
, 意味著沒有日志輸出。
對于每個級別的重要性,Logger
?接口定義兩個方法:
- 一個用于接受簡單字符串的方法,如?
Debug
- 一個用于接收模板字符串和占位符值的方法,如?
Debugf
將日志功能定義為接口的好處是:在需要更改或替換功能時,只需要更改實現,我們的調用接口并不需要改變;接口也使得功能作為服務提供給應用程序。
Logger 接口的具體實現
日志接口定義好了之后,我們來創建具體的?Logger
?接口的實現。
創建一個?logger_default.go
?的文件,然后寫入如下的代碼:
package logging import ( "fmt" "log" ) type DefaultLogger struct { minLevel LogLevel loggers map[LogLevel]*log.Logger triggerPanic bool } func (l *DefaultLogger) MinLogLevel() LogLevel { return l.minLevel } func (l *DefaultLogger) write(level LogLevel, message string) { if l.minLevel <= level { l.loggers[level].Output(2, message) } } func (l *DefaultLogger) Trace(msg string) { l.write(Trace, msg) } func (l *DefaultLogger) Tracef(template string, vals ...interface{}) { l.write(Trace, fmt.Sprintf(template, vals...)) } func (l *DefaultLogger) Debug(msg string) { l.write(Debug, msg) } func (l *DefaultLogger) Debugf(template string, vals ...interface{}) { l.write(Debug, fmt.Sprintf(template, vals...)) } func (l *DefaultLogger) Info(msg string) { l.write(Information, msg) } func (l *DefaultLogger) Infof(template string, vals ...interface{}) { l.write(Information, fmt.Sprintf(template, vals...)) } func (l *DefaultLogger) Warn(msg string) { l.write(Warning, msg) } func (l *DefaultLogger) Warnf(template string, vals ...interface{}) { l.write(Warning, fmt.Sprintf(template, vals...)) } func (l *DefaultLogger) Panic(msg string) { l.write(Fatal, msg) if l.triggerPanic { panic(msg) } } func (l *DefaultLogger) Panicf(template string, vals ...interface{}) { formattedMsg := fmt.Sprintf(template, vals...) l.write(Fatal, formattedMsg) if l.triggerPanic { panic(formattedMsg) } }
NewDefaultLogger()
?函數創建一個具有最小嚴重程度日志?DefaultLogger
?和?log.Loggers
?將消息寫入標準輸出。
最終我們的目錄結構如下:
測試日志功能
為了做一個簡單的測試,我們可以修改最開始的?main()
?函數,以便查看日志功能是否能成功打印出日志消息,回到?main.go
?,寫入如下代碼:
package main import ( // "fmt" "sports/logging" ) func writeMessage(logger logging.Logger) { // fmt.Println("Let's Go") logger.Info("Let's Go, logger") } func main() { var logger logging.Logger = logging.NewDefaultLogger(logging.Information) writeMessage(logger) }
由?NewDefaultLogger
?創建的最小日志級別被設置為?Information
,這意味著更低的日志級別(Trace
?和?Debug
)將被忽略,再次編譯和執行?sports
?項目,就會看到本地的日志輸出,可能你按照我的操作只會時間戳不同,如下:
$ go run . 11:46:55 INFO Let's Go, logger
終端結果如圖所示:
總結
到了本文的總結時刻了,為了學習 Go Web 項目,本文先回顧了一下 Go 項目的初始化構建和運行過程,然后往我們的?sports
?項目中添加了一個日志功能,逐步完善日志接口和實現,最后在主函數中進行了一個簡單的日志輸出測試。
原文鏈接:https://segmentfault.com/a/1190000042745375
相關推薦
- 2023-03-02 docker-compose安裝RabbitMQ及插件操作步驟_docker
- 2022-04-28 Python字符串的創建和駐留機制詳解_python
- 2022-07-27 詳解Python中的PyInputPlus模塊_python
- 2022-04-25 Pandas?時間序列分析中的resample函數_python
- 2022-08-25 利用Android實現光影流動特效的方法詳解_Android
- 2023-01-28 GoLang?nil與interface的空指針深入分析_Golang
- 2023-03-26 Go語言通過WaitGroup實現控制并發的示例詳解_Golang
- 2022-07-30 Qt實現不規則窗體
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支