1.10.2
Test / testing (>=1.20, ubuntu-latest) (push) Waiting to run Details
Test / testing (1.19.13, ubuntu-latest) (push) Has been cancelled Details

This commit is contained in:
Akvicor 2024-02-19 16:46:42 +08:00
parent 3749401133
commit 4dec9bfb86
15 changed files with 583 additions and 4 deletions

View File

@ -14,20 +14,25 @@ import "git.viry.cc/gomod/util"
- [x] SHA1 (File, reader, string, bytes)
- [x] SHA256 (File, reader, string, bytes)
- [x] SHA512 (File, reader, string, bytes)
- [x] AES (CBC)
- [x] Base64
- [x] bytes to int (uint16, uint32, uint64)
- [x] int to bytes (uint16, uint32, uint64)
- [x] Bytes Combine
- [x] Bit Set
- [x] JSON
- [x] Slice Remove Duplicates
- [x] File Stat
- [x] Dir List
- [x] Mkdir
- [x] Dir Size
- [x] Size Unit, Decimal System and Binary System
- [x] Path Split
- [x] Random String
- [x] IP
- [x] Time Calculate
- [x] Tcp Port Checker
- [x] Port
- [x] Get Client IP & HTTP GET/POST/PUT Request & HTTP Response & Redirect
# CRC32 & MD5 & SHA1 & SHA256 & SHA512
@ -72,6 +77,24 @@ fmt.Println(cp.Result().Value())
- `.WriteString()` 写入`string`
- `.Result()` 获取计算结果
# AES
- 计算结果为`*AESResult`类型,可通过以下方法获取不同类型结果
- `.Bytes() []byte`
- `.Base64() *Base64Result`
- `.String() string`
- `.Upper() string`
- `.Lower() string`
- `.Encrypted() bool`
- `.Decrypt(key []byte, iv ...[]byte) *AESResult`
- `.Encrypt(key []byte, iv ...[]byte) *AESResult`
- `.Error() error` 获取计算过程中产生的错误
## NewAESResult()
- `.EncryptCBC(origData, key []byte, iv ...[]byte) *AESResult`
- `.DecryptCBC(encrypted, key []byte, iv ...[]byte) *AESResult`
# Base64
- 计算结果为`*Base64Result`类型,可通过以下方法获取不同类型结果
@ -137,6 +160,26 @@ fmt.Println(NewJSONResult([]byte(`{"name":"Akvicor","age":17}`)).Map())
- `.MapArray() []map[string]any` 返回json数组如果变量中保存的是json对象自动创建一个数组并将变量作为数组第一个元素
- `.Error() error` 获取计算过程中产生的错误
# Slice Remove Duplicates
Slice去除重复元素
- `NewRemoveDuplicates() *RemoveDuplicates`
- `.String(s []string) []string`
- `.Byte(s []byte) []byte`
- `.Int8(s []int8) []int8`
- `.Int16(s []int16) []int16`
- `.Int(s []int) []int`
- `.Int32(s []int32) []int32`
- `.Int64(s []int64) []int64`
- `.UInt8(s []uint8) []uint8`
- `.UInt16(s []uint16) []uint16`
- `.UInt(s []uint) []uint`
- `.UInt32(s []uint32) []uint32`
- `.UInt64(s []uint64) []uint64`
- `.Float32(s []float32) []float32`
- `.Float64(s []float64) []float64`
# File Stat
判断文件类型(不存在,是文件夹,是文件
@ -181,6 +224,22 @@ type DirListUnitModel struct {
}
```
# Mkdir
创建文件夹
```go
MkdirP(p string, perm ...os.FileMode) error
```
# Mkdir
获取文件夹大小
```go
DirSize(p string) (int64, error)
```
# Size Unit, Decimal System and Binary System
将大小单位`B`转换为`K,M,G,T,P,E`,并支持返回格式化后的字符串
@ -234,6 +293,7 @@ Size(1*SizeB + 2*SizeKB).Format(",", true)
- `Uint32ToIPAddr` uint32转为ip地址
- `IPToUint32` ip转为uint32
- `Uint32ToIP` uint32转为ip
- `GetLocalIp` 获取本地IP
# Time Calculate
@ -259,6 +319,12 @@ Size(1*SizeB + 2*SizeKB).Format(",", true)
- `TcpPortIsOpen(ip, port string)`
- `TcpPortIsOpenByAddr(ipPort string)`
# Port
获取可用端口
- `GetAvailablePort() (int, error)`
# Get Client IP & HTTP GET/POST/PUT Request & HTTP Response & Redirect
## 获取IP

150
aes.go Normal file
View File

@ -0,0 +1,150 @@
package util
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"strings"
)
type AESResult struct {
data []byte
encrypted bool
err error
}
func (a *AESResult) Bytes() []byte {
if a.err != nil {
return []byte{}
}
return a.data
}
func (a *AESResult) Base64() *Base64Result {
if a.err != nil {
return NewBase64().EncodeBytes([]byte{})
}
return NewBase64().EncodeBytes(a.data)
}
func (a *AESResult) String() string {
if a.err != nil {
return ""
}
return string(a.data)
}
func (a *AESResult) Upper() string {
if a.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(a.data))
}
func (a *AESResult) Lower() string {
if a.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(a.data))
}
func (a *AESResult) Decrypt(key []byte, iv ...[]byte) *AESResult {
if a.err != nil {
return a
}
if a.encrypted {
return NewAES().DecryptCBC(a.data, key, iv...)
} else {
return a
}
}
func (a *AESResult) Encrypt(key []byte, iv ...[]byte) *AESResult {
if a.err != nil {
return a
}
if a.encrypted {
return a
} else {
return NewAES().DecryptCBC(a.data, key, iv...)
}
}
func (a *AESResult) Encrypted() bool {
return a.encrypted
}
func (a *AESResult) Error() error {
return a.err
}
func NewAESResult(data []byte, encrypted bool, err error) *AESResult {
res := &AESResult{
data: make([]byte, len(data)),
encrypted: encrypted,
err: err,
}
copy(res.data, data)
return res
}
type AES struct{}
func NewAES() *AES {
return &AES{}
}
func (*AES) EncryptCBC(origData, key []byte, iv ...[]byte) *AESResult {
block, err := aes.NewCipher(key)
if err != nil {
return NewAESResult(nil, false, err)
}
blockSize := block.BlockSize()
var ivi []byte
ivb := BytesCombine(iv...)
if len(ivb) >= blockSize {
ivi = ivb[:blockSize]
} else {
ivi = key[:blockSize]
}
origData = pkcs5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, ivi)
encrypted := make([]byte, len(origData))
blockMode.CryptBlocks(encrypted, origData)
return NewAESResult(encrypted, true, nil)
}
func (*AES) DecryptCBC(encrypted, key []byte, iv ...[]byte) *AESResult {
block, err := aes.NewCipher(key)
if err != nil {
return NewAESResult(nil, false, err)
}
blockSize := block.BlockSize()
var ivi []byte
ivb := BytesCombine(iv...)
if len(ivb) >= blockSize {
ivi = ivb[:blockSize]
} else {
ivi = key[:blockSize]
}
blockMode := cipher.NewCBCDecrypter(block, ivi)
origData := make([]byte, len(encrypted))
blockMode.CryptBlocks(origData, encrypted)
origData = pkcs5UnPadding(origData)
return NewAESResult(origData, false, nil)
}
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padText...)
}
func pkcs5UnPadding(origData []byte) []byte {
length := len(origData)
unPadding := int(origData[length-1])
return origData[:(length - unPadding)]
}

35
aes_test.go Normal file
View File

@ -0,0 +1,35 @@
package util
import (
"testing"
)
func TestAES(t *testing.T) {
testString := "Akvicor"
testKey := "6dac2a12159afc4ee5100f6a950052a2"
testIv := "xb27xzkb49s01byh"
testEncrypted := "nPH37q+v2zGpXmdYKAE/JA=="
enc := NewAES().EncryptCBC([]byte(testString), []byte(testKey), []byte(testIv))
if !enc.Encrypted() {
t.Errorf("expected true got false")
}
if enc.Base64().String() != testEncrypted {
t.Errorf("expected %s got %s", testEncrypted, enc.Base64().String())
}
dec := enc.Decrypt([]byte(testKey), []byte(testIv))
if dec.Encrypted() {
t.Errorf("expected false got true")
}
if dec.String() != testString {
t.Errorf("expected %s got %s", testString, dec.String())
}
dec = NewAES().DecryptCBC(enc.Bytes(), []byte(testKey), []byte(testIv))
if dec.Encrypted() {
t.Errorf("expected false got true")
}
if dec.String() != testString {
t.Errorf("expected %s got %s", testString, dec.String())
}
}

View File

@ -10,10 +10,16 @@ type Base64Result struct {
}
func (b *Base64Result) Bytes() []byte {
if b.err != nil {
return []byte{}
}
return []byte(b.result)
}
func (b *Base64Result) String() string {
if b.err != nil {
return ""
}
return b.result
}

View File

@ -15,22 +15,37 @@ type CRC32Result struct {
}
func (c *CRC32Result) Value() uint32 {
if c.err != nil {
return 0
}
return c.value
}
func (c *CRC32Result) Array() [4]byte {
if c.err != nil {
return [4]byte{}
}
return UInt32ToBytesArray(c.value)
}
func (c *CRC32Result) Slice() []byte {
if c.err != nil {
return []byte{}
}
return UInt32ToBytesSlice(c.value)
}
func (c *CRC32Result) Upper() string {
if c.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(c.Slice()))
}
func (c *CRC32Result) Lower() string {
if c.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(c.Slice()))
}

28
file.go
View File

@ -4,6 +4,7 @@ import (
"errors"
"io/fs"
"os"
"path"
"path/filepath"
"time"
)
@ -124,3 +125,30 @@ func DirList(p string) *DirListModel {
}
return ls
}
func MkdirP(p string, perm ...os.FileMode) error {
p = path.Clean(p)
if FileStat(p).NotExist() {
if len(perm) > 0 {
return os.MkdirAll(p, perm[0])
} else {
return os.MkdirAll(p, 0755)
}
}
return nil
}
func DirSize(p string) (int64, error) {
var size int64
p = path.Clean(p)
err := filepath.Walk(p, func(_ string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
size += info.Size()
}
return err
})
return size, err
}

0
go.sum Normal file
View File

19
ip.go
View File

@ -81,3 +81,22 @@ func Uint32ToIP(i uint32) net.IP {
return ip
}
func GetLocalIp() (string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return "", err
}
for _, address := range addrs {
// 检查ip地址判断是否回环地址
if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
return ipNet.IP.String(), nil
}
}
}
return "", errors.New("get local ip failed")
}

12
md5.go
View File

@ -19,18 +19,30 @@ type MD5Result struct {
}
func (m *MD5Result) Array() [MD5ResultLength]byte {
if m.err != nil {
return [MD5ResultLength]byte{}
}
return m.result
}
func (m *MD5Result) Slice() []byte {
if m.err != nil {
return []byte{}
}
return m.result[:]
}
func (m *MD5Result) Upper() string {
if m.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(m.result[:]))
}
func (m *MD5Result) Lower() string {
if m.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(m.result[:]))
}

25
port.go
View File

@ -7,19 +7,36 @@ import (
)
func TcpPortIsOpen(ip, port string) bool {
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", ip, port), 3*time.Second)
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", ip, port), 15*time.Second)
if err != nil {
return false
}
defer conn.Close()
defer func() { _ = conn.Close() }()
return true
}
func TcpPortIsOpenByAddr(ipPort string) bool {
conn, err := net.DialTimeout("tcp", ipPort, 3*time.Second)
conn, err := net.DialTimeout("tcp", ipPort, 15*time.Second)
if err != nil {
return false
}
defer conn.Close()
defer func() { _ = conn.Close() }()
return true
}
func GetAvailablePort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer func(l *net.TCPListener) {
_ = l.Close()
}(l)
return l.Addr().(*net.TCPAddr).Port, nil
}

12
sha1.go
View File

@ -19,18 +19,30 @@ type SHA1Result struct {
}
func (s *SHA1Result) Array() [SHA1ResultLength]byte {
if s.err != nil {
return [SHA1ResultLength]byte{}
}
return s.result
}
func (s *SHA1Result) Slice() []byte {
if s.err != nil {
return []byte{}
}
return s.result[:]
}
func (s *SHA1Result) Upper() string {
if s.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(s.result[:]))
}
func (s *SHA1Result) Lower() string {
if s.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(s.result[:]))
}

View File

@ -19,18 +19,30 @@ type SHA256Result struct {
}
func (s *SHA256Result) Array() [SHA256ResultLength]byte {
if s.err != nil {
return [SHA256ResultLength]byte{}
}
return s.result
}
func (s *SHA256Result) Slice() []byte {
if s.err != nil {
return []byte{}
}
return s.result[:]
}
func (s *SHA256Result) Upper() string {
if s.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(s.result[:]))
}
func (s *SHA256Result) Lower() string {
if s.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(s.result[:]))
}

View File

@ -19,18 +19,30 @@ type SHA512Result struct {
}
func (s *SHA512Result) Array() [SHA512ResultLength]byte {
if s.err != nil {
return [SHA512ResultLength]byte{}
}
return s.result
}
func (s *SHA512Result) Slice() []byte {
if s.err != nil {
return []byte{}
}
return s.result[:]
}
func (s *SHA512Result) Upper() string {
if s.err != nil {
return ""
}
return strings.ToUpper(hex.EncodeToString(s.result[:]))
}
func (s *SHA512Result) Lower() string {
if s.err != nil {
return ""
}
return strings.ToLower(hex.EncodeToString(s.result[:]))
}

175
slice.go Normal file
View File

@ -0,0 +1,175 @@
package util
type RemoveDuplicates struct{}
func NewRemoveDuplicates() *RemoveDuplicates {
return &RemoveDuplicates{}
}
func (d *RemoveDuplicates) String(s []string) []string {
result := make([]string, 0, len(s))
temp := map[string]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Byte(s []byte) []byte {
result := make([]byte, 0, len(s))
temp := map[byte]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Int8(s []int8) []int8 {
result := make([]int8, 0, len(s))
temp := map[int8]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Int16(s []int16) []int16 {
result := make([]int16, 0, len(s))
temp := map[int16]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Int(s []int) []int {
result := make([]int, 0, len(s))
temp := map[int]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Int32(s []int32) []int32 {
result := make([]int32, 0, len(s))
temp := map[int32]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Int64(s []int64) []int64 {
result := make([]int64, 0, len(s))
temp := map[int64]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) UInt8(s []uint8) []uint8 {
result := make([]uint8, 0, len(s))
temp := map[uint8]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) UInt16(s []uint16) []uint16 {
result := make([]uint16, 0, len(s))
temp := map[uint16]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) UInt(s []uint) []uint {
result := make([]uint, 0, len(s))
temp := map[uint]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) UInt32(s []uint32) []uint32 {
result := make([]uint32, 0, len(s))
temp := map[uint32]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) UInt64(s []uint64) []uint64 {
result := make([]uint64, 0, len(s))
temp := map[uint64]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Float32(s []float32) []float32 {
result := make([]float32, 0, len(s))
temp := map[float32]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func (d *RemoveDuplicates) Float64(s []float64) []float64 {
result := make([]float64, 0, len(s))
temp := map[float64]struct{}{}
for _, item := range s {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}

20
slice_test.go Normal file
View File

@ -0,0 +1,20 @@
package util
import (
"fmt"
)
func ExampleRemoveDuplicates() {
s := []string{
"aaa",
"bbb",
"aaa",
"ccc",
"aaa",
}
ss := NewRemoveDuplicates().String(s)
fmt.Println(ss)
// Output:
// [aaa bbb ccc]
}