golang string转int8_聊聊golang的zap的Field

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

1160dbd4ff2b195d08bd17c796805be4.png

Field

zap@v1.16.0/zapcore/field.go

type Field struct {    Key       string    Type      FieldType    Integer   int64    String    string    Interface interface{}}

Field定义了Key、FieldType、Integer、String、Interface属性

AddTo

zap@v1.16.0/zapcore/field.go

func (f Field) AddTo(enc ObjectEncoder) {    var err error    switch f.Type {    case ArrayMarshalerType:        err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler))    case ObjectMarshalerType:        err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler))    case BinaryType:        enc.AddBinary(f.Key, f.Interface.([]byte))    case BoolType:        enc.AddBool(f.Key, f.Integer == 1)    case ByteStringType:        enc.AddByteString(f.Key, f.Interface.([]byte))    case Complex128Type:        enc.AddComplex128(f.Key, f.Interface.(complex128))    case Complex64Type:        enc.AddComplex64(f.Key, f.Interface.(complex64))    case DurationType:        enc.AddDuration(f.Key, time.Duration(f.Integer))    case Float64Type:        enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer)))    case Float32Type:        enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer)))    case Int64Type:        enc.AddInt64(f.Key, f.Integer)    case Int32Type:        enc.AddInt32(f.Key, int32(f.Integer))    case Int16Type:        enc.AddInt16(f.Key, int16(f.Integer))    case Int8Type:        enc.AddInt8(f.Key, int8(f.Integer))    case StringType:        enc.AddString(f.Key, f.String)    case TimeType:        if f.Interface != nil {            enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location)))        } else {            // Fall back to UTC if location is nil.            enc.AddTime(f.Key, time.Unix(0, f.Integer))        }    case TimeFullType:        enc.AddTime(f.Key, f.Interface.(time.Time))    case Uint64Type:        enc.AddUint64(f.Key, uint64(f.Integer))    case Uint32Type:        enc.AddUint32(f.Key, uint32(f.Integer))    case Uint16Type:        enc.AddUint16(f.Key, uint16(f.Integer))    case Uint8Type:        enc.AddUint8(f.Key, uint8(f.Integer))    case UintptrType:        enc.AddUintptr(f.Key, uintptr(f.Integer))    case ReflectType:        err = enc.AddReflected(f.Key, f.Interface)    case NamespaceType:        enc.OpenNamespace(f.Key)    case StringerType:        err = encodeStringer(f.Key, f.Interface, enc)    case ErrorType:        encodeError(f.Key, f.Interface.(error), enc)    case SkipType:        break    default:        panic(fmt.Sprintf("unknown field type: %v", f))    }    if err != nil {        enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error())    }}

AddTo方法根据Field的类型来执行encoder的对应方法将Field的key和value添加到encoder中

Equals

zap@v1.16.0/zapcore/field.go

func (f Field) Equals(other Field) bool {    if f.Type != other.Type {        return false    }    if f.Key != other.Key {        return false    }    switch f.Type {    case BinaryType, ByteStringType:        return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte))    case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType:        return reflect.DeepEqual(f.Interface, other.Interface)    default:        return f == other    }}

Equals方法用于判断两个Field是否相等,对于BinaryType或ByteStringType使用bytes.Equal判断,对于ArrayMarshalerType、ObjectMarshalerType、ErrorType、ReflectType使用reflect.DeepEqual判断,其他的默认用==判断

addFields

zap@v1.16.0/zapcore/field.go

func addFields(enc ObjectEncoder, fields []Field) {    for i := range fields {        fields[i].AddTo(enc)    }}

addFields方法用于将fields批量添加到encoder中

With

zap@v1.16.0/zapcore/core.go

func (c *ioCore) With(fields []Field) Core {    clone := c.clone()    addFields(clone.enc, fields)    return clone}

zapcore的With方法用于将fields添加到core中,core的Field属于全局通用的Field

logger

