func (mp mpath) merge(v url.Values) (outPath string, otherValues url.Values, reterr error) {
	if len(v) > 0 {
		otherValues = make(url.Values, len(v))
		for k, val := range v {
			otherValues[k] = val
		}
	}
	var buf bytes.Buffer
	buf.Grow(64)
	for _, p := range mp {
		if strings.HasPrefix(p, "/:") {
			pname := p[2:]
			vlist := v[pname]
			buf.WriteString("/")
			if len(vlist) == 0 {  
				reterr = errMissingParam
				buf.WriteString("_")
				continue
			}
			buf.WriteString(vlist[0])
			otherValues.Del(pname)
			continue
		}
		buf.WriteString(p)
		continue
	}
	if len(otherValues) == 0 {
		otherValues = nil
	}
	return buf.String(), otherValues, reterr
}
merge will use any values provided for the appropriate path params
and return the constructed path.  A missing param value will cause
errMissingParam to be returned but will still return the path with
the missing param(s) replaced with "_".  The otherValues will
be populated with all values not merged into the output path.
package vgrouter
import (
	"bytes"
	"errors"
	"net/url"
	"path"
	"strings"
)
func parseMpath(p string) (mpath, error) {
	ret := make(mpath, 0, 2)
	p = path.Clean("/" + p)
	startIdx := 0
	for i, c := range p {
		if c == '/' {
			str := p[startIdx:i]
			if len(str) > 0 {
				ret = append(ret, str)
			}
			startIdx = i
		}
	}
	str := p[startIdx:]
	if len(str) > 0 {
		ret = append(ret, str)
	}
	return ret, nil
}
type mpath []string
func (mp mpath) paramNames() []string {
	var ret []string
	for _, p := range mp {
		if strings.HasPrefix(p, "/:") {
			ret = append(ret, p[2:])
		}
	}
	return ret
}
func (mp mpath) String() string {
	return strings.Join(mp, "")
}
var errMissingParam = errors.New("missing param")