英文:
Copy net.IP in Golang
问题
我尝试复制一个net.IP实例的值(第14行和第19行),但显然只是传递了指针。我做错了什么?
请求的代码如下:
package main
import (
"log"
"net"
)
type Range struct {
Start net.IP `json:"start"`
End net.IP `json:"end"`
}
func (r Range) Expand() []net.IP {
next := r.Start // 这里(第14行)
out := []net.IP{next}
for !next.Equal(r.End) {
incIP(next)
out = append(out, next) // 这里(第19行)
}
return out
}
func incIP(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
func main() {
r := Range{
Start: net.ParseIP("192.100.10.4"),
End: net.ParseIP("192.100.13.1"),
}
out := r.Expand()
log.Print(r)
log.Print(out)
}
你在代码中的问题是,你传递的是指针而不是值。在Go语言中,net.IP是一个切片类型,它是一个引用类型。当你将一个切片传递给函数时,实际上传递的是切片的指针,而不是切片的副本。因此,在你的代码中,你修改的是原始切片,而不是副本。
要解决这个问题,你可以在Expand函数中创建一个新的net.IP实例,并将原始的net.IP值复制到新的实例中。这样,你就可以修改新的实例而不会影响原始的net.IP值。
以下是修改后的代码:
func (r Range) Expand() []net.IP {
next := net.IP(r.Start.To4()) // 创建新的net.IP实例并复制值
out := []net.IP{next}
for !next.Equal(r.End) {
incIP(next)
out = append(out, net.IP(next.To4())) // 创建新的net.IP实例并复制值
}
return out
}
通过使用net.IP.To4()
方法,你可以创建一个新的net.IP实例并复制原始值。这样,你就可以在循环中修改新的实例,并将其添加到输出切片中,而不会影响原始的net.IP值。
希望这可以帮助到你!
英文:
I try to copy the value of a net.IP instance (line 14 and 19) but obviously just pass around the pointer:
http://play.golang.org/p/xmYQrsf496
What am I doing wrong?
CODE as requested:
package main
import (
"log"
"net"
)
type Range struct {
Start net.IP `json:"start"`
End net.IP `json:"end"`
}
func (r Range) Expand() []net.IP {
next := r.Start // here (line 14)
out := []net.IP{next}
for !next.Equal(r.End) {
incIP(next)
out = append(out, next) // and here (line 19)
}
return out
}
func incIP(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
func main() {
r := Range{
Start: net.ParseIP("192.100.10.4"),
End: net.ParseIP("192.100.13.1"),
}
out := r.Expand()
log.Print(r)
log.Print(out)
}
答案1
得分: 6
看一下net.IP
的文档;它只是一个[]byte
,所以你可以使用copy
内置函数。
例如:
func dupIP(ip net.IP) net.IP {
dup := make(net.IP, len(ip))
copy(dup, ip)
return dup
}
如果你关心空间,你还可以从文档中注意到,尽管所有的net
例程都支持长度为4的net.IP
(例如ip := net.IP([]byte{1, 2, 3, 4}
)可以工作),但它们生成的所有例程都是16字节。由于你要创建很多个,如果你关心几个字节的空间,或者如果你关心255.255.255.255之后会发生什么,你可以像下面这样避免这个问题:
func dupIP(ip net.IP) net.IP {
// 为了节省空间,尽量只使用4个字节
if x := ip.To4(); x != nil {
ip = x
}
dup := make(net.IP, len(ip))
copy(dup, ip)
return dup
}
对于IPv6地址,你可能希望做一些不同的处理,我认为按照你的方式对IPv6进行“递增”可能没有意义,不过我可能错了。
你可以在这里找到修改后的原始版本:https://play.golang.org/p/GP9vASvUgh
英文:
Look at the documentation for net.IP
; it's just a []byte
so you could use the copy
builtin.
E.g.:
func dupIP(ip net.IP) net.IP {
dup := make(net.IP, len(ip))
copy(dup, ip)
return dup
}
If you care about space, you can also note from the documentation that although all the net
routines support a net.IP
of length 4 (e.g. ip := net.IP([]byte{1, 2, 3, 4}
) will work) all the ones they generate are 16 bytes. Since you make a whole bunch, if you care about a few bytes of space, or if you care what happens after 255.255.255.255, you can avoid this for IPv4 like so:
func dupIP(ip net.IP) net.IP {
// To save space, try and only use 4 bytes
if x := ip.To4(); x != nil {
ip = x
}
dup := make(net.IP, len(ip))
copy(dup, ip)
return dup
}
You may want to do something different for IPv6 addresses, I don't think it makes sense to "increment" an IPv6 the way you do, I could be wrong though.
Modified version of your original:
https://play.golang.org/p/GP9vASvUgh
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论