zap@v1.16.0/logger.go

func (log *Logger) With(fields ...Field) *Logger {    if len(fields) == 0 {        return log    }    l := log.clone()    l.core = l.core.With(fields)    return l}func (log *Logger) Info(msg string, fields ...Field) {    if ce := log.check(InfoLevel, msg); ce != nil {        ce.Write(fields...)    }}

logger的With方法最后是执行core的With,添加的是全局的;而Info之类方法提供的Field参数属于动态的,每条log自己的动态Field,它最后调用的是encoder的EncodeEntry(Entry, []Field)方法

Write

zap@v1.16.0/zapcore/json_encoder.go

func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) {    final := enc.clone()    final.buf.AppendByte('{')    if final.LevelKey != "" {        final.addKey(final.LevelKey)        cur := final.buf.Len()        final.EncodeLevel(ent.Level, final)        if cur == final.buf.Len() {            // User-supplied EncodeLevel was a no-op. Fall back to strings to keep            // output JSON valid.            final.AppendString(ent.Level.String())        }    }    if final.TimeKey != "" {        final.AddTime(final.TimeKey, ent.Time)    }    if ent.LoggerName != "" && final.NameKey != "" {        final.addKey(final.NameKey)        cur := final.buf.Len()        nameEncoder := final.EncodeName        // if no name encoder provided, fall back to FullNameEncoder for backwards        // compatibility        if nameEncoder == nil {            nameEncoder = FullNameEncoder        }        nameEncoder(ent.LoggerName, final)        if cur == final.buf.Len() {            // User-supplied EncodeName was a no-op. Fall back to strings to            // keep output JSON valid.            final.AppendString(ent.LoggerName)        }    }    if ent.Caller.Defined {        if final.CallerKey != "" {            final.addKey(final.CallerKey)            cur := final.buf.Len()            final.EncodeCaller(ent.Caller, final)            if cur == final.buf.Len() {                // User-supplied EncodeCaller was a no-op. Fall back to strings to                // keep output JSON valid.                final.AppendString(ent.Caller.String())            }        }        if final.FunctionKey != "" {            final.addKey(final.FunctionKey)            final.AppendString(ent.Caller.Function)        }    }    if final.MessageKey != "" {        final.addKey(enc.MessageKey)        final.AppendString(ent.Message)    }    if enc.buf.Len() > 0 {        final.addElementSeparator()        final.buf.Write(enc.buf.Bytes())    }    addFields(final, fields)    final.closeOpenNamespaces()    if ent.Stack != "" && final.StacktraceKey != "" {        final.AddString(final.StacktraceKey, ent.Stack)    }    final.buf.AppendByte('}')    if final.LineEnding != "" {        final.buf.AppendString(final.LineEnding)    } else {        final.buf.AppendString(DefaultLineEnding)    }    ret := final.buf    putJSONEncoder(final)    return ret, nil}

jsonEncoder的Write方法执行的是Field的addFields(final, fields),将Field的key、value添加到encoder中

实例

func fieldDemo() {    logger, err := zap.NewProduction()    defer logger.Sync()    if err != nil {        panic(err)    }    logger = logger.With(zap.String("appId", "demoApp"))    logger.Info("failed to fetch URL",        // Structured context as strongly typed Field values.        zap.String("url", "https://example.com"),        zap.Int("attempt", 3),        zap.Duration("backoff", time.Second),    )}

输出

{"level":"info","ts":1608304623.277035,"caller":"zap/zap_demo.go:28","msg":"failed to fetch URL","appId":"demoApp","url":"https://example.com","attempt":3,"backoff":1}

小结

Field的AddTo方法根据Field的类型来执行encoder的对应方法将Field的key和value添加到encoder中;logger的With方法最后是执行core的With,添加的是全局的;而Info之类方法提供的Field参数属于动态的,每条log自己的动态Field,它最后调用的是encoder的EncodeEntry(Entry, []Field)方法

doc

  • zap
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值