Объедините URL-пути с path.Join()

Есть ли способ в Go объединить пути URL-адреса так же, как мы можем с path.Join() используя path.Join()?

Например, см. например, Объединить абсолютный путь и относительный путь, чтобы получить новый абсолютный путь.

Когда я использую path.Join("http://foo", "bar"), я получаю http: /foo/bar.

Смотрите на игровой площадке Golang.

Ответ 1

Путь функции.Join ожидает путь, а не URL. Разберите URL-адрес, чтобы получить путь и присоединиться к этому пути:

u, err := url.Parse("http://foo")
u.Path = path.Join(u.Path, "bar.html")
s := u.String() // prints http://foo/bar.html

playground example

Если вы комбинируете больше, чем путь (например, схема или хост), или строка больше, чем путь (например, включает строку запроса), используйте ResolveReference.

Ответ 2

ResolveReference() в пакете net/url

Принятый ответ не будет работать для относительных путей URL, содержащих окончание файла, например .html или .img. Функция ResolveReference() - это правильный способ соединения URL-адресов в go.

package main

import (
    "fmt"
    "log"
    "net/url"
)

func main() {
    u, err := url.Parse("../../..//search?q=dotnet")
    if err != nil {
        log.Fatal(err)
    }
    base, err := url.Parse("http://example.com/directory/")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(base.ResolveReference(u))
}

Ответ 3

Я написал эту функцию утилиты, которая работает для моих целей:

func Join(basePath string, paths ...string) (*url.URL, error) {

    u, err := url.Parse(basePath)

    if err != nil {
        return nil, fmt.Errorf("invalid url")
    }

    p2 := append([]string{u.Path}, paths...)

    result := path.Join(p2...)

    u.Path = result

    return u, nil
}

https://play.golang.org/p / -QNVvyzacMM

Ответ 4

Простой подход к этому состоит в том, чтобы обрезать/вы не хотите и присоединиться. Вот пример func

func JoinURL(base string, paths ...string) string {
    p := path.Join(paths...)
    return fmt.Sprintf("%s/%s", strings.TrimRight(base, "/"), strings.TrimLeft(p, "/"))
}

Использование будет

b := "http://my.domain.com/api/"
u := JoinURL(b, "/foo", "bar/", "baz")
fmt.Println(u)

Это устраняет необходимость проверки/возврата ошибок