Ensure query strings are escaped properly; fixes #324
diff --git a/params.go b/params.go
index 68c17eb..a980903 100644
--- a/params.go
+++ b/params.go
@@ -103,7 +103,8 @@
 		optsType = optsType.Elem()
 	}
 
-	var optsSlice []string
+	params := url.Values{}
+
 	if optsValue.Kind() == reflect.Struct {
 		for i := 0; i < optsValue.NumField(); i++ {
 			v := optsValue.Field(i)
@@ -118,11 +119,11 @@
 				if !isZero(v) {
 					switch v.Kind() {
 					case reflect.String:
-						optsSlice = append(optsSlice, tags[0]+"="+v.String())
+						params.Add(tags[0], v.String())
 					case reflect.Int:
-						optsSlice = append(optsSlice, tags[0]+"="+strconv.FormatInt(v.Int(), 10))
+						params.Add(tags[0], strconv.FormatInt(v.Int(), 10))
 					case reflect.Bool:
-						optsSlice = append(optsSlice, tags[0]+"="+strconv.FormatBool(v.Bool()))
+						params.Add(tags[0], strconv.FormatBool(v.Bool()))
 					}
 				} else {
 					// Otherwise, the field is not set.
@@ -132,18 +133,9 @@
 					}
 				}
 			}
+		}
 
-		}
-		// URL encode the string for safety.
-		s := strings.Join(optsSlice, "&")
-		if s != "" {
-			s = "?" + s
-		}
-		u, err := url.Parse(s)
-		if err != nil {
-			return nil, err
-		}
-		return u, nil
+		return &url.URL{RawQuery: params.Encode()}, nil
 	}
 	// Return an error if the underlying type of 'opts' isn't a struct.
 	return nil, fmt.Errorf("Options type is not a struct.")
diff --git a/params_test.go b/params_test.go
index 9f1d3bd..4a2c9fe 100644
--- a/params_test.go
+++ b/params_test.go
@@ -43,7 +43,7 @@
 		R: "red",
 		C: true,
 	}
-	expected := &url.URL{RawQuery: "j=2&r=red&c=true"}
+	expected := &url.URL{RawQuery: "c=true&j=2&r=red"}
 	actual, err := BuildQueryString(&opts)
 	if err != nil {
 		t.Errorf("Error building query string: %v", err)
@@ -138,5 +138,18 @@
 	expected = false
 	actual = isZero(testStructValue)
 	th.CheckEquals(t, expected, actual)
+}
 
+func TestQueriesAreEscaped(t *testing.T) {
+	type foo struct {
+		Name  string `q:"something"`
+		Shape string `q:"else"`
+	}
+
+	expected := &url.URL{RawQuery: "else=Triangl+e&something=blah%2B%3F%21%21foo"}
+
+	actual, err := BuildQueryString(foo{Name: "blah+?!!foo", Shape: "Triangl e"})
+	th.AssertNoErr(t, err)
+
+	th.AssertDeepEquals(t, expected, actual)
 }