带缓存版:
package main
import (
"bytes"
"fmt"
"net"
"os"
"strings"
"sync"
"time"
)
var ipCacheMap sync.Map
var ipCacheMapTimeout = 10 * time.Minute
type IpCacheMapValue struct {
Ip string
Ts time.Time
}
func main() {
ipv4, err := GetLocalIP("")
fmt.Printf("ipv4=%v err=%v\n", ipv4, err)
}
func GetLocalIP(ipPrefix string) (ipv4 string, err error) {
var defaultIface string
if ipPrefix == "" {
bs, err := os.ReadFile("/proc/net/route")
if err != nil {
return "", err
}
lines := bytes.Split(bs, []byte{'\n'})
defaultDestination := []byte("00000000")
for _, line := range lines {
line = bytes.Trim(line, "\r\t ")
if len(line) == 0 {
continue
}
parts := bytes.Split(line, []byte{'\t'})
if len(parts) < 3 || bytes.Compare(parts[1], defaultDestination) != 0 {
continue
}
defaultIface = string(parts[0])
break
}
}
ipVal, ok := ipCacheMap.Load(ipPrefix)
if ok {
ipInfo, ok := ipVal.(IpCacheMapValue)
if ok && time.Now().Before(ipInfo.Ts.Add(ipCacheMapTimeout)) {
return ipInfo.Ip, nil
}
}
var (
addrs []net.Addr
ifaces []net.Interface
addr net.Addr
ipNet *net.IPNet
isIpNet bool
)
ifaces, err = net.Interfaces()
if err != nil {
return
}
for _, iface := range ifaces {
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
continue
}
if ipPrefix == "" && iface.Name != defaultIface {
continue
}
addrs, err = iface.Addrs()
if err != nil {
continue
}
for _, addr = range addrs {
if ipNet, isIpNet = addr.(*net.IPNet); isIpNet && !ipNet.IP.IsLoopback() {
// 跳过IPV6
if ipNet.IP.To4() != nil {
ipv4 = ipNet.IP.String() // 192.168.1.1
if ipPrefix != "" && !strings.HasPrefix(ipv4, ipPrefix) {
continue
}
ipCacheMap.Store(ipPrefix, IpCacheMapValue{Ip: ipv4, Ts: time.Now()})
return
}
}
}
}
err = fmt.Errorf("get local ip fail")
return
}
--end--
9582

被折叠的 条评论
为什么被折叠?



