Go如何将字符串解组为包装的原子整数?

huangapple go评论72阅读模式
英文:

How does Go unmarshall a string into a wrapped atomc int?

问题

Uber的日志记录库Zap有一个Config结构体,其中日志级别定义如下:

type Config struct {
	Level AtomicLevel `json:"level" yaml:"level"`
}

其中类型AtomicLevel是一个包装了Go的atomic.Int32的结构体:

type AtomicLevel struct {
	l *atomic.Int32
}

在这个设置中,Go的json.Unmarshal如何成功地将一个字符串(比如"debug")解组成正确的原子整数值,如下面的示例所示?

package main

import (
	"encoding/json"

	"go.uber.org/zap"
)

func main() {
	// 对于某些用户来说,NewProduction、NewDevelopment和NewExample构造函数提供的预设可能不合适。
	// 对于大多数用户来说,捆绑的Config结构体提供了灵活性和便利性的正确平衡。(对于更复杂的需求,请参阅AdvancedConfiguration示例。)
	//
	// 有关所有可用选项,请参阅Config和zapcore.EncoderConfig的文档。
	rawJSON := []byte(`{
	  "level": "debug",
	  "encoding": "json",
	}`)

	var cfg zap.Config
	if err := json.Unmarshal(rawJSON, &cfg); err != nil {
		panic(err)
	}
	logger, err := cfg.Build()
	if err != nil {
		panic(err)
	}
	defer logger.Sync()

	logger.Info("logger construction succeeded")
}
英文:

Uber's logging library Zap has a Config struct, in which the log level is defined as follows:

type Config struct {
	Level AtomicLevel `json:"level" yaml:"level"`
}

Where the type AtomicLevel is a struct that wraps Go's atomic.Int32:

type AtomicLevel struct {
	l *atomic.Int32
}

With this setup, how can Go's json.Unmarshall successfully unmarshalls a string, say, "debug" into the correct atomic int value, as the following example illustrates?

package main

import (
	"encoding/json"

	"go.uber.org/zap"
)

func main() {
	// For some users, the presets offered by the NewProduction, NewDevelopment,
	// and NewExample constructors won't be appropriate. For most of those
	// users, the bundled Config struct offers the right balance of flexibility
	// and convenience. (For more complex needs, see the AdvancedConfiguration
	// example.)
	//
	// See the documentation for Config and zapcore.EncoderConfig for all the
	// available options.
	rawJSON := []byte(`{
	  "level": "debug",
	  "encoding": "json",
	}`)

	var cfg zap.Config
	if err := json.Unmarshal(rawJSON, &cfg); err != nil {
		panic(err)
	}
	logger, err := cfg.Build()
	if err != nil {
		panic(err)
	}
	defer logger.Sync()

	logger.Info("logger construction succeeded")
}

答案1

得分: 2

AtomicLevel具有一个UnmarshalText方法,这意味着它实现了encoding.TextUnmarshaler接口。当JSON解码器看到一个JSON字符串并且目标类型实现了TextUnmarshaler接口时,它会调用其UnmarshalText方法将字符串转换为适当的值(除非该类型实现了json.Unmarshaler,在这种情况下,它优先)。AtomicLevel没有实现json.Unmarshaler

英文:

AtomicLevel has an UnmarshalText method, which means it implements the encoding.TextUnmarshaler interface. When the JSON decoder sees a JSON string and the destination is a type that implements TextUnmarshaler, its UnmarshalText method is called to convert the string into an appropriate value (unless the type implements json.Unmarshaler, in which case that takes precedence. AtomicLevel doesn't.)

huangapple
  • 本文由 发表于 2022年7月4日 10:00:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/72851107.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定