go net: clarify safe way to do URL deep-copying

jqjz2hbq  于 6个月前  发布在  Go
关注(0)|答案(5)|浏览(44)

有时候需要复制(别名为“深拷贝”)一个 net.URL 对象。我的理解是,net.URL 可以通过简单地复制结构来安全地复制:

newUrl := *url

由于 net.URL 通常由指针处理,因此检查文档以查看对象是否包含内部指针是很正常的,在这种情况下,复制可能会变得棘手。net.URL 的内容如下:

type URL struct {
    Scheme     string
    Opaque     string    // encoded opaque data
    User       *Userinfo // username and password information
    Host       string    // host or host:port
    Path       string    // path (relative paths may omit leading slash)
    RawPath    string    // encoded path hint (see EscapedPath method); added in Go 1.5
    ForceQuery bool      // append a query ('?') even if RawQuery is empty; added in Go 1.7
    RawQuery   string    // encoded query values, without '?'
    Fragment   string    // fragment for references, without '#'
}

所以确实有一个指针在那里。这促使人们想出了另一种复制 URL 的方法,例如 String / Parse 往返:
https://medium.com/@nrxr/quick-dirty-way-to-deep-copy-a-url-url-on-go-464312241de4
这里的技巧是,User *Userinfo 实际上是“不可变的”。这是在 Userinfo 中记录的:The Userinfo type is an immutable encapsulation of username and password [...]。因此,鉴于这种不变性的保证,简单地复制一个 URL 示例来复制它是安全的。标准库也执行 URL 示例的复制操作,例如:
go/src/net/http/request.go
第 361 行中的 245409e
| | *r2=*r |
因此,这个问题的主题是:

  • 我能否得到确认,复制 URL 是正确的方法,而不仅仅是当前实现的意外(因此,它受到 Go 1.0 兼容性的保证)?
  • 我们是否应该更好地记录它,因为它往往对这个库的新来的读者来说令人困惑?要么明确说明复制它的正确方法,要么将“不可变”一词移动到 User *Userinfo 字段的内联文档中(或者两者都做?)。
3mpgtkmj

3mpgtkmj1#

这个文档更好吗?

euoag5mw

euoag5mw2#

你好,@rasky。
确实安全,事实上,我是Medium帖子的作者,我在几周前合并的一个PR中使用了newU := *u方法:https://github.com/golang/go/pull/35578/files#diff-6c2d018290e298803c0c9419d8739885R824-R837

jvlzgdj9

jvlzgdj93#

相关评论#41733(评论) 由@rsc发表

我仍然不明白在URL文档中究竟有什么值得一提的。
这是一个关于数据的一般性质,如果你想在变异之前复制一份,你可以这样做:u2 := *u; mutate u2。
我仍然不明白在URL上这个操作需要多少次。
@ainar-g已经看到过,但这只是存在,而不是频率。

hi3rlvi2

hi3rlvi24#

关于#41733存在一些令人困惑的地方,因为实际上在net/http内部有一个cloneURL函数,而不仅仅是一个u2 := *u的事情。然而,它并不是url.URL公共协议的一部分,原因不明。

moiiocjp

moiiocjp5#

最近遇到了一个问题,没有好的方法来深度克隆一个URL。

相关问题