這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
首先上代碼:
func main() {b := truea1, _ := json.Marshal(b)a2, _ := Marshal(b)fmt.Println(string(a1))fmt.Println(string(a2))}
輸出:
truetrue
以最簡單的單個bool 類型的序列化為例,我們來搞清楚json 包裡面的調用棧如下:
從入口出發,第一個方法是:
func Marshal(v interface{}) ([]byte, error) {e := &encodeState{}err := e.marshal(v)if err != nil {return nil, err}return e.Bytes(), nil}
這裡沒有什麼特殊,只是為了引出encodeState
// An encodeState encodes JSON into a bytes.Buffer.type encodeState struct {bytes.Buffer // accumulated outputscratch [64]byte}
這裡的Buffer就是我們所有輸出位元組的Buffer,再繼續往裡面走
func (e *encodeState) marshal(v interface{}) (err error) {defer func() {if r := recover(); r != nil {if _, ok := r.(runtime.Error); ok {panic(r)}if s, ok := r.(string); ok {panic(s)}err = r.(error)}}()e.reflectValue(reflect.ValueOf(v))return nil}
這裡我們看到了反射獲得值,個人認為這裡的命名不太科學,不過無妨,繼續往下走。
func valueEncoder(v reflect.Value) encoderFunc {if !v.IsValid() {return invalidValueEncoder}return typeEncoder(v.Type())}
這裡通過反射的類型,獲得和使用該類型的序列化方法.順便還做了把緩衝。
func typeEncoder(t reflect.Type) encoderFunc {encoderCache.RLock()f := encoderCache.m[t]encoderCache.RUnlock()if f != nil {return f}// To deal with recursive types, populate the map with an// indirect func before we build it. This type waits on the// real func (f) to be ready and then calls it. This indirect// func is only used for recursive types.encoderCache.Lock()if encoderCache.m == nil {encoderCache.m = make(map[reflect.Type]encoderFunc)}var wg sync.WaitGroupwg.Add(1)encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {wg.Wait()f(e, v, quoted)}encoderCache.Unlock()// Compute fields without lock.// Might duplicate effort but won't hold other computations back.f = newTypeEncoder(t, true)wg.Done()encoderCache.Lock()encoderCache.m[t] = fencoderCache.Unlock()return f}
至於具體的Encoder,通過Type很容易找到。
switch t.Kind() {case reflect.Bool:return boolEncodercase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:return intEncodercase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:return uintEncodercase reflect.Float32:return float32Encodercase reflect.Float64:return float64Encodercase reflect.String:return stringEncodercase reflect.Interface:return interfaceEncodercase reflect.Struct:return newStructEncoder(t)case reflect.Map:return newMapEncoder(t)case reflect.Slice:return newSliceEncoder(t)case reflect.Array:return newArrayEncoder(t)case reflect.Ptr:return newPtrEncoder(t)default:return unsupportedTypeEncoder
最終我們這裡的boolEncoder的實現
func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {if quoted {e.WriteByte('"')}if v.Bool() {e.WriteString("true")} else {e.WriteString("false")}if quoted {e.WriteByte('"')}}
當然這個只是一個最簡單的樣本,裡面很多實現的細節可以推敲。這裡只是把這種序列化的方式歸結為類型反射+緩衝的方式。
備忘
這個系列不是一個大而全的package api 指南,只包括作者認為最常見的使用方式。抗議無效。