func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error {
	if err := checkExtensionTypes(pb, extension); err != nil {
		return err
	}
	typ := reflect.TypeOf(extension.ExtensionType)
	if typ != reflect.TypeOf(value) {
		return errors.New("bad extension value type")
	}
	pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
	return nil
}
TODO: (needed for repeated extensions)
- ExtensionSize
- AddExtension
SetExtension sets the specified extension of pb to the specified value.
package proto
import (
	"errors"
	"reflect"
	"strconv"
	"unsafe"
)
type ExtensionRange struct {
	Start, End int32  
}
type extendableProto interface {
	ExtensionRangeArray() []ExtensionRange
	ExtensionMap() map[int32]Extension
}
type ExtensionDesc struct {
	ExtendedType  interface{}  
	ExtensionType interface{}  
	Field         int32        
	Name          string       
	Tag           string       
}
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("bad extended type; " + b.String() + " does not extend " + a.String())
	}
	if !isExtensionField(pb, extension.Field) {
		return errors.New("bad extension number; not in declared ranges")
	}
	return nil
}
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 := new(Properties)
		props.Init(et, "unknown_name", e.desc.Tag, 0)
		p := NewBuffer(nil)
		x := reflect.New(et)
		x.Elem().Set(reflect.ValueOf(e.value))
		if err := props.enc(p, props, x.Pointer()); err != nil {
			return err
		}
		e.enc = p.buf
		m[k] = e
	}
	return nil
}
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)
}
func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
	if err := checkExtensionTypes(pb, extension); err != nil {
		return nil, err
	}
	e, ok := pb.ExtensionMap()[extension.Field]
	if !ok {
		return nil, nil  
	}
	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
	return e.value, nil
}
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
	_, n := DecodeVarint(b)
	o := NewBuffer(b[n:])
	t := reflect.TypeOf(extension.ExtensionType)
	props := &Properties{}
	props.Init(t, "irrelevant_name", extension.Tag, 0)
	base := unsafe.New(t)
	var sbase uintptr
	if t.Elem().Kind() == reflect.Struct {
		*(*unsafe.Pointer)(base) = unsafe.New(t.Elem())
	} else {
		sbase = uintptr(unsafe.New(t.Elem()))
	}
	if err := props.dec(o, props, uintptr(base), sbase); err != nil {
		return nil, err
	}
	return unsafe.Unreflect(t, base), nil
}
func GetExtensions(pb interface{}, es []*ExtensionDesc) (extensions []interface{}, err error) {
	epb, ok := pb.(extendableProto)
	if !ok {
		err = errors.New("not an extendable proto")
		return
	}
	extensions = make([]interface{}, len(es))
	for i, e := range es {
		extensions[i], err = GetExtension(epb, e)
		if err != nil {
			return
		}
	}
	return
}