Go で URL を扱う時は通常、net/url
を使います。その際、例えばベースとなる URL にパスを足そうと思うと意外としんどかったりしました。
package main
import (
"fmt"
"log"
"net/url"
"path"
)
func main() {
endpoint := "https://example.com"
u, err := url.Parse(endpoint)
if err != nil {
log.Fatal(err)
}
u.Path = path.Join(u.Path, "foo", "bar", "baz")
endpoint = u.String()
fmt.Println(endpoint)
}
一部の方は「ハァッ?文字列で足せばいいじゃん」と思われるかもしれませんが、URL のパスを扱うという行為は実はとても難しい事なのです。path.Join
を使う事で、不要な /
が混じらない効果があります。また以下の様に相対パスを扱う場合
u.Path = path.Join(u.Path, "foo", "..", "baz")
https:///example.com/foo/baz
に修正してくれるといった効果もあります。そういう点で僕は Go で URL を扱う場合は面倒でも url.Parse
を使う事をオススメしています。しかしたかが元が文字列の URL にパスを足す為だけにこれだけのコードを書くのは、いくら Explicit の精神とは言え面倒に感じるのは共感できます。
net/url: add JoinPath, URL.JoinPath · golang/go@604140d · GitHubGo の master ブランチで
Builds on CL 332209. Fixes #47005 Change-Id: I82708dede05d79a196ca63f5a4e7cb5ac9a041ea GitHub-Last-R...
https://github.com/golang/go/commit/604140d93111f89911e17cb147dcf6a02d2700d0
net/url
に JoinPath
と URL.JoinPath
が追加されました。上記のコードであれば以下の様に簡単にパスを結合する事ができる様になりました。
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
endpoint := "https://example.com"
var err error
endpoint, err = url.JoinPath(endpoint, "foo", "bar")
if err != nil {
log.Fatal(err)
}
fmt.Println(endpoint)
}
URL のパスを組み立てる為に URL
を作らなくても良いので、ずいぶん楽になりました。