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

Go中slog使用入門

 更新時(shí)間:2026年03月26日 09:56:55   作者:FlDmr4i28  
slog是Go1.21引入的官方結(jié)構(gòu)化日志庫,本文就來介紹一下Go中slog使用入門,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

簡介

slog 是 Go 1.21 引入的官方結(jié)構(gòu)化日志庫(Structured Logging)。它結(jié)束了 Go 標(biāo)準(zhǔn)庫只有簡單 log 包的歷史,讓我們可以直接輸出 JSON 或 Key-Value 格式的日志,非常適合對(duì)接 ELK、Grafana Loki 等日志分析系統(tǒng)。

相較于第三方日志庫如 zap、logrusslog 的優(yōu)勢(shì)在于:

  • 零依賴:作為標(biāo)準(zhǔn)庫的一部分,無需引入第三方依賴
  • 官方維護(hù):長期穩(wěn)定,API 變更有 Go 兼容性承諾保障
  • 接口簡潔:API 設(shè)計(jì)清晰,學(xué)習(xí)成本低
  • 可擴(kuò)展:通過自定義 Handler 可以實(shí)現(xiàn)各種定制需求

基本使用

slog 用起來非常簡單。默認(rèn)輸出到標(biāo)準(zhǔn)錯(cuò)誤流(os.Stderr),格式為普通文本。

package main
import (
	"fmt"
	"log/slog"
)
func main() {
	slog.Debug("Hello world")
	slog.Info("Hello world")
	slog.Warn("Hello world")
	slog.Error("Hello world")
	slog.Info("this is a message", "name", "zhangsan")
	age := 8
	slog.Warn(fmt.Sprintf("這是 %d 歲?", age))
}

運(yùn)行輸出:

$ go run main.go
2026/02/15 11:52:24 INFO Hello world
2026/02/15 11:52:24 WARN Hello world
2026/02/15 11:52:24 ERROR Hello world
2026/02/15 11:52:24 INFO this is a message name=zhangsan
2026/02/15 11:52:24 WARN 這是 8 歲?

注意:默認(rèn)的 slog logger 日志級(jí)別為 INFO,因此 Debug 級(jí)別的日志不會(huì)輸出。

日志級(jí)別

slog 定義了四個(gè)日志級(jí)別,從低到高依次為:

級(jí)別常量說明
DEBUGslog.LevelDebug調(diào)試信息,開發(fā)環(huán)境使用
INFOslog.LevelInfo常規(guī)信息
WARNslog.LevelWarn警告信息
ERRORslog.LevelError錯(cuò)誤信息

輸出 JSON 格式

slog 可以輸出 JSON 格式,便于與 ELK、Grafana Loki 等日志系統(tǒng)集成。

以下示例演示了如何修改默認(rèn)的時(shí)間戳格式和調(diào)用源輸出格式,并將其設(shè)置為默認(rèn) logger:

package main
import (
	"fmt"
	"log/slog"
	"os"
	"time"
)
func main() {
	jsonLogger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
		AddSource: true,            // 添加調(diào)用源信息
		Level:     slog.LevelDebug, // 設(shè)置日志級(jí)別
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			// 自定義時(shí)間格式
			if a.Key == slog.TimeKey {
				if t, ok := a.Value.Any().(time.Time); ok {
					a.Value = slog.StringValue(t.Format(time.RFC3339))
				}
			}
			// 簡化調(diào)用源信息,只保留文件名和行號(hào)
			if a.Key == slog.SourceKey {
				source := a.Value.Any().(*slog.Source)
				shortFile := source.File
				for i := len(source.File) - 1; i > 0; i-- {
					if source.File[i] == '/' {
						shortFile = source.File[i+1:]
						break
					}
				}
				return slog.String("source", fmt.Sprintf("%s:%d", shortFile, source.Line))
			}
			return a
		},
	}))
	jsonLogger.Debug("Hello world")
	jsonLogger.Info("Hello world")
	jsonLogger.Warn("Hello world")
	jsonLogger.Error("Hello world")
	jsonLogger.Info("this is a message", "name", "zhangsan")
	age := 8
	jsonLogger.Warn(fmt.Sprintf("這是 %d 歲?", age))
	// 替換默認(rèn) logger
	slog.SetDefault(jsonLogger)
	slog.Debug("Hello world")
	slog.Info("Hello world")
	slog.Warn("Hello world")
	slog.Error("Hello world")
	slog.Info("this is a message", "name", "zhangsan")
	age = 9
	slog.Warn(fmt.Sprintf("這是 %d 歲?", age))
}

