简体   繁体   中英

How to parse/create a dynamic url in golang

I am trying to create a buildURL function that can generate an url. However I have run into a problem when facing a dynamic url.

type ShopifyDownloader struct {
    Domain      string
    AccessToken string
}

func (sd *ShopifyDownloader) BuildURL(Path string, Query map[string]string) (string, error) {
    u, err := url.Parse("https://123.myshopify.com/admin/orders/count.json?access_token=123")
    if err != nil {
        fmt.Println("Cannot parse", err)
        return "", err
    }
    u.Host = sd.Domain
    u.Path = Path
    params := url.Values{}
    for key, value := range Query {
        params.Add(key, value)
    }
    u.RawQuery = params.Encode()
    nu := u.String()
    var buffer bytes.Buffer
    buffer.WriteString(nu)
    buffer.WriteString("?access_token=")
    buffer.WriteString(sd.AccessToken)
    bu := buffer.String()
    return bu, err
}

It takes domain, token, path and queries and generate an url in string. However it does not work with a dynamic path (with id) like this /admin/orders/#{id}.json or this /admin/products/#{id}/images/#{id}.json Does anybody have any suggestion?

Why not just build a url with something simpler at the point where you use it?

url := fmt.Sprintf("%s/admin/orders/count.json?access_token=%s&custom=%s",sd.Domain,sd.Token,customparam)

Then use it. This has the virtue of being completely clear as to intent and the url used in each case while sharing the important stuff (shopify domain etc). Then for your question about ids it becomes easier:

url := fmt.Sprintf("%s/admin/orders/%d.json?access_token=%s",sd.Domain,orderID,sd.Token)

and

url := fmt.Sprintf("%s/admin/products/%d/images/%d.json?access_token=%s",sd.Domain,productID,imageID,sd.Token)

if you feel your params are super complex (for me this would have to be at least 5), just put them in an url.Values (including the token):

params := url.Values{"myparam":{"123"}, "token": {sd.Token}}
url := fmt.Sprintf("%s/admin/orders/count.json?%s", sd.Domain, 
params.Encode())

but this is only worthwhile if you have a significant number of params.

If you want to add functions to ShopifyDownloader, why force the caller to define the url structure? Try to make it simpler for them. You don't need to parse urls or write to a bytes buffer, http.Get expects a string, so work with strings. If you want to build functions, consider instead having separate functions which know about the url formats, to abstract this away from the caller, so :

 func (sd *ShopifyDownloader) OrderURL(orderID int, params url.Values) string {
        params["token"] = []string{sd.AccessToken}
        return fmt.Sprintf("%s/admin/orders/%d.json?%s",sd.Domain,orderID,params)
    }

The caller should not know about the specific format of Shopify urls, which may change (just as the endpoint may change).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM