Simpler int->ip unpacking?

855 views
Skip to first unread message

Vlad Didenko

unread,
May 10, 2013, 12:38:54 AM5/10/13
to golan...@googlegroups.com
I need to get get IPv4 addresses packed in an integer out and do not like the way I end up doing it. Seems to be that too much heavy machinery used for a simple thing. What do I miss?

func int2bytes(ip_int uint64) (net.IP, error) {
var bufarray []byte
buf := bytes.NewBuffer(bufarray)
err = binary.Write(buf, binary.LittleEndian, ip_int)
if err != nil {
return nil, errors.New("Failed to convert integer into bytearray.")
}
return buf.Bytes()[:4], nil
}

peterGo

unread,
May 10, 2013, 2:15:37 AM5/10/13
to golan...@googlegroups.com
Vlad,

    ip_addr = make([]byte, 4)
    binary.LittleEndian.PutUint32(ip_addr, 0x0100007f)

Peter

Tharaneedharan Vilwanathan

unread,
May 10, 2013, 3:07:43 AM5/10/13
to Ryan Leavengood, golang-nuts
Hi,

If I am right, this looks simpler and more optimized:

func IntToIP(ip uint64) net.IP {
result := make(net.IP, 4)
        result[0] = byte(ip)
        result[1] = byte(ip >>8)
        result[2] = byte(ip >>16)
        result[3] = byte(ip >> 24)
return result
}

May be there is a better version. Also, please correct me if I am wrong.

Thanks
dharani


On Thu, May 9, 2013 at 10:33 PM, Ryan Leavengood <leave...@gmail.com> wrote:
Replying to myself:

The byte conversion actually makes the masking with & unnecessary. In addition the for can use range. So an even better version is here:


Regards,
Ryan


On Friday, May 10, 2013 1:03:37 AM UTC-4, Ryan Leavengood wrote:
func intToIP(ip_int uint64) net.IP {
result := make(net.IP, 4)
for i := 0; i < 4; i++ {
result[i] = byte((ip_int >> uint(8 * i)) & 0xff)
}
return result
}

On Friday, May 10, 2013 12:38:54 AM UTC-4, Vlad Didenko wrote:

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

dlin

unread,
May 10, 2013, 3:27:15 AM5/10/13
to golan...@googlegroups.com, Ryan Leavengood
I'm wonder do you have the reverse IPToInt()?

Ryan Leavengood

unread,
May 10, 2013, 10:33:10 AM5/10/13
to golan...@googlegroups.com, Ryan Leavengood
Dharani,

Your version looks good, and is indeed quite a bit faster than mine (about 3 times as fast.) I suppose the use of range and the multiply is what is slowing mine so much. Peter's is also very fast (about the same speed as Dharani's) and concise.

In general though they are all so fast in Go that in the grand scheme it probably doesn't matter. A million conversions (leaving out a function call and allocation of the result variable) takes about 6 milliseconds on my machine for both Dharani and Peter's code (and this is with Go 1.0.3.)

I do wonder why this conversion (and the reverse) is not in the standard library.

Regards,
Ryan

Ryan Leavengood

unread,
May 10, 2013, 11:06:21 AM5/10/13
to golan...@googlegroups.com
To put this topic to bed, the standard library binary.LittleEndian.PutUint32 function which Peter used is exactly Dharani's code:


So that is what should be used for this. Also since net.IP is really just a byte slice, you can make a variable of that type and use it directly with PutUint32.

Finally the LittleEndian.Uint32 function in the same package above will do the opposite conversion. And again you can just give it a net.IP.

Regards,
Ryan

Vlad Didenko

unread,
May 10, 2013, 11:37:53 AM5/10/13
to golan...@googlegroups.com
Peter,

Awesome. thank you, that is what I was looking for!

Vlad

Vlad Didenko

unread,
May 10, 2013, 11:41:19 AM5/10/13
to golan...@googlegroups.com
Ryan,

Absolutely binary package is the way to do it. I did not get type casting right when used shifts in a loop initially, so moved to the binary package. PutUint*  is what I was looking for.

Vlad

Rémy Oudompheng

unread,
May 10, 2013, 1:54:42 PM5/10/13
to Vlad Didenko, golan...@googlegroups.com
Why did you need to pack IP addresses as integers in the first place?

Rémy.


2013/5/10, Vlad Didenko <busi...@didenko.com>:
> Here is the code in the playground... <http://play.golang.org/p/F-9SDlK-nN>

Vlad Didenko

unread,
May 10, 2013, 3:58:58 PM5/10/13
to golan...@googlegroups.com
I need to unpack it, because the code I interface with is written by a very clever person and packs it that way.

slene

unread,
May 10, 2013, 10:49:28 AM5/10/13
to Ryan Leavengood, golan...@googlegroups.com
Hi,

Can use this test get almost same speed.

uint32 -> ip string
ip string -> uint32

http://play.golang.org/p/T5B-6RExlj
Message has been deleted
Message has been deleted

李彬

unread,
Mar 12, 2014, 6:27:09 AM3/12/14
to golan...@googlegroups.com

func inet_aton(ip string) (ip_int uint32) {
ip_byte := net.ParseIP(ip).To4()
for i := 0; i < len(ip_byte); i++ {
ip_int |= uint32(ip_byte[i])
if i < 3 {
ip_int <<= 8
}
}
return
}

func inet_ntoa(ip uint32) string {
return fmt.Sprintf("%d.%d.%d.%d", byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip))
}

在 2013年5月10日星期五UTC+8下午12时38分54秒,Vlad Didenko写道:

chris dollin

unread,
Mar 12, 2014, 9:48:16 AM3/12/14
to 李彬, golang-nuts
On 12 March 2014 10:27, 李彬 <hdk...@gmail.com> wrote:

func inet_aton(ip string) (ip_int uint32) {
ip_byte := net.ParseIP(ip).To4()
for i := 0; i < len(ip_byte); i++ {
ip_int |= uint32(ip_byte[i])
if i < 3 {
ip_int <<= 8
}
}
return
}

Wouldn't that be simpler as

func inet_aton(ip string) uint32 {
   ip_byte := net.ParseIP(ip).To4()
   return uint32(ip_byte[0] << 24) | uint32(ip_byte[1] << 16) |
        uint32(ip_byte[2] << 8) | uint32(ip_byte[3]);
}

?

Chris

--
Chris "allusive" Dollin
Reply all
Reply to author
Forward
0 new messages