service.xpcool.com/common/tools/ip/ip.go
夏犀麟 8d5f2c65ae feat(common): 新增公共模块 common/tools 及项目上下文记忆体系
- common/tools 工具模块,10 个子功能:md5/cryptox/uuid/random/timex/convertx/strx/slicex/ip/filex(薄封装 GoFrame 内置组件)
- AGENTS.md 项目智能体说明书(架构、规范、命令、记忆体系索引)
- docs/change-log/2026-08-24.md 本次请求与变更记录
- .gitignore 排除 .workbuddy/;PROJECT_STRUCTURE.md 补充目录树
2026-08-24 17:18:10 +08:00

60 lines
1.6 KiB
Go

// 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))
}