最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go slog 日志打印最佳實(shí)踐案例

 更新時(shí)間:2025年10月27日 10:11:11   作者:golang學(xué)習(xí)記  
Go 1.21 引入了log/slog 包,為Go語言帶來了原生的結(jié)構(gòu)化日志解決方案,本文將深入探討如何使用slog實(shí)現(xiàn)高效、可靠的日志記錄,感興趣的朋友跟隨小編一起看看吧

引言

Go 1.21 引入了 log/slog 包,為 Go 語言帶來了原生的結(jié)構(gòu)化日志解決方案。與傳統(tǒng)的簡單日志包或第三方庫相比,slog 提供了更強(qiáng)大、更靈活的日志記錄能力。本文將深入探討如何使用 slog 實(shí)現(xiàn)高效、可靠的日志記錄。

核心概念

slog 圍繞三個(gè)核心類型構(gòu)建:

  1. Logger - 用戶交互的前端接口
  2. Handler - 實(shí)際處理日志的后端
  3. Record - 在前后端之間傳遞的日志數(shù)據(jù)
// 創(chuàng)建使用 JSON 格式的 Logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
// 創(chuàng)建記錄并傳遞給 Handler
logger.Info("user logged in", "user_id", 123)

輸出結(jié)果:

{
  "time": "...",
  "level": "INFO",
  "msg": "user logged in",
  "user_id": 123
}

最佳實(shí)踐

1. 使用強(qiáng)類型屬性

避免使用易出錯(cuò)的鍵值對方式:

// 容易出錯(cuò) - 缺少值時(shí)會產(chǎn)生 !BADKEY
logger.Warn("permission denied", "user_id", 12345, "resource")

推薦使用類型安全的 slog.Attr

logger.Warn("permission denied",
    slog.Int("user_id", 12345),
    slog.String("resource", "/api/admin"))

2. 使用 linter 強(qiáng)制一致性

通過 sloglint 確保代碼庫中的日志風(fēng)格一致:

# 安裝 sloglint
go install github.com/ettle/strcase/cmd/sloglint@latest
# 運(yùn)行檢查
sloglint ./...

配置 .sloglintrc 文件來定義團(tuán)隊(duì)規(guī)范:

# 強(qiáng)制使用 slog.Attr 而非原始鍵值對
require-typed-attrs: true
# 要求所有日志消息使用小寫
lowercase-messages: true
# 禁止在日志中記錄敏感信息
forbidden-keys: ["password", "token", "secret"]

3. 合理設(shè)置日志級別

根據(jù)日志的重要性選擇合適的級別:

// DEBUG - 詳細(xì)調(diào)試信息,僅在開發(fā)/調(diào)試時(shí)啟用
logger.Debug("database query executed", slog.String("query", sql))
// INFO - 常規(guī)操作信息
logger.Info("user created", slog.Int("user_id", userID))
// WARN - 異常情況但不影響系統(tǒng)運(yùn)行
logger.Warn("cache miss", slog.String("key", cacheKey))
// ERROR - 錯(cuò)誤情況需要關(guān)注
logger.Error("database connection failed", slog.String("error", err.Error()))
// Custom levels for business logic
const (
    LevelTrace = slog.Level(-8)
    LevelFatal = slog.Level(12)
)

4. 全局日志器配置

在應(yīng)用啟動時(shí)配置全局日志器:

func init() {
    opts := &slog.HandlerOptions{
        Level:     slog.LevelInfo, // 生產(chǎn)環(huán)境通常使用 Info 級別
        AddSource: false,          // 生產(chǎn)環(huán)境關(guān)閉源碼位置以提高性能
    }
    // 根據(jù)環(huán)境選擇處理器
    var handler slog.Handler
    if os.Getenv("ENV") == "development" {
        handler = slog.NewTextHandler(os.Stdout, opts)
    } else {
        handler = slog.NewJSONHandler(os.Stdout, opts)
    }
    slog.SetDefault(slog.New(handler))
}

5. 上下文傳遞日志器

在 HTTP 處理器或服務(wù)方法中傳遞帶有上下文信息的日志器:

func handleRequest(w http.ResponseWriter, r *http.Request) {
    // 為當(dāng)前請求創(chuàng)建帶上下文的日志器
    requestLogger := slog.With(
        slog.String("request_id", getRequestID(r)),
        slog.String("user_agent", r.UserAgent()),
        slog.String("method", r.Method),
        slog.String("path", r.URL.Path),
    )
    // 在處理邏輯中使用上下文日志器
    if err := processRequest(r, requestLogger); err != nil {
        requestLogger.Error("request processing failed", slog.String("error", err.Error()))
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }
    requestLogger.Info("request processed successfully")
}

6. 敏感信息處理

永遠(yuǎn)不要在日志中記錄敏感信息:

// ? 錯(cuò)誤做法
logger.Info("user login", 
    slog.String("email", user.Email),
    slog.String("password", user.Password)) // 危險(xiǎn)!
// ? 正確做法
logger.Info("user login",
    slog.String("email", maskEmail(user.Email)),
    slog.Bool("success", loginSuccess))
func maskEmail(email string) string {
    parts := strings.Split(email, "@")
    if len(parts) != 2 {
        return "invalid-email"
    }
    username := parts[0]
    if len(username) <= 2 {
        return "**@" + parts[1]
    }
    masked := username[:2] + strings.Repeat("*", len(username)-2)
    return masked + "@" + parts[1]
}

7. 性能優(yōu)化

避免在日志記錄中執(zhí)行昂貴操作:

// ? 低效 - 即使日志級別不夠也會執(zhí)行序列化
logger.Debug("expensive data", slog.Any("data", expensiveSerialization()))
// ? 高效 - 使用惰性求值
if logger.Enabled(context.Background(), slog.LevelDebug) {
    logger.Debug("expensive data", slog.Any("data", expensiveSerialization()))
}
// 或者使用 slog.Group 進(jìn)行批量屬性處理
logger.Info("user profile",
    slog.Group("profile",
        slog.String("name", user.Name),
        slog.Int("age", user.Age),
        slog.String("city", user.City),
    ))

8. 自定義 Handler

為特殊需求創(chuàng)建自定義 Handler:

type FilteringHandler struct {
    slog.Handler
    filter func(slog.Record) bool
}
func (h *FilteringHandler) Handle(ctx context.Context, r slog.Record) error {
    if h.filter(r) {
        return h.Handler.Handle(ctx, r)
    }
    return nil
}
// 使用示例:過濾掉包含特定關(guān)鍵詞的日志
filterHandler := &FilteringHandler{
    Handler: slog.NewJSONHandler(os.Stdout, nil),
    filter: func(r slog.Record) bool {
        return !strings.Contains(r.Message, "heartbeat")
    },
}
logger := slog.New(filterHandler)

9. 結(jié)構(gòu)化錯(cuò)誤處理

將錯(cuò)誤信息結(jié)構(gòu)化記錄:

// 自定義錯(cuò)誤類型
type AppError struct {
    Code    string
    Message string
    Cause   error
}
func (e *AppError) Error() string {
    return e.Message
}
// 記錄結(jié)構(gòu)化錯(cuò)誤
if err != nil {
    var appErr *AppError
    if errors.As(err, &appErr) {
        logger.Error("application error",
            slog.String("error_code", appErr.Code),
            slog.String("error_message", appErr.Message),
            slog.String("cause", appErr.Cause.Error()))
    } else {
        logger.Error("unexpected error", slog.String("error", err.Error()))
    }
}

10. 測試日志輸出

在單元測試中驗(yàn)證日志行為:

func TestUserService_CreateUser(t *testing.T) {
    var buf bytes.Buffer
    logger := slog.New(slog.NewJSONHandler(&buf, nil))
    service := NewUserService(logger)
    err := service.CreateUser(context.Background(), "test@example.com")
    assert.NoError(t, err)
    // 驗(yàn)證日志內(nèi)容
    var logRecord map[string]interface{}
    err = json.Unmarshal(buf.Bytes(), &logRecord)
    assert.NoError(t, err)
    assert.Equal(t, "user created", logRecord["msg"])
    assert.Equal(t, "test@example.com", logRecord["email"])
}

總結(jié)

slog 包為 Go 應(yīng)用提供了現(xiàn)代化的結(jié)構(gòu)化日志解決方案。通過遵循這些最佳實(shí)踐,你可以構(gòu)建出既高效又可靠的日志系統(tǒng),為應(yīng)用的可觀測性和故障排查提供有力支持。好的日志實(shí)踐不僅能幫助你快速定位問題,還能在不影響性能的前提下提供豐富的上下文信息。

到此這篇關(guān)于Go slog 日志打印最佳實(shí)踐指南的文章就介紹到這了,更多相關(guān)Go slog 日志打印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go存儲基礎(chǔ)使用direct io方法實(shí)例

    Go存儲基礎(chǔ)使用direct io方法實(shí)例

    這篇文章主要介紹了Go存儲基礎(chǔ)之如何使用direct io方法實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 基于go語言實(shí)現(xiàn)圖片驗(yàn)證碼的代碼示例

    基于go語言實(shí)現(xiàn)圖片驗(yàn)證碼的代碼示例

    這篇文章主要為大家詳細(xì)介紹了基于go語言實(shí)現(xiàn)圖片驗(yàn)證碼的代碼示例,文中的示例代碼簡潔易懂,具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-10-10
  • 線上問題排查之golang使用json進(jìn)行對象copy

    線上問題排查之golang使用json進(jìn)行對象copy

    這篇文章主要介紹了線上問題排查之golang使用json進(jìn)行對象copy,文章圍繞golang使用json進(jìn)行對象copy的內(nèi)存溢出問題排查展開詳細(xì)內(nèi)容需要的小伙伴可以參考一下
    2022-06-06
  • Go語言中http.ResponseWriter接口

    Go語言中http.ResponseWriter接口

    http.ResponseWriter是Go語言中用來設(shè)置HTTP響應(yīng)的接口,本文主要介紹了Go語言中http.ResponseWriter接口,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • Golang實(shí)現(xiàn)反向代理的示例代碼

    Golang實(shí)現(xiàn)反向代理的示例代碼

    這篇文章主要為大家學(xué)習(xí)介紹了如何利用Golang實(shí)現(xiàn)反向代理,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-07-07
  • go語言語法基礎(chǔ)的全面梳理(適合入門)

    go語言語法基礎(chǔ)的全面梳理(適合入門)

    這篇文章主要介紹了go語言語法基礎(chǔ)的相關(guān)資料,從基礎(chǔ)語法到并發(fā)編程,涵蓋變量聲明、數(shù)據(jù)類型、流程控制、函數(shù)、接口、錯(cuò)誤處理及并發(fā)編程,全面覆蓋Go語言核心特性,需要的朋友可以參考下
    2026-06-06
  • 基于Golang開發(fā)一個(gè)輕量級登錄庫/框架

    基于Golang開發(fā)一個(gè)輕量級登錄庫/框架

    幾乎每個(gè)項(xiàng)目都會有登錄,退出等用戶功能,而登錄又不單僅僅是登錄,我們要考慮很多東西。所以本文就來用Golang開發(fā)一個(gè)輕量級登錄庫/框架吧
    2023-05-05
  • go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析

    go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析

    這篇文章主要為大家介紹了go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 基于golang uint8、int8與byte的區(qū)別說明

    基于golang uint8、int8與byte的區(qū)別說明

    這篇文章主要介紹了基于golang uint8、int8與byte的區(qū)別說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Go泛型中的~struct{}的具體使用

    Go泛型中的~struct{}的具體使用

    本文主要Go泛型中的~struct{}的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-12-12

最新評論

潜江市| 厦门市| 眉山市| 澄迈县| 宜良县| 威宁| 湛江市| 丹阳市| 诸城市| 化州市| 山东省| 襄樊市| 秦安县| 遂宁市| 囊谦县| 梁河县| 锡林郭勒盟| 泰兴市| 哈尔滨市| 晋江市| 辽宁省| 九龙城区| 高平市| 安徽省| 正宁县| 米林县| 依安县| 喀喇| 贡嘎县| 永清县| 桃江县| 武隆县| 霍州市| 东兴市| 乌鲁木齐市| 北宁市| 常宁市| 乌海市| 青田县| 三河市| 邯郸县|