func Type(uri string) Option {
	return optionFunc(func(problem *Problem) {
		problem.data["type"] = uri
	})
}
Type sets the type URI (typically, with the "http" or "https" scheme) that identifies the problem type.
When dereferenced, it SHOULD provide human-readable documentation for the problem type
package problem
import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"net/http"
	"strconv"
)
const (
	ContentTypeJSON = "application/problem+json"
	ContentTypeXML = "application/problem+xml"
)
type Option interface {
	apply(*Problem)
}
type optionFunc func(*Problem)
func (f optionFunc) apply(problem *Problem) { f(problem) }
type Problem struct {
	data   map[string]interface{}
	reason error
}
func (p Problem) JSON() []byte {
	b, _ := p.MarshalJSON()
	return b
}
func (p Problem) XML() []byte {
	b, _ := xml.Marshal(p)
	return b
}
func (p Problem) UnmarshalJSON(b []byte) error {
	return json.Unmarshal(b, &p.data)
}
func (p Problem) MarshalJSON() ([]byte, error) {
	return json.Marshal(&p.data)
}
func (p *Problem) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	lastElem := ""
	for {
		if tok, err := d.Token(); err == nil {
			switch t := tok.(type) {
			case xml.StartElement:
				if t.Name.Space != "urn:ietf:rfc:7807" {
					return fmt.Errorf("Expected namespace urn:ietf:rfc:7807")
				}
				lastElem = t.Name.Local
			case xml.CharData:
				if lastElem != "" {
					if lastElem == "status" {
						i, err := strconv.Atoi(string(t))
						if err != nil {
							return err
						}
						p = p.Append(Status(i))
					} else {
						p = p.Append(Custom(lastElem, string(t)))
					}
				}
			}
		} else {
			break
		}
	}
	return nil
}
func (p Problem) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	start.Name = xml.Name{Local: "problem"}
	start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "xmlns"}, Value: "urn:ietf:rfc:7807"})
	tokens := []xml.Token{start}
	for k, v := range p.data {
		v := fmt.Sprintf("%v", v)
		t := xml.StartElement{Name: xml.Name{Space: "", Local: k}}
		tokens = append(tokens, t, xml.CharData(v), xml.EndElement{Name: t.Name})
	}
	tokens = append(tokens, xml.EndElement{Name: start.Name})
	for _, t := range tokens {
		e.EncodeToken(t)
	}
	return e.Flush()
}
func (p Problem) XMLString() string {
	return string(p.XML())
}
func (p Problem) JSONString() string {
	return string(p.JSON())
}
func (p Problem) Error() string {
	return p.JSONString()
}
func (p Problem) Is(err error) bool {
	return p.Error() == err.Error()
}
func (p Problem) Unwrap() error {
	return p.reason
}
func (p Problem) WriteTo(w http.ResponseWriter) (int, error) {
	w.Header().Set("Content-Type", ContentTypeJSON)
	if statuscode, ok := p.data["status"]; ok {
		if statusint, ok := statuscode.(int); ok {
			w.WriteHeader(statusint)
		}
	}
	return w.Write(p.JSON())
}
func (p Problem) WriteXMLTo(w http.ResponseWriter) (int, error) {
	w.Header().Set("Content-Type", ContentTypeXML)
	if statuscode, ok := p.data["status"]; ok {
		if statusint, ok := statuscode.(int); ok {
			w.WriteHeader(statusint)
		}
	}
	return w.Write(p.XML())
}
func New(opts ...Option) *Problem {
	problem := &Problem{}
	problem.data = make(map[string]interface{})
	for _, opt := range opts {
		opt.apply(problem)
	}
	return problem
}
func Of(statusCode int) *Problem {
	return New(Status(statusCode), Title(http.StatusText(statusCode)))
}
func (p *Problem) Append(opts ...Option) *Problem {
	for _, opt := range opts {
		opt.apply(p)
	}
	return p
}
func Wrap(err error) Option {
	return optionFunc(func(problem *Problem) {
		problem.reason = err
		problem.data["reason"] = err.Error()
	})
}