func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
	if err := checkExtensionTypes(pb, extension); err != nil {
		return nil, err
	}
	emap := pb.ExtensionMap()
	e, ok := emap[extension.Field]
	if !ok {
		return defaultExtensionValue(extension)
	}
	if e.value != nil {
		if e.desc != extension {
			return nil, errors.New("proto: descriptor conflict")
		}
		return e.value, nil
	}
	v, err := decodeExtension(e.enc, extension)
	if err != nil {
		return nil, err
	}
	e.value = v
	e.desc = extension
	e.enc = nil
	emap[extension.Field] = e
	return e.value, nil
}
GetExtension parses and returns the given extension of pb.
If the extension is not present and has no default value it returns ErrMissingExtension.
package proto
import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"sync"
)
var ErrMissingExtension = errors.New("proto: missing extension")
type ExtensionRange struct {
	Start, End int32  
}
type extendableProto interface {
	Message
	ExtensionRangeArray() []ExtensionRange
	ExtensionMap() map[int32]Extension
}
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
type ExtensionDesc struct {
	ExtendedType  Message      
	ExtensionType interface{}  
	Field         int32        
	Name          string       
	Tag           string       
}
func (ed *ExtensionDesc) repeated() bool {
	t := reflect.TypeOf(ed.ExtensionType)
	return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
}
type Extension struct {
	desc  *ExtensionDesc
	value interface{}
	enc   []byte
}
func SetRawExtension(base extendableProto, id int32, b []byte) {
	base.ExtensionMap()[id] = Extension{enc: b}
}
func isExtensionField(pb extendableProto, field int32) bool {
	for _, er := range pb.ExtensionRangeArray() {
		if er.Start <= field && field <= er.End {
			return true
		}
	}
	return false
}
func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
	if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b {
		return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
	}
	if !isExtensionField(pb, extension.Field) {
		return errors.New("proto: bad extension number; not in declared ranges")
	}
	return nil
}
type extPropKey struct {
	base  reflect.Type
	field int32
}
var extProp = struct {
	sync.RWMutex
	m map[extPropKey]*Properties
}{
	m: make(map[extPropKey]*Properties),
}
func extensionProperties(ed *ExtensionDesc) *Properties {
	key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
	extProp.RLock()
	if prop, ok := extProp.m[key]; ok {
		extProp.RUnlock()
		return prop
	}
	extProp.RUnlock()
	extProp.Lock()
	defer extProp.Unlock()
	if prop, ok := extProp.m[key]; ok {
		return prop
	}
	prop := new(Properties)
	prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
	extProp.m[key] = prop
	return prop
}
func encodeExtensionMap(m map[int32]Extension) error {
	for k, e := range m {
		if e.value == nil || e.desc == nil {
			continue
		}
		et := reflect.TypeOf(e.desc.ExtensionType)
		props := extensionProperties(e.desc)
		p := NewBuffer(nil)
		x := reflect.New(et)
		x.Elem().Set(reflect.ValueOf(e.value))
		if err := props.enc(p, props, toStructPointer(x)); err != nil {
			return err
		}
		e.enc = p.buf
		m[k] = e
	}
	return nil
}
func sizeExtensionMap(m map[int32]Extension) (n int) {
	for _, e := range m {
		if e.value == nil || e.desc == nil {
			n += len(e.enc)
			continue
		}
		et := reflect.TypeOf(e.desc.ExtensionType)
		props := extensionProperties(e.desc)
		x := reflect.New(et)
		x.Elem().Set(reflect.ValueOf(e.value))
		n += props.size(props, toStructPointer(x))
	}
	return
}
func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
	_, ok := pb.ExtensionMap()[extension.Field]
	return ok
}
func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
	delete(pb.ExtensionMap(), extension.Field)
}