在Go中从字符串中解析多个整数?

huangapple go评论68阅读模式
英文:

Parse multiple integers from a string in Go?

问题

抱歉,我不知道如何表达标题。

我对这段代码有一个问题。

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。

如何简化这个过程?

英文:

sorry for the title , i don't know how to say that

i have a questions about this code

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 
}

I want to convert an ip address to integer number

you see I have wrote such ugly code

first retrive number from strconv.Atoi then convert it to int64

How to simplify this ?

答案1

得分: 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])
}
英文:

If you want to parse multiple integers from a string, try the Sscanf function, like this:

func main() {
	var ip [4] uint32
	addr := &quot;192.168.0.1&quot;
	_, err := fmt.Sscanf(addr, &quot;%d.%d.%d.%d&quot;, &amp;ip[0], &amp;ip[1], &amp;ip[2], &amp;ip[3])
    if err != nil {
        fmt.Println(err)
        return
    }
	fmt.Println(ip)
	fmt.Println(ip[0]&lt;&lt;24 + ip[1]&lt;&lt;16 + ip[2]&lt;&lt;8 + ip[3])
}

答案2

得分: 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)。

英文:

This construct is heavy but appears more natural if you, as you probably should, were catching the parsing errors.

This being said, the correct solution to that exact problem is to use the existing net.ParseIP function which builds an IP

func ParseIP(s string) IP

If you must keep your current function prototype, I suggest this :

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

Note that you may add a test on the return of ParseIP (which is nil in case of error)

答案3

得分: 1

我不建议这样做,因为这样会忽略错误,但你可以编写一个函数来获取第一个值:

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

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

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

// 警告:未经测试的代码!!

type InvalidIP string
func (InvalidIP ipStr) Error() string {
    return "无效的IPv4地址:" + 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类型是否足够满足你的需求。

英文:

I don't recommend it, because you would be ignoring errors, but you can write a function to give you the first value:

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

Then use first(strconv.Atoi(p[0])) in your code.

For the particular code you listed though, I would use the (well tested!) standard library's net.ParseIP() and net.To4() functions:

// WARNING untested code!!

type InvalidIP string
func (InvalidIP ipStr) Error() string {
    return &quot;Invalid IPv4 address: &quot;+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 &lt;&lt;= 8
        ret += b
    }
    return ret, nil
}

Note that the above code adds error checking, and also accepts IPv6 formatted v4 addresses "::FFFF:C0A8:0101". Consider whether you really need an int64 type to represent IP addresses, or whether the standard library's net.IP type is good enough for your purposes.

huangapple
  • 本文由 发表于 2012年6月9日 22:08:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/10961674.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定