3

对不起标题,我不知道怎么说

我对此代码有疑问

func ip2long(ip string) (ret int64) {
  p:= strings.Split(ip, ".")
  n, _:= strconv.Atoi(p[0])
  ret += int64(n)*16777216 
  n, _= strconv.Atoi(p[1])
  ret += int64(n)*65536 
  n, _= strconv.Atoi(p[2])
  ret += int64(n)*256
  n, _= strconv.Atoi(p[3])
  ret += int64(n)

  return 
}

我想将IP地址转换为整数

你看我写了这么丑的代码

首先从 strconv.Atoi 检索数字,然后将其转换为 int64

如何简化这个?

4

3 回答 3

7

如果要从字符串中解析多个整数,请尝试使用 Sscanf 函数,如下所示:

func main() {
    var ip [4] uint32
    addr := "192.168.0.1"
    _, err := fmt.Sscanf(addr, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(ip)
    fmt.Println(ip[0]<<24 + ip[1]<<16 + ip[2]<<8 + ip[3])
}
于 2012-06-09T18:02:07.050 回答
6

这个结构很重,但如果您可能应该捕获解析错误,则看起来更自然。

话虽这么说,该确切问题的正确解决方案是使用 net.ParseIP构建IP的现有功能

func ParseIP(s string) IP

如果您必须保留当前的函数原型,我建议:

func ip2long(s string) (ret int64) {
    bip := ([]byte)(net.ParseIP(s).To4())
    return (int64)(bip[0]) * (1 << 24) + (int64)(bip[1]) * (1 << 16) + (int64)(bip[2]) * (1 << 8) + (int64)(bip[3])
}

请注意,您可以在 ParseIP 的返回上添加一个测试(如果出现错误,则为 nil)

于 2012-06-09T14:50:48.397 回答
1

我不推荐它,因为你会忽略错误,但你可以编写一个函数来给你第一个值:

func first(x int, _ error) int {return x;}

然后first(strconv.Atoi(p[0]))在您的代码中使用。

不过,对于您列出的特定代码,我将使用(经过充分测试!)标准库的 net.ParseIP() 和 net.To4() 函数:

// WARNING untested code!!

type InvalidIP string
func (InvalidIP ipStr) Error() string {
    return "Invalid IPv4 address: "+ipStr
}

func ip2long(ipStr string) (ret int64, err error) {
    var ip net.IP
    if ip = net.ParseIP(ipStr); ip == nil {
        return 0, InvalidIP(ip)
    }
    if ip = ip.To4(); ip == nil {
        return 0, InvalidIP(ip)
    }
    for b := range ip {
        ret <<= 8
        ret += b
    }
    return ret, nil
}

请注意,上面的代码添加了错误检查,并且还接受 IPv6 格式的 v4 地址“::FFFF:C0A8:0101”。考虑您是否真的需要一个 int64 类型来表示 IP 地址,或者标准库的 net.IP 类型是否足以满足您的目的。

于 2012-06-09T15:21:45.977 回答