func marshalWithSprint(t reflect.Type, tag tag) marshaler {
	formSet := formSetter(tag)
	omit := omitter(t, tag)
	return func(v reflect.Value, p *Params) error {
		if omit(v) {
			return nil
		}
		formSet(tag.name, fmt.Sprint(v.Interface()), p)
		return nil
	}
}
marshalWithSprint returns an marshaler
that unmarshals the given tag using fmt.Sprint.
package httprequest
import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"reflect"
	"strings"
	"github.com/julienschmidt/httprouter"
	"gopkg.in/errgo.v1"
)
func Marshal(baseURL, method string, x interface{}) (*http.Request, error) {
	var xv reflect.Value
	if ch, ok := x.(*CustomHeader); ok {
		xv = reflect.ValueOf(ch.Body)
	} else {
		xv = reflect.ValueOf(x)
	}
	pt, err := getRequestType(xv.Type())
	if err != nil {
		return nil, errgo.WithCausef(err, ErrBadUnmarshalType, "bad type %s", xv.Type())
	}
	req, err := http.NewRequest(method, baseURL, BytesReaderCloser{bytes.NewReader(nil)})
	if err != nil {
		return nil, errgo.Mask(err)
	}
	req.Form = url.Values{}
	if pt.formBody {
		req.PostForm = url.Values{}
	}
	p := &Params{
		Request: req,
	}
	if err := marshal(p, xv, pt); err != nil {
		return nil, errgo.Mask(err, errgo.Is(ErrUnmarshal))
	}
	if pt.formBody {
		data := []byte(req.PostForm.Encode())
		p.Request.Body = BytesReaderCloser{bytes.NewReader(data)}
		p.Request.ContentLength = int64(len(data))
		p.Request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		p.Request.PostForm = nil
	}
	if headerSetter, ok := x.(HeaderSetter); ok {
		headerSetter.SetHeader(p.Request.Header)
	}
	return p.Request, nil
}
func marshal(p *Params, xv reflect.Value, pt *requestType) error {
	xv = xv.Elem()
	for _, f := range pt.fields {
		fv := xv.FieldByIndex(f.index)
		if f.isPointer {
			if fv.IsNil() {
				continue
			}
			fv = fv.Elem()
		}
		if err := f.marshal(fv, p); err != nil {
			return errgo.WithCausef(err, ErrUnmarshal, "cannot marshal field")
		}
	}
	path, err := buildPath(p.Request.URL.Path, p.PathVar)
	if err != nil {
		return errgo.Mask(err)
	}
	p.Request.URL.Path = path
	if q := p.Request.Form.Encode(); q != "" && p.Request.URL.RawQuery != "" {
		p.Request.URL.RawQuery += "&" + q
	} else {
		p.Request.URL.RawQuery += q
	}
	return nil
}
func buildPath(path string, p httprouter.Params) (string, error) {
	pathBytes := make([]byte, 0, len(path)*2)
	for {
		s, rest := nextPathSegment(path)
		if s == "" {
			break
		}
		if s[0] != ':' && s[0] != '*' {
			pathBytes = append(pathBytes, s...)
			path = rest
			continue
		}
		if s[0] == '*' && rest != "" {
			return "", errgo.New("star path parameter is not at end of path")
		}
		if len(s) == 1 {
			return "", errgo.New("empty path parameter")
		}
		val := p.ByName(s[1:])
		if val == "" {
			return "", errgo.Newf("missing value for path parameter %q", s[1:])
		}
		if s[0] == '*' {
			if !strings.HasPrefix(val, "/") {
				return "", errgo.Newf("value %q for path parameter %q does not start with required /", val, s)
			}
			val = val[1:]
		}
		pathBytes = append(pathBytes, val...)
		path = rest
	}
	return string(pathBytes), nil
}
func nextPathSegment(s string) (string, string) {
	if s == "" {
		return "", ""
	}
	if s[0] == ':' || s[0] == '*' {
		if i := strings.Index(s, "/"); i != -1 {
			return s[0:i], s[i:]
		}
		return s, ""
	}
	if i := strings.IndexAny(s, ":*"); i != -1 {
		return s[0:i], s[i:]
	}
	return s, ""
}
func getMarshaler(tag tag, t reflect.Type) (marshaler, error) {
	switch {
	case tag.source == sourceNone:
		return marshalNop, nil
	case tag.source == sourceBody:
		return marshalBody, nil
	case t == reflect.TypeOf([]string(nil)):
		switch tag.source {
		default:
			return nil, errgo.New("invalid target type []string for path parameter")
		case sourceForm:
			return marshalAllForm(tag.name), nil
		case sourceFormBody:
			return marshalAllFormBody(tag.name), nil
		case sourceHeader:
			return marshalAllHeader(tag.name), nil
		}
	case t == reflect.TypeOf(""):
		return marshalString(tag), nil
	case implementsTextMarshaler(t):
		return marshalWithMarshalText(t, tag), nil
	default:
		return marshalWithSprint(t, tag), nil
	}
}
func marshalNop(v reflect.Value, p *Params) error {
	return nil
}
func marshalBody(v reflect.Value, p *Params) error {
	data, err := json.Marshal(v.Addr().Interface())
	if err != nil {
		return errgo.Notef(err, "cannot marshal request body")
	}
	p.Request.Body = BytesReaderCloser{bytes.NewReader(data)}
	p.Request.ContentLength = int64(len(data))
	p.Request.Header.Set("Content-Type", "application/json")
	return nil
}
func marshalAllForm(name string) marshaler {
	return func(v reflect.Value, p *Params) error {
		if ss := v.Interface().([]string); len(ss) > 0 {
			p.Request.Form[name] = ss
		}
		return nil
	}
}
func marshalAllFormBody(name string) marshaler {
	return func(v reflect.Value, p *Params) error {
		if ss := v.Interface().([]string); len(ss) > 0 {
			p.Request.PostForm[name] = ss
		}
		return nil
	}
}
func marshalAllHeader(name string) marshaler {
	return func(v reflect.Value, p *Params) error {
		if ss := v.Interface().([]string); len(ss) > 0 {
			p.Request.Header[name] = ss
		}
		return nil
	}
}
func marshalString(tag tag) marshaler {
	formSet := formSetter(tag)
	return func(v reflect.Value, p *Params) error {
		s := v.String()
		if tag.omitempty && s == "" {
			return nil
		}
		formSet(tag.name, v.String(), p)
		return nil
	}
}
type encodingTextMarshaler interface {
	MarshalText() (text []byte, err error)
}
var textMarshalerType = reflect.TypeOf((*encodingTextMarshaler)(nil)).Elem()
func implementsTextMarshaler(t reflect.Type) bool {
	return reflect.PtrTo(t).Implements(textMarshalerType)
}
func marshalWithMarshalText(t reflect.Type, tag tag) marshaler {
	formSet := formSetter(tag)
	omit := omitter(t, tag)
	return func(v reflect.Value, p *Params) error {
		if omit(v) {
			return nil
		}
		m := v.Addr().Interface().(encodingTextMarshaler)
		data, err := m.MarshalText()
		if err != nil {
			return errgo.Mask(err)
		}
		formSet(tag.name, string(data), p)
		return nil
	}
}
type IsZeroer interface {
	IsZero() bool
}
var isZeroerType = reflect.TypeOf((*IsZeroer)(nil)).Elem()
func omitter(t reflect.Type, tag tag) func(reflect.Value) bool {
	never := func(reflect.Value) bool {
		return false
	}
	if !tag.omitempty {
		return never
	}
	if reflect.PtrTo(t).Implements(isZeroerType) {
		return func(v reflect.Value) bool {
			return v.Addr().Interface().(IsZeroer).IsZero()
		}
	}
	if t.Comparable() {
		zeroVal := reflect.Zero(t).Interface()
		return func(v reflect.Value) bool {
			return v.Interface() == zeroVal
		}
	}
	return never
}