【发布时间】:2016-04-12 14:27:49
【问题描述】:
Go 中有没有一种方法可以像使用 path.Join() 处理文件路径一样组合 URL 路径?
例如参见例如Combine absolute path and relative path to get a new absolute path。
当我使用path.Join("http://foo", "bar") 时,我得到http:/foo/bar。
【问题讨论】:
Go 中有没有一种方法可以像使用 path.Join() 处理文件路径一样组合 URL 路径?
例如参见例如Combine absolute path and relative path to get a new absolute path。
当我使用path.Join("http://foo", "bar") 时,我得到http:/foo/bar。
【问题讨论】:
函数 path.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
如果您组合的多于路径(例如方案或主机)或字符串多于路径(例如它包括查询字符串),则使用ResolveReference。
【讨论】:
u.String()和ResolveReference之间的细微差别
path.Join(u.Path, "bar.html")生成的路径在所有平台上都是"/foo/bar.html",包括Windows。 Join 实现中的路径包literally uses forward slash。
ResolveReference() in net/url package
接受的答案不适用于包含 .html 或 .img 等文件结尾的相对 url 路径。 ResolveReference() 函数是 go 中加入 url 路径的正确方法。
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))
}
【讨论】:
一个简单的方法是修剪你不想要的 / 并加入。这是一个示例函数
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)
这消除了检查/返回错误的需要
【讨论】:
要加入URL 与另一个URL 或路径,有URL.Parse():
func (u *URL) Parse(ref string) (*URL, error)Parse 在接收者的上下文中解析 URL。提供的网址 可能是相对或绝对。解析失败时,解析返回
nil、err, 否则返回值与ResolveReference相同。
func TestURLParse(t *testing.T) {
baseURL, _ := url.Parse("http://foo/a/b/c")
url1, _ := baseURL.Parse("d/e")
require.Equal(t, "http://foo/a/b/d/e", url1.String())
url2, _ := baseURL.Parse("../d/e")
require.Equal(t, "http://foo/a/d/e", url2.String())
url3, _ := baseURL.Parse("/d/e")
require.Equal(t, "http://foo/d/e", url3.String())
}
【讨论】:
我编写了这个适用于我的用途的实用函数:
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
}
【讨论】: