From 991dbe50e02a72a7904b07f723239691f076e68b Mon Sep 17 00:00:00 2001 From: john Date: Sat, 16 May 2020 15:35:21 +0800 Subject: [PATCH] add more functions for package gipv4; move package guuid to standalone package of gogf --- .example/other/test2.go | 44 ++++++++- net/gipv4/gipv4.go | 160 +++---------------------------- net/gipv4/gipv4_ip.go | 128 +++++++++++++++++++++++++ net/gipv4/gipv4_lookup.go | 52 ++++++++++ net/gipv4/gipv4_mac.go | 40 ++++++++ util/grand/grand_intn.go | 18 ++-- util/guuid/guuid.go | 92 ------------------ util/guuid/guuid_z_bench_test.go | 56 ----------- util/guuid/guuid_z_unit_test.go | 35 ------- 9 files changed, 282 insertions(+), 343 deletions(-) create mode 100644 net/gipv4/gipv4_ip.go create mode 100644 net/gipv4/gipv4_lookup.go create mode 100644 net/gipv4/gipv4_mac.go delete mode 100644 util/guuid/guuid.go delete mode 100644 util/guuid/guuid_z_bench_test.go delete mode 100755 util/guuid/guuid_z_unit_test.go diff --git a/.example/other/test2.go b/.example/other/test2.go index ceeedbf4c..616e55134 100644 --- a/.example/other/test2.go +++ b/.example/other/test2.go @@ -2,11 +2,47 @@ package main import ( "fmt" - "github.com/gogf/gf/os/gtime" + "net" ) -func main() { - for i := 0; i < 100; i++ { - fmt.Println(gtime.TimestampNanoStr()) +func getMacAddrs() (macAddrs []string) { + netInterfaces, err := net.Interfaces() + if err != nil { + fmt.Printf("fail to get net interfaces: %v", err) + return macAddrs } + + for _, netInterface := range netInterfaces { + macAddr := netInterface.HardwareAddr.String() + if len(macAddr) == 0 { + continue + } + + macAddrs = append(macAddrs, macAddr) + } + return macAddrs +} + +func getIPs() (ips []string) { + + interfaceAddr, err := net.InterfaceAddrs() + if err != nil { + fmt.Printf("fail to get net interface addrs: %v", err) + return ips + } + + for _, address := range interfaceAddr { + ipNet, isValidIpNet := address.(*net.IPNet) + if isValidIpNet && !ipNet.IP.IsLoopback() { + if ipNet.IP.To4() != nil { + ips = append(ips, ipNet.IP.String()) + } + } + } + return ips +} + +func main() { + fmt.Printf("mac addrs: %q\n", getMacAddrs()) + fmt.Printf("ips: %q\n", getIPs()) } diff --git a/net/gipv4/gipv4.go b/net/gipv4/gipv4.go index b9e06ca7e..222be658f 100644 --- a/net/gipv4/gipv4.go +++ b/net/gipv4/gipv4.go @@ -10,58 +10,12 @@ package gipv4 import ( "encoding/binary" - "errors" "fmt" + "github.com/gogf/gf/text/gregex" "net" "strconv" - "strings" - - "github.com/gogf/gf/text/gregex" ) -// Validate checks whether given a valid IPv4 address. -func Validate(ip string) bool { - return gregex.IsMatchString(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`, ip) -} - -// GetHostByName returns the IPv4 address corresponding to a given Internet host name. -func GetHostByName(hostname string) (string, error) { - ips, err := net.LookupIP(hostname) - if ips != nil { - for _, v := range ips { - if v.To4() != nil { - return v.String(), nil - } - } - return "", nil - } - return "", err -} - -// GetHostsByName returns a list of IPv4 addresses corresponding to a given Internet host name. -func GetHostsByName(hostname string) ([]string, error) { - ips, err := net.LookupIP(hostname) - if ips != nil { - var ipStrings []string - for _, v := range ips { - if v.To4() != nil { - ipStrings = append(ipStrings, v.String()) - } - } - return ipStrings, nil - } - return nil, err -} - -// GetNameByAddr returns the Internet host name corresponding to a given IP address. -func GetNameByAddr(ipAddress string) (string, error) { - names, err := net.LookupAddr(ipAddress) - if names != nil { - return strings.TrimRight(names[0], "."), nil - } - return "", err -} - // Ip2long converts ip address to an uint32 integer. func Ip2long(ip string) uint32 { netIp := net.ParseIP(ip) @@ -78,14 +32,9 @@ func Long2ip(long uint32) string { return net.IP(ipByte).String() } -// GetSegment returns the segment of given ip address. -// Eg: 192.168.2.102 -> 192.168.2 -func GetSegment(ip string) string { - match, err := gregex.MatchString(`^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$`, ip) - if err != nil || len(match) < 4 { - return "" - } - return fmt.Sprintf("%s.%s.%s", match[1], match[2], match[3]) +// Validate checks whether given a valid IPv4 address. +func Validate(ip string) bool { + return gregex.IsMatchString(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`, ip) } // ParseAddress parses
to its ip and port. @@ -99,99 +48,12 @@ func ParseAddress(address string) (string, int) { return "", 0 } -// IntranetIP returns the first intranet ip of current machine. -func IntranetIP() (ip string, err error) { - ips, err := IntranetIPArray() - if err != nil { - return "", err +// GetSegment returns the segment of given ip address. +// Eg: 192.168.2.102 -> 192.168.2 +func GetSegment(ip string) string { + match, err := gregex.MatchString(`^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$`, ip) + if err != nil || len(match) < 4 { + return "" } - if len(ips) == 0 { - return "", errors.New("no intranet ip found") - } - return ips[0], nil -} - -// IntranetIPArray returns the intranet ip list of current machine. -func IntranetIPArray() (ips []string, err error) { - ips = make([]string, 0) - ifaces, e := net.Interfaces() - if e != nil { - return ips, e - } - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - // interface down - continue - } - if iface.Flags&net.FlagLoopback != 0 { - // loopback interface - continue - } - // ignore warden bridge - if strings.HasPrefix(iface.Name, "w-") { - continue - } - addresses, e := iface.Addrs() - if e != nil { - return ips, e - } - for _, addr := range addresses { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - } - - if ip == nil || ip.IsLoopback() { - continue - } - ip = ip.To4() - if ip == nil { - // not an ipv4 address - continue - } - ipStr := ip.String() - if IsIntranet(ipStr) { - ips = append(ips, ipStr) - } - } - } - return ips, nil -} - -// IsIntranet checks and returns whether given ip an intranet ip. -// -// Local: 127.0.0.1 -// A: 10.0.0.0--10.255.255.255 -// B: 172.16.0.0--172.31.255.255 -// C: 192.168.0.0--192.168.255.255 -func IsIntranet(ip string) bool { - if ip == "127.0.0.1" { - return true - } - array := strings.Split(ip, ".") - if len(array) != 4 { - return false - } - // A - if array[0] == "10" || (array[0] == "192" && array[1] == "168") { - return true - } - // C - if array[0] == "192" && array[1] == "168" { - return true - } - // B - if array[0] == "172" { - second, err := strconv.ParseInt(array[1], 10, 64) - if err != nil { - return false - } - if second >= 16 && second <= 31 { - return true - } - } - return false + return fmt.Sprintf("%s.%s.%s", match[1], match[2], match[3]) } diff --git a/net/gipv4/gipv4_ip.go b/net/gipv4/gipv4_ip.go new file mode 100644 index 000000000..11972d4ab --- /dev/null +++ b/net/gipv4/gipv4_ip.go @@ -0,0 +1,128 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +// + +package gipv4 + +import ( + "errors" + "net" + "strconv" + "strings" +) + +// IPArray retrieves and returns all the ip of current host. +func IPArray() (ips []string, err error) { + interfaceAddr, err := net.InterfaceAddrs() + if err != nil { + return nil, err + } + for _, address := range interfaceAddr { + ipNet, isValidIpNet := address.(*net.IPNet) + if isValidIpNet && !ipNet.IP.IsLoopback() { + if ipNet.IP.To4() != nil { + ips = append(ips, ipNet.IP.String()) + } + } + } + return ips, nil +} + +// IntranetIP retrieves and returns the first intranet ip of current machine. +func IntranetIP() (ip string, err error) { + ips, err := IntranetIPArray() + if err != nil { + return "", err + } + if len(ips) == 0 { + return "", errors.New("no intranet ip found") + } + return ips[0], nil +} + +// IntranetIPArray retrieves and returns the intranet ip list of current machine. +func IntranetIPArray() (ips []string, err error) { + interFaces, e := net.Interfaces() + if e != nil { + return ips, e + } + for _, interFace := range interFaces { + if interFace.Flags&net.FlagUp == 0 { + // interface down + continue + } + if interFace.Flags&net.FlagLoopback != 0 { + // loopback interface + continue + } + // ignore warden bridge + if strings.HasPrefix(interFace.Name, "w-") { + continue + } + addresses, e := interFace.Addrs() + if e != nil { + return ips, e + } + for _, addr := range addresses { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + + if ip == nil || ip.IsLoopback() { + continue + } + ip = ip.To4() + if ip == nil { + // not an ipv4 address + continue + } + ipStr := ip.String() + if IsIntranet(ipStr) { + ips = append(ips, ipStr) + } + } + } + return ips, nil +} + +// IsIntranet checks and returns whether given ip an intranet ip. +// +// Local: 127.0.0.1 +// A: 10.0.0.0--10.255.255.255 +// B: 172.16.0.0--172.31.255.255 +// C: 192.168.0.0--192.168.255.255 +func IsIntranet(ip string) bool { + if ip == "127.0.0.1" { + return true + } + array := strings.Split(ip, ".") + if len(array) != 4 { + return false + } + // A + if array[0] == "10" || (array[0] == "192" && array[1] == "168") { + return true + } + // C + if array[0] == "192" && array[1] == "168" { + return true + } + // B + if array[0] == "172" { + second, err := strconv.ParseInt(array[1], 10, 64) + if err != nil { + return false + } + if second >= 16 && second <= 31 { + return true + } + } + return false +} diff --git a/net/gipv4/gipv4_lookup.go b/net/gipv4/gipv4_lookup.go new file mode 100644 index 000000000..423a611f1 --- /dev/null +++ b/net/gipv4/gipv4_lookup.go @@ -0,0 +1,52 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +// + +package gipv4 + +import ( + "net" + "strings" +) + +// GetHostByName returns the IPv4 address corresponding to a given Internet host name. +func GetHostByName(hostname string) (string, error) { + ips, err := net.LookupIP(hostname) + if ips != nil { + for _, v := range ips { + if v.To4() != nil { + return v.String(), nil + } + } + return "", nil + } + return "", err +} + +// GetHostsByName returns a list of IPv4 addresses corresponding to a given Internet +// host name. +func GetHostsByName(hostname string) ([]string, error) { + ips, err := net.LookupIP(hostname) + if ips != nil { + var ipStrings []string + for _, v := range ips { + if v.To4() != nil { + ipStrings = append(ipStrings, v.String()) + } + } + return ipStrings, nil + } + return nil, err +} + +// GetNameByAddr returns the Internet host name corresponding to a given IP address. +func GetNameByAddr(ipAddress string) (string, error) { + names, err := net.LookupAddr(ipAddress) + if names != nil { + return strings.TrimRight(names[0], "."), nil + } + return "", err +} diff --git a/net/gipv4/gipv4_mac.go b/net/gipv4/gipv4_mac.go new file mode 100644 index 000000000..6cb231fcd --- /dev/null +++ b/net/gipv4/gipv4_mac.go @@ -0,0 +1,40 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +// + +package gipv4 + +import ( + "net" +) + +// Mac retrieves and returns the first mac address of current host. +func Mac() (mac string, err error) { + macs, err := MacArray() + if err != nil { + return "", err + } + if len(macs) > 0 { + return macs[0], nil + } + return "", nil +} + +// MacArray retrieves and returns all the mac address of current host. +func MacArray() (macs []string, err error) { + netInterfaces, err := net.Interfaces() + if err != nil { + return nil, err + } + for _, netInterface := range netInterfaces { + macAddr := netInterface.HardwareAddr.String() + if len(macAddr) == 0 { + continue + } + macs = append(macs, macAddr) + } + return macs, nil +} diff --git a/util/grand/grand_intn.go b/util/grand/grand_intn.go index 0b64e5637..12bad78eb 100644 --- a/util/grand/grand_intn.go +++ b/util/grand/grand_intn.go @@ -22,11 +22,13 @@ var ( ) // It uses a asynchronous goroutine to produce the random number, -// and a buffer chan to store the random number. So it has high performance -// to generate random number. +// and a buffer chan to store the random numbers. +// So it has high performance to generate random numbers. func init() { - step := 0 - buffer := make([]byte, 1024) + var ( + step = 0 + buffer = make([]byte, 1024) + ) go func() { for { if n, err := rand.Read(buffer); err != nil { @@ -43,6 +45,8 @@ func init() { break } } + // The step cannot be 0, + // as it will produce the same random number as previous. if step == 0 { step = 2 } @@ -55,10 +59,10 @@ func init() { }() } -// Intn returns a int number which is between 0 and max - [0, max). +// Intn returns a int number which is between 0 and max: [0, max). // -// Note: -// 1. The can only be geater than 0, or else it return directly; +// Note that: +// 1. The can only be greater than 0, or else it returns directly; // 2. The result is greater than or equal to 0, but less than ; // 3. The result number is 32bit and less than math.MaxUint32. func Intn(max int) int { diff --git a/util/guuid/guuid.go b/util/guuid/guuid.go deleted file mode 100644 index e0fc1d016..000000000 --- a/util/guuid/guuid.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -// Package guuid generates and inspects UUIDs. -// -// This package is a wrapper for most common used UUID package: -// https://github.com/google/uuid -package guuid - -import ( - "github.com/google/uuid" - "os" -) - -// UUID representation compliant with specification -// described in RFC 4122. -type UUID = uuid.UUID - -// UUID DCE domains. -const ( - DomainPerson = uuid.Domain(0) - DomainGroup = uuid.Domain(1) - DomainOrg = uuid.Domain(2) -) - -// New creates a new random UUID or panics. -func New() UUID { - return uuid.New() -} - -// NewUUID returns a Version 1 UUID based on the current NodeID and clock -// sequence, and the current time. If the NodeID has not been set by SetNodeID -// or SetNodeInterface then it will be set automatically. If the NodeID cannot -// be set NewUUID returns nil. If clock sequence has not been set by -// SetClockSequence then it will be set automatically. If GetTime fails to -// return the current NewUUID returns nil and an error. -// -// In most cases, New should be used. -func NewUUID() (UUID, error) { - return uuid.NewUUID() -} - -// NewDCEGroup returns a DCE Security (Version 2) UUID in the group -// domain with the id returned by os.Getgid. -// -// NewDCESecurity(Group, uint32(os.Getgid())) -func NewDCEGroup() (UUID, error) { - return uuid.NewDCESecurity(DomainGroup, uint32(os.Getgid())) -} - -// NewDCEPerson returns a DCE Security (Version 2) UUID in the person -// domain with the id returned by os.Getuid. -// -// NewDCESecurity(Person, uint32(os.Getuid())) -func NewDCEPerson() (UUID, error) { - return uuid.NewDCESecurity(DomainPerson, uint32(os.Getuid())) -} - -// NewMD5 returns a new MD5 (Version 3) UUID based on the -// supplied name space and data. It is the same as calling: -// -// NewHash(md5.New(), space, data, 3) -func NewMD5(space UUID, data []byte) UUID { - return uuid.NewMD5(space, data) -} - -// NewRandom returns a Random (Version 4) UUID. -// -// The strength of the UUIDs is based on the strength of the crypto/rand -// package. -// -// A note about uniqueness derived from the UUID Wikipedia entry: -// -// Randomly generated UUIDs have 122 random bits. One's annual risk of being -// hit by a meteorite is estimated to be one chance in 17 billion, that -// means the probability is about 0.00000000006 (6 × 10−11), -// equivalent to the odds of creating a few tens of trillions of UUIDs in a -// year and having one duplicate. -func NewRandom() (UUID, error) { - return uuid.NewRandom() -} - -// NewSHA1 returns a new SHA1 (Version 5) UUID based on the -// supplied name space and data. It is the same as calling: -// -// NewHash(sha1.New(), space, data, 5) -func NewSHA1(space UUID, data []byte) UUID { - return uuid.NewSHA1(space, data) -} diff --git a/util/guuid/guuid_z_bench_test.go b/util/guuid/guuid_z_bench_test.go deleted file mode 100644 index f75b591bd..000000000 --- a/util/guuid/guuid_z_bench_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -// go test *.go -bench=".*" -benchmem - -package guuid_test - -import ( - "github.com/gogf/gf/util/guuid" - "testing" -) - -func Benchmark_New(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.New() - } -} - -func Benchmark_NewUUID(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.NewUUID() - } -} - -func Benchmark_NewDCEGroup(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.NewDCEGroup() - } -} - -func Benchmark_NewDCEPerson(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.NewDCEPerson() - } -} - -func Benchmark_NewRandom(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.NewRandom() - } -} - -func Benchmark_NewMD5(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.NewMD5(guuid.UUID{}, []byte("")) - } -} - -func Benchmark_NewSHA1(b *testing.B) { - for i := 0; i < b.N; i++ { - guuid.NewSHA1(guuid.UUID{}, []byte("")) - } -} diff --git a/util/guuid/guuid_z_unit_test.go b/util/guuid/guuid_z_unit_test.go deleted file mode 100755 index 5e6c36c0d..000000000 --- a/util/guuid/guuid_z_unit_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package guuid_test - -import ( - "github.com/gogf/gf/util/guuid" - "testing" - - "github.com/gogf/gf/test/gtest" -) - -func Test_Basic(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - t.Assert(len(guuid.New().String()), 36) - - uuid, _ := guuid.NewUUID() - t.Assert(len(uuid.String()), 36) - - uuid, _ = guuid.NewDCEGroup() - t.Assert(len(uuid.String()), 36) - - uuid, _ = guuid.NewDCEPerson() - t.Assert(len(uuid.String()), 36) - - uuid, _ = guuid.NewRandom() - t.Assert(len(uuid.String()), 36) - - t.Assert(len(guuid.NewMD5(guuid.UUID{}, []byte("")).String()), 36) - t.Assert(len(guuid.NewSHA1(guuid.UUID{}, []byte("")).String()), 36) - }) -}