【问题标题】:Combine URL paths with path.Join()将 URL 路径与 path.Join() 组合
【发布时间】: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

Golang Playground

【问题讨论】:

    标签: url go path


    【解决方案1】:

    函数 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
    

    playground example

    如果您组合的多于路径(例如方案或主机)或字符串多于路径(例如它包括查询字符串),则使用ResolveReference

    【讨论】:

    • 这个答案正确解释了u.String()ResolveReference之间的细微差别
    • 我相信这在 Windows 上是不正确的,它会用“\”而不是“/”加入
    • @CodyA.Ray 该代码在 Windows 上正常工作。 path package 使用正斜杠分隔的路径,如包文档的第一段所述。 path/filepath 包在 Windows 上使用反斜杠,但这不是此答案中使用的包。
    • @CeriseLimón 但这是否意味着在 Windows 上运行时生成的 URL 看起来像“foo\bar.html”,而不是预期的“foo/bar.html”?
    • @CodyA.Ray 路径包适用于所有平台上的正斜杠分隔路径。 path.Join(u.Path, "bar.html")生成的路径在所有平台上都是"/foo/bar.html",包括Windows。 Join 实现中的路径包literally uses forward slash
    【解决方案2】:

    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))
    }
    

    【讨论】:

      【解决方案3】:

      一个简单的方法是修剪你不想要的 / 并加入。这是一个示例函数

      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)
      

      这消除了检查/返回错误的需要

      【讨论】:

        【解决方案4】:

        要加入URL 与另一个URL 或路径,有URL.Parse()

        func (u *URL) Parse(ref string) (*URL, error)
        

        Parse 在接收者的上下文中解析 URL。提供的网址 可能是相对绝对。解析失败时,解析返回 nilerr, 否则返回值与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())
        }
        

        【讨论】:

          【解决方案5】:

          我编写了这个适用于我的用途的实用函数:

          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

          【讨论】:

            猜你喜欢
            • 2015-07-13
            • 1970-01-01
            • 1970-01-01
            • 2021-04-26
            • 1970-01-01
            • 1970-01-01
            • 2021-02-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多