運(yùn)行輸出:

$ go run main.go
{"time":"2026-02-15T12:07:32+08:00","level":"DEBUG","source":"main.go:38","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"INFO","source":"main.go:39","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"WARN","source":"main.go:40","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"ERROR","source":"main.go:41","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"INFO","source":"main.go:43","msg":"this is a message","name":"zhangsan"}
{"time":"2026-02-15T12:07:32+08:00","level":"WARN","source":"main.go:46","msg":"這是 8 歲?"}
{"time":"2026-02-15T12:07:32+08:00","level":"DEBUG","source":"main.go:50","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"INFO","source":"main.go:51","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"WARN","source":"main.go:52","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"ERROR","source":"main.go:53","msg":"Hello world"}
{"time":"2026-02-15T12:07:32+08:00","level":"INFO","source":"main.go:55","msg":"this is a message","name":"zhangsan"}
{"time":"2026-02-15T12:07:32+08:00","level":"WARN","source":"main.go:58","msg":"這是 9 歲?"}

HandlerOptions 詳解

HandlerOptions 提供了三個(gè)配置項(xiàng):

字段類型說明
AddSourcebool是否添加調(diào)用源信息(文件名和行號(hào))
Levelslog.Leveler最低日志級(jí)別,低于此級(jí)別的日志將被忽略
ReplaceAttrfunc([]string, slog.Attr) slog.Attr用于修改或替換屬性的回調(diào)函數(shù)

With 注入通用屬性

創(chuàng)建 Logger 時(shí),可以用 With 方法為 logger 添加通用屬性。這些屬性會(huì)自動(dòng)附加到每條日志記錄中,適合注入服務(wù)名、環(huán)境、版本等上下文信息。

package main
import (
	"fmt"
	"log/slog"
	"os"
	"time"
)
func main() {
	jsonLogger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
		AddSource: true,
		Level:     slog.LevelDebug,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey {
				if t, ok := a.Value.Any().(time.Time); ok {
					a.Value = slog.StringValue(t.Format(time.RFC3339))
				}
			}
			if a.Key == slog.SourceKey {
				source := a.Value.Any().(*slog.Source)
				shortFile := source.File
				for i := len(source.File) - 1; i > 0; i-- {
					if source.File[i] == '/' {
						shortFile = source.File[i+1:]
						break
					}
				}
				return slog.String("source", fmt.Sprintf("%s:%d", shortFile, source.Line))
			}
			return a
		},
	})).With("logger", "json", "env", "production")
	jsonLogger.Debug("Hello world")
	jsonLogger.Info("Hello world")
	jsonLogger.Warn("Hello world")
	jsonLogger.Error("Hello world")
	jsonLogger.Info("this is a message", "name", "zhangsan")
}

運(yùn)行輸出:

$ go run main.go
{"time":"2026-02-15T13:24:38+08:00","level":"DEBUG","source":"main.go:42","msg":"Hello world","logger":"json","env":"production"}
{"time":"2026-02-15T13:24:38+08:00","level":"INFO","source":"main.go:43","msg":"Hello world","logger":"json","env":"production"}
{"time":"2026-02-15T13:24:38+08:00","level":"WARN","source":"main.go:44","msg":"Hello world","logger":"json","env":"production"}
{"time":"2026-02-15T13:24:38+08:00","level":"ERROR","source":"main.go:45","msg":"Hello world","logger":"json","env":"production"}
{"time":"2026-02-15T13:24:38+08:00","level":"INFO","source":"main.go:47","msg":"this is a message","logger":"json","env":"production","name":"zhangsan"}

使用 Group 對(duì)屬性分組

當(dāng)日志屬性較多時(shí),可以使用 slog.Group 將相關(guān)屬性組織在一起,使輸出結(jié)構(gòu)更清晰:

package main
import (
	"fmt"
	"log/slog"
	"os"
	"time"
)
func main() {
	jsonLogger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
		AddSource: true,
		Level:     slog.LevelDebug,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey {
				if t, ok := a.Value.Any().(time.Time); ok {
					a.Value = slog.StringValue(t.Format(time.RFC3339))
				}
			}
			if a.Key == slog.SourceKey {
				source := a.Value.Any().(*slog.Source)
				shortFile := source.File
				for i := len(source.File) - 1; i > 0; i-- {
					if source.File[i] == '/' {
						shortFile = source.File[i+1:]
						break
					}
				}
				return slog.String("source", fmt.Sprintf("%s:%d", shortFile, source.Line))
			}
			return a
		},
	}))
	jsonLogger = jsonLogger.With("logger", "json")
	// 使用 Group 組織相關(guān)屬性
	jsonLogger.Info("系統(tǒng)狀態(tài)",
		slog.Group("metrics",
			slog.Int("cpu", 4),
			slog.Float64("memPercent", 2.33),
		),
		slog.Group("request",
			slog.String("method", "GET"),
			slog.String("path", "/api/users"),
		),
	)
}

運(yùn)行輸出:

$ go run main.go
{"time":"2026-02-15T13:30:08+08:00","level":"INFO","source":"main.go:43","msg":"系統(tǒng)狀態(tài)","logger":"json","metrics":{"cpu":4,"memPercent":2.33},"request":{"method":"GET","path":"/api/users"}}

高性能場景使用 LogAttrs

如果需要在高性能循環(huán)中打印日志,建議使用 LogAttrs 方法。它使用強(qiáng)類型屬性(slog.Attr),避免了反射帶來的性能開銷。

package main
import (
	"context"
	"log/slog"
	"os"
	"time"
)
func main() {
	jsonLogger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
		AddSource: true,
		Level:     slog.LevelDebug,
		ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
			if a.Key == slog.TimeKey {
				if t, ok := a.Value.Any().(time.Time); ok {
					a.Value = slog.StringValue(t.Format(time.RFC3339))
				}
			}
			if a.Key == slog.SourceKey {
				source := a.Value.Any().(*slog.Source)
				shortFile := source.File
				for i := len(source.File) - 1; i > 0; i-- {
					if source.File[i] == '/' {
						shortFile = source.File[i+1:]
						break
					}
				}
				return slog.String("source", fmt.Sprintf("%s:%d", shortFile, source.Line))
			}
			return a
		},
	})).With("logger", "json")
	for i := range 5 {
		jsonLogger.LogAttrs(
			context.Background(),
			slog.LevelInfo,
			"執(zhí)行遍歷",
			slog.Int("round", i),
			slog.String("task_name", "cleanup"),
			slog.Duration("duration", time.Second*time.Duration(i+1)),
		)
	}
}

運(yùn)行輸出:

$ go run main.go
{"time":"2026-02-15T13:38:21+08:00","level":"INFO","source":"main.go:45","msg":"執(zhí)行遍歷","logger":"json","round":0,"task_name":"cleanup","duration":1000000000}
{"time":"2026-02-15T13:38:21+08:00","level":"INFO","source":"main.go:45","msg":"執(zhí)行遍歷","logger":"json","round":1,"task_name":"cleanup","duration":2000000000}
{"time":"2026-02-15T13:38:21+08:00","level":"INFO","source":"main.go:45","msg":"執(zhí)行遍歷","logger":"json","round":2,"task_name":"cleanup","duration":3000000000}
{"time":"2026-02-15T13:38:21+08:00","level":"INFO","source":"main.go:45","msg":"執(zhí)行遍歷","logger":"json","round":3,"task_name":"cleanup","duration":4000000000}
{"time":"2026-02-15T13:38:21+08:00","level":"INFO","source":"main.go:45","msg":"執(zhí)行遍歷","logger":"json","round":4,"task_name":"cleanup","duration":5000000000}

性能對(duì)比

根據(jù)官方基準(zhǔn)測試,LogAttrs 相比普通方法調(diào)用有約 30% 的性能提升:

方法內(nèi)存分配性能
slog.Info(msg, "key", value)有額外分配基準(zhǔn)
slog.LogAttrs(ctx, level, msg, attrs...)零額外分配快約 30%

提取 Context 中的鏈路信息

slog 提供了 InfoContext、WarnContext 等方法,可以從 context.Context 中提取數(shù)據(jù)。默認(rèn)情況下,這些方法不會(huì)自動(dòng)提取 context 中的值,需要通過自定義 Handler 來實(shí)現(xiàn)。

自定義 ContextHandler

以下示例實(shí)現(xiàn)了一個(gè)自定義 Handler,用于從 context 中提取 TraceID:

