9

聊聊golang的zap的marshaler

 3 years ago
source link: https://studygolang.com/articles/32233
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文主要研究一下golang的zap的marshaler

ObjectMarshaler

[email protected]/zapcore/marshaler.go

type ObjectMarshaler interface {
    MarshalLogObject(ObjectEncoder) error
}
// ObjectMarshalerFunc is a type adapter that turns a function into an
// ObjectMarshaler.
type ObjectMarshalerFunc func(ObjectEncoder) error

// MarshalLogObject calls the underlying function.
func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error {
    return f(enc)
}

ObjectMarshaler接口定义了MarshalLogObject方法;ObjectMarshalerFunc类型定义了MarshalLogObject方法,使得ObjectMarshalerFunc实现ObjectMarshaler接口

ArrayMarshaler

[email protected]/zapcore/marshaler.go

type ArrayMarshaler interface {
    MarshalLogArray(ArrayEncoder) error
}

// ArrayMarshalerFunc is a type adapter that turns a function into an
// ArrayMarshaler.
type ArrayMarshalerFunc func(ArrayEncoder) error

// MarshalLogArray calls the underlying function.
func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error {
    return f(enc)
}

ArrayMarshaler接口定义了MarshalLogArray方法;ArrayMarshalerFunc类型定义了MarshalLogArray方法,使得ArrayMarshalerFunc实现了MarshalLogArray接口

ObjectEncoder

[email protected]/zapcore/encoder.go

type ObjectEncoder interface {
    // Logging-specific marshalers.
    AddArray(key string, marshaler ArrayMarshaler) error
    AddObject(key string, marshaler ObjectMarshaler) error

    // Built-in types.
    AddBinary(key string, value []byte)     // for arbitrary bytes
    AddByteString(key string, value []byte) // for UTF-8 encoded bytes
    AddBool(key string, value bool)
    AddComplex128(key string, value complex128)
    AddComplex64(key string, value complex64)
    AddDuration(key string, value time.Duration)
    AddFloat64(key string, value float64)
    AddFloat32(key string, value float32)
    AddInt(key string, value int)
    AddInt64(key string, value int64)
    AddInt32(key string, value int32)
    AddInt16(key string, value int16)
    AddInt8(key string, value int8)
    AddString(key, value string)
    AddTime(key string, value time.Time)
    AddUint(key string, value uint)
    AddUint64(key string, value uint64)
    AddUint32(key string, value uint32)
    AddUint16(key string, value uint16)
    AddUint8(key string, value uint8)
    AddUintptr(key string, value uintptr)

    // AddReflected uses reflection to serialize arbitrary objects, so it can be
    // slow and allocation-heavy.
    AddReflected(key string, value interface{}) error
    // OpenNamespace opens an isolated namespace where all subsequent fields will
    // be added. Applications can use namespaces to prevent key collisions when
    // injecting loggers into sub-components or third-party libraries.
    OpenNamespace(key string)
}

ObjectEncoder的AddArray方法需要ArrayMarshaler参数,AddObject方法需要ObjectMarshaler参数

zap.Object

[email protected]/field.go

// Object constructs a field with the given key and ObjectMarshaler. It
// provides a flexible, but still type-safe and efficient, way to add map- or
// struct-like user-defined types to the logging context. The struct's
// MarshalLogObject method is called lazily.
func Object(key string, val zapcore.ObjectMarshaler) Field {
    return Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val}
}

zap.Object方法要求value实现zapcore.ObjectMarshaler接口

zap.Array

[email protected]/array.go

// Array constructs a field with the given key and ArrayMarshaler. It provides
// a flexible, but still type-safe and efficient, way to add array-like types
// to the logging context. The struct's MarshalLogArray method is called lazily.
func Array(key string, val zapcore.ArrayMarshaler) Field {
    return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val}
}

zap.Array方法要求value实现了zapcore.ArrayMarshaler接口

type User struct {
    Name      string
    Email     string
    CreatedAt time.Time
}

func (u *User) MarshalLogObject(enc zapcore.ObjectEncoder) error {
    enc.AddString("name", u.Name)
    enc.AddString("email", u.Email)
    enc.AddInt64("created_at", u.CreatedAt.UnixNano())
    return nil
}

type Users []*User

func (uu Users) MarshalLogArray(arr zapcore.ArrayEncoder) error {
    var err error
    for i := range uu {
        err = multierr.Append(err, arr.AppendObject(uu[i]))
    }
    return err
}

func marshalerDemo() {
    logger, err := zap.NewProduction()
    defer logger.Sync()
    if err != nil {
        panic(err)
    }
    var user = &User{
        Name:      "hello1",
        Email:     "[email protected]",
        CreatedAt: time.Date(2020, 12, 19, 8, 0, 0, 0, time.UTC),
    }
    var users Users
    users = append(users, &User{
        Name:      "hello2",
        Email:     "[email protected]",
        CreatedAt: time.Date(2020, 12, 19, 9, 0, 0, 0, time.UTC),
    }, &User{
        Name:      "hello3",
        Email:     "[email protected]",
        CreatedAt: time.Date(2020, 12, 20, 10, 0, 0, 0, time.UTC),
    })
    logger.Info("marshaler", zap.Object("user", user))
    logger.Info("marshaler", zap.Array("users", users))
}

User类型实现了MarshalLogObject方法;Users类型实现了MarshalLogArray方法;之后在logger添加Field的时候,就可以使用zap.Object或者zap.Array方法

{"level":"info","ts":1608348349.487255,"caller":"zap/zap_demo.go:66","msg":"marshaler","user":{"name":"hello1","email":"[email protected]","created_at":1608364800000000000}}
{"level":"info","ts":1608348349.4873412,"caller":"zap/zap_demo.go:67","msg":"marshaler","users":[{"name":"hello2","email":"[email protected]","created_at":1608368400000000000},{"name":"hello3","email":"[email protected]","created_at":1608458400000000000}]}

zap的marshaler定义了ObjectMarshaler(MarshalLogObject)及ArrayMarshaler(MarshalLogArray)接口;在logger若想使用zap.Object或者zap.Array方法就要求对应的类型实现对应的接口。


有疑问加站长微信联系(非本文作者)

280

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK