// Package ip provides IP address helpers. package ip import ( "net" "strconv" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/net/gipv4" ) // IsValid reports whether s is a valid IPv4 address. func IsValid(s string) bool { return gipv4.Validate(s) } // LocalIP returns the first non-loopback IPv4 address of this host. func LocalIP() (string, error) { addrs, err := net.InterfaceAddrs() if err != nil { return "", gerror.Wrap(err, `net.InterfaceAddrs failed`) } for _, addr := range addrs { if ipNet, ok := addr.(*net.IPNet); ok { if ipv4 := ipNet.IP.To4(); ipv4 != nil && !ipv4.IsLoopback() { return ipv4.String(), nil } } } return "", nil } // IsInternal reports whether s is a private/internal IPv4 address // (private ranges, loopback or link-local). func IsInternal(s string) bool { parsed := net.ParseIP(s) if parsed == nil || parsed.To4() == nil { return false } return parsed.IsPrivate() || parsed.IsLoopback() || parsed.IsLinkLocalUnicast() } // ToLong converts an IPv4 string to its uint32 representation // (big-endian, same as inet_aton). func ToLong(s string) (uint32, error) { ipv4 := net.ParseIP(s).To4() if ipv4 == nil { return 0, gerror.Newf(`invalid IPv4 address: %s`, s) } return uint32(ipv4[0])<<24 | uint32(ipv4[1])<<16 | uint32(ipv4[2])<<8 | uint32(ipv4[3]), nil } // ToString converts a uint32 IPv4 value to its dotted-decimal string. func ToString(v uint32) string { return strconv.Itoa(int(v>>24)) + "." + strconv.Itoa(int(v>>16&0xFF)) + "." + strconv.Itoa(int(v>>8&0xFF)) + "." + strconv.Itoa(int(v&0xFF)) }