package main
import (
	"context"
	"log/slog"
	"os"
)
type contextKey string
const TraceIDKey contextKey = "trace_id"
// ContextHandler 包裝一個(gè) slog.Handler,在處理日志時(shí)自動(dòng)從 context 中提取 TraceID
type ContextHandler struct {
	slog.Handler
}
func (h *ContextHandler) Handle(ctx context.Context, record slog.Record) error {
	if ctx != nil {
		if traceID, ok := ctx.Value(TraceIDKey).(string); ok && traceID != "" {
			record.AddAttrs(slog.String(string(TraceIDKey), traceID))
		}
	}
	return h.Handler.Handle(ctx, record)
}
func main() {
	baseHandler := slog.NewJSONHandler(os.Stdout, nil)
	handler := &ContextHandler{Handler: baseHandler}
	jsonLogger := slog.New(handler)
	slog.SetDefault(jsonLogger)
	ctx := context.WithValue(context.Background(), TraceIDKey, "abc123-def456")
	slog.InfoContext(ctx, "hello world")
	slog.WarnContext(ctx, "something happened", "user", "zhangsan")
}

運(yùn)行輸出:

$ go run main.go | python3 -m json.tool
{
  "time": "2026-02-15T13:56:43.086323769+08:00",
  "level": "INFO",
  "msg": "hello world",
  "trace_id": "abc123-def456"
}
{
  "time": "2026-02-15T13:56:43.086323769+08:00",
  "level": "WARN",
  "msg": "something happened",
  "user": "zhangsan",
  "trace_id": "abc123-def456"
}

在 Gin 框架中使用 slog

在 Gin 中使用 slog 的 context 能力,通常的做法是編寫一個(gè)中間件來注入 TraceID,并配合自定義 slog.Handler 來提取它。

package main
import (
	"context"
	"log/slog"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"runtime/debug"
	"strings"
	"time"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)
type contextKey string
const TraceIDKey contextKey = "trace_id"
// ContextHandler 從 context 中提取 TraceID 并添加到日志中
type ContextHandler struct {
	slog.Handler
}
func (h *ContextHandler) Handle(ctx context.Context, record slog.Record) error {
	if ctx != nil {
		if traceID, ok := ctx.Value(TraceIDKey).(string); ok && traceID != "" {
			record.AddAttrs(slog.String(string(TraceIDKey), traceID))
		}
	}
	return h.Handler.Handle(ctx, record)
}
// SlogMiddleware 是一個(gè) Gin 中間件,用于注入 TraceID
func SlogMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		// 優(yōu)先從請(qǐng)求頭獲取 TraceID,沒有則生成新的
		traceID := c.GetHeader("X-Trace-ID")
		if traceID == "" {
			traceID = uuid.New().String()
		}
		// 將 TraceID 注入到標(biāo)準(zhǔn)的 context.Context 中
		// 注意:Gin 的 c.Set 只在 Gin 內(nèi)部生效,slog 需要標(biāo)準(zhǔn)庫的 Context
		ctx := context.WithValue(c.Request.Context(), TraceIDKey, traceID)
		c.Request = c.Request.WithContext(ctx)
		// 將 TraceID 寫入響應(yīng)頭,方便客戶端追蹤
		c.Header("X-Trace-ID", traceID)
		c.Next()
		// 請(qǐng)求結(jié)束后的匯總?cè)罩?
		slog.InfoContext(c.Request.Context(), "Request completed",
			slog.String("method", c.Request.Method),
			slog.String("path", c.Request.URL.Path),
			slog.Int("status", c.Writer.Status()),
			slog.Int("body_size", c.Writer.Size()),
			slog.Duration("latency", time.Since(start)),
		)
	}
}
// SlogRecovery 是一個(gè)自定義的恢復(fù)中間件
// 它會(huì)捕獲 Panic,記錄堆棧信息,并使用 slog.ErrorContext 輸出
func SlogRecovery() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				// 檢查是否是連接中斷(broken pipe)
				var brokenPipe bool
				if ne, ok := err.(*net.OpError); ok {
					if se, ok := ne.Err.(*os.SyscallError); ok {
						if strings.Contains(strings.ToLower(se.Error()), "broken pipe") ||
							strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
							brokenPipe = true
						}
					}
				}
				// 獲取堆棧信息
				stack := string(debug.Stack())
				// 獲取原始請(qǐng)求內(nèi)容
				httpRequest, _ := httputil.DumpRequest(c.Request, false)
				if brokenPipe {
					slog.ErrorContext(c.Request.Context(), "網(wǎng)絡(luò)連接中斷",
						slog.Any("error", err),
						slog.String("request", string(httpRequest)),
					)
					c.Error(err.(error))
					c.Abort()
					return
				}
				// 記錄 Panic 詳情
				slog.ErrorContext(c.Request.Context(), "Recovery from panic",
					slog.Any("error", err),
					slog.String("stack", stack),
					slog.String("request", string(httpRequest)),
				)
				ctx := c.Request.Context()
				traceID, _ := ctx.Value(TraceIDKey).(string)
				// 返回 500 狀態(tài)碼
				c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
					"code":      http.StatusInternalServerError,
					"msg":       "Internal Server Error",
					"data":      nil,
					"timestamp": time.Now().Format(time.RFC3339),
					"trace_id":  traceID,
				})
			}
		}()
		c.Next()
	}
}
func main() {
	// 初始化 slog
	baseHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelDebug,
	})
	handler := &ContextHandler{Handler: baseHandler}
	jsonLogger := slog.New(handler)
	slog.SetDefault(jsonLogger)
	// 使用 gin.New() 而不是 gin.Default(),避免內(nèi)置日志干擾
	r := gin.New()
	r.Use(SlogMiddleware())
	r.Use(SlogRecovery())
	r.GET("/ping", func(c *gin.Context) {
		slog.InfoContext(c.Request.Context(), "Processing /ping request",
			slog.String("user", "zhangsan"),
		)
		time.Sleep(time.Second * 2)
		c.JSON(200, gin.H{"msg": "pong"})
	})
	r.GET("/panic", func(c *gin.Context) {
		slog.InfoContext(c.Request.Context(), "About to panic")
		panic("something went wrong")
	})
	r.Run(":8080")
}

運(yùn)行后測試:

$ curl http://localhost:8080/ping
{"msg":"pong"}
$ curl http://localhost:8080/panic
{"code":500,"msg":"Internal Server Error","data":null,"timestamp":"2026-02-15T14:30:00+08:00","trace_id":"xxx-xxx-xxx"}

日志輸出文件

寫日志文件一定要注意控制日志文件大小,建議配合系統(tǒng)的logrotate。如果服務(wù)運(yùn)行在kubernetes,建議只輸出控制臺(tái)日志,由專門的日志收集平臺(tái)去獲取控制臺(tái)日志。

基本實(shí)現(xiàn)

寫到app.log

package main
import (
	"log/slog"
	"os"
)
func main() {
	logFile, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic(err)
	}
	handler := slog.NewJSONHandler(logFile, nil)
	logger := slog.New(handler)
	slog.SetDefault(logger)
	slog.Info("hello world")
}

配合logrotate。在 /etc/logrotate.d/myapp 創(chuàng)建配置文件

/path/to/app.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    copytruncate    # 復(fù)制后截?cái)?,不需要重?Go 程序
}

使用lumberjack輪轉(zhuǎn)日志文件

如果不想用系統(tǒng)的 logrotate ,可以使用 lumberjack 包,它提供了更靈活的日志輪轉(zhuǎn)策略。

import "gopkg.in/natefinch/lumberjack.v2"
func initLumberjack() {
    rollingFile := &lumberjack.Logger{
        Filename:   "./logs/app.log",
        MaxSize:    100, // 單位 MB
        MaxBackups: 3,   // 保留舊文件的最大個(gè)數(shù)
        MaxAge:     28,  // 保留舊文件的最大天數(shù)
        Compress:   true, // 是否壓縮
    }
    handler := slog.NewJSONHandler(rollingFile, nil)
    slog.SetDefault(slog.New(handler))
}

同時(shí)輸出控制臺(tái)和日志文件

go1.26 版本后實(shí)現(xiàn)了slog.NewMultiHandler,1.26 前可使用io.multiwriter。

package main
import (
	"log/slog"
	"os"
)
func main() {
	logFile, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic(err)
	}
	fileHandler := slog.NewJSONHandler(logFile, nil)
	consoleHandler := slog.NewTextHandler(os.Stdout, nil)
	multiHandler := slog.NewMultiHandler(fileHandler, consoleHandler) // slog.NewMultiHandler 需要go1.26.0+版本
	logger := slog.New(multiHandler)
	slog.SetDefault(logger)
	slog.Info("hello world")
}

自定義日志級(jí)別

除了四個(gè)內(nèi)置級(jí)別,slog 還支持自定義日志級(jí)別 (一般來說默認(rèn)的日志級(jí)別已經(jīng)夠用了):

package main
import (
	"log/slog"
	"os"
)
func main() {
	// 定義自定義日志級(jí)別
	const (
		LevelTrace   = slog.Level(-8) // 比 Debug 更低
		LevelNotice  = slog.Level(2)  // 介于 Info 和 Warn 之間
		LevelFatal   = slog.Level(12) // 比 Error 更高
	)
	logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		Level: LevelTrace, // 設(shè)置最低級(jí)別
	}))
	logger.Log(nil, LevelTrace, "trace message")
	logger.Log(nil, LevelNotice, "notice message")
	logger.Log(nil, LevelFatal, "fatal message")
}

總結(jié)

slog 作為 Go 官方的結(jié)構(gòu)化日志庫,用起來還是挺方便的。對(duì)于新項(xiàng)目,推薦直接使用 slog;對(duì)于已有項(xiàng)目,可以逐步遷移,slog 的 API 設(shè)計(jì)使得遷移成本很低。

到此這篇關(guān)于Go中slog使用入門的文章就介紹到這了,更多相關(guān)Go slog使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang 內(nèi)存對(duì)齊的實(shí)現(xiàn)

    golang 內(nèi)存對(duì)齊的實(shí)現(xiàn)

    在代碼編譯階段,編譯器會(huì)對(duì)數(shù)據(jù)的存儲(chǔ)布局進(jìn)行對(duì)齊優(yōu)化,本文主要介紹了golang 內(nèi)存對(duì)齊的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • 一文了解Go語言中編碼規(guī)范的使用

    一文了解Go語言中編碼規(guī)范的使用

    這篇文章主要介紹了一文了解Go語言中編碼規(guī)范的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • go如何使用gin結(jié)合jwt做登錄功能簡單示例

    go如何使用gin結(jié)合jwt做登錄功能簡單示例

    jwt全稱Json web token,是一種認(rèn)證和信息交流的工具,這篇文章主要給大家介紹了關(guān)于go如何使用gin結(jié)合jwt做登錄功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • vscode搭建go開發(fā)環(huán)境案例詳解

    vscode搭建go開發(fā)環(huán)境案例詳解

    對(duì)于Visual Studio Code開發(fā)工具,有一款優(yōu)秀的GoLang插件,今天通過本文給大家介紹下vscode搭建go開發(fā)環(huán)境的詳細(xì)教程,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • Golang 使用Map實(shí)現(xiàn)去重與set的功能操作

    Golang 使用Map實(shí)現(xiàn)去重與set的功能操作

    這篇文章主要介紹了Golang 使用 Map 實(shí)現(xiàn)去重與 set 的功能操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang 文件操作:刪除指定的文件方式

    Golang 文件操作:刪除指定的文件方式

    這篇文章主要介紹了Golang 文件操作:刪除指定的文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • golang接口的正確用法分享

    golang接口的正確用法分享

    這篇文章主要介紹了golang接口的正確用法分享的相關(guān)資料,需要的朋友可以參考下
    2023-09-09
  • 一文帶你掌握Go語言并發(fā)模式中的Context的上下文管理

    一文帶你掌握Go語言并發(fā)模式中的Context的上下文管理

    在?Go?的日常開發(fā)中,Context?上下文對(duì)象無處不在,無論是處理網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫操作還是調(diào)用?RPC?等場景,那你真的熟悉它的正確用法嗎,隨著本文一探究竟吧
    2023-05-05
  • Go語言學(xué)習(xí)otns示例分析

    Go語言學(xué)習(xí)otns示例分析

    這篇文章主要為大家介紹了Go語言學(xué)習(xí)otns示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 使用Golang實(shí)現(xiàn)Sm2加解密的代碼詳解

    使用Golang實(shí)現(xiàn)Sm2加解密的代碼詳解

    本文主要介紹了Go語言實(shí)現(xiàn)Sm2加解密的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03

最新評(píng)論

佛坪县| 银川市| 大丰市| 吴旗县| 镶黄旗| 鹰潭市| 贞丰县| 申扎县| 澳门| 罗定市| 松溪县| 太湖县| 遵义县| 库车县| 本溪| 兰溪市| 东至县| 汤原县| 海伦市| 河曲县| 玛多县| 华宁县| 从化市| 自治县| 桓台县| 交城县| 子长县| 绥宁县| 丘北县| 江北区| 潜山县| 安新县| 都昌县| 高台县| 平顺县| 岚皋县| 华安县| 昭苏县| 临清市| 甘谷县| 赣榆县|