add more functions for package gipv4; move package guuid to standalone package of gogf

This commit is contained in:
john
2020-05-16 15:35:21 +08:00
parent 8050efb835
commit 991dbe50e0
9 changed files with 282 additions and 343 deletions

View File

@ -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())
}

View File

@ -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 <ip> 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 <ip> 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 <address> 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])
}

128
net/gipv4/gipv4_ip.go Normal file
View File

@ -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
}

52
net/gipv4/gipv4_lookup.go Normal file
View File

@ -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
}

40
net/gipv4/gipv4_mac.go Normal file
View File

@ -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
}

View File

@ -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 <max> can only be geater than 0, or else it return <max> directly;
// Note that:
// 1. The <max> can only be greater than 0, or else it returns <max> directly;
// 2. The result is greater than or equal to 0, but less than <max>;
// 3. The result number is 32bit and less than math.MaxUint32.
func Intn(max int) int {

View File

@ -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 × 1011),
// 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)
}

View File

@ -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(""))
}
}

View File

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