package tracker import ( "errors" "net" "net/url" "reflect" "strconv" "strings" ) type Request struct { InfoHash []byte `query:"info_hash"` PeerID []byte `query:"peer_id"` Port int `query:"port"` Uploaded int `query:"uploaded"` Downloaded int `query:"downloaded"` Left int `query:"left"` IP net.IPAddr `query:"ip,optional"` NumWant int `query:"numwant,optional"` } func MarshalQuery(v interface{}) (string, error) { val := reflect.ValueOf(v) return marshalQuery(val) } func marshalQuery(v reflect.Value) (string, error) { if v.Kind() != reflect.Struct { return "", errors.New("must be a struct") } q := url.Values{} t := v.Type() for i := 0; i < t.NumField(); i++ { name := strings.ToLower(t.Field(i).Name) f := v.Field(i) switch f.Kind() { case reflect.Int: q.Add(name, strconv.Itoa(int(f.Int()))) case reflect.String: q.Add(name, f.String()) case reflect.Slice: if f.Type().Elem().Kind() == reflect.Uint8 { q.Add(name, string(f.Bytes())) } } } return "?" + q.Encode(), nil }