GoTool is a small and complete Golang tool set. It mainly refines and integrates the commonly used methods in daily development to avoid repeating the wheel and improve work efficiency. Each method is extracted from the author's work experience and previous projects.
If you feel OK, please click STAR
English 简体中文
- Add file IO manipulation tool FileUtils
- Add CaptchaUtils, a captcha generation tool
- Add file directory compression and decompression tool ZipUtis
- String array tool StrArrayUtils
- Add DesensitizedUtils, a sensitive message desensitization tool
- Add the menu tree data formatting tool TreeUtils
- Add JSON output beautification tool PrettyUtils
- Add type conversion tool TypeConversion
go get github.com/druidcaesa/gotool
go.mod github.com/druidcaesa/gotool
import "github.com/druidcaesa/gotool"
Type conversion tool, mainly used for string, int, float type conversion, err is internally processed, and default values can be set to avoid frequent err operations
1、StrToInt String type to int type, there are two parameters, str->the string to be converted, defaultNum default value, when an exception occurs, it can directly return to the default value, no default value returns 0
func TestStrToInt(t *testing.T) {
toInt := gotool.TypeConversion.StrToInt("32e", 56)
fmt.Println("An exception occurs, return to the default value:", toInt)
toInt = gotool.TypeConversion.StrToInt("32e")
fmt.Println("An exception occurred, no default value:", toInt)
}
//out
=== RUN TestStrToInt
An exception occurs, return to the default value: 56
An exception occurred, no default value: 0
--- PASS: TestStrToInt (0.00s)
PASS
func TestIntToStr(t *testing.T) {
var num int64 = 1344
str := gotool.TypeConversion.IntToStr(num)
fmt.Println("int64 to string",str)
str = gotool.TypeConversion.IntToStr("num")
fmt.Println("Enter the string directly, and the string will be returned directly",str)
}
//out
=== RUN TestIntToStr
int64 to string 1344
Enter the string directly, and the string will be returned directly num
--- PASS: TestIntToStr (0.00s)
PASS
3、StrToFloat64 The string is converted to float64 type, the default value can be passed, if an exception occurs, the default value will be returned, and no default value will be returned to 0
func TestStrToFloat64(t *testing.T) {
toFloat32 := gotool.TypeConversion.StrToFloat32("12.78")
fmt.Println(toFloat32)
toFloat32 = gotool.TypeConversion.StrToFloat32("12.78e")
fmt.Println(toFloat32)
}
//out
=== RUN TestStrToFloat64
12.78
0
--- PASS: TestStrToFloat64 (0.00s)
PASS
Golang is a string commonly used tool set, which basically covers the tools that are often used in development, and is currently in the process of misconduct.
func TestStringReplacePlaceholder(t *testing.T) {
s := "Hello {},My is {}"
placeholder, err := gotool.StrUtils.ReplacePlaceholder(s, "work", "gotool")
if err == nil {
fmt.Println(placeholder)
}
}
//out
== = RUN TestStringReplacePlaceholder
Hello work, My is gotool
--- PASS: TestStringReplacePlaceholder (0.00s)
PASS
func TestRemoveSuffix(t *testing.T) {
fullFilename := "test.txt"
suffix, _ := gotool.StrUtils.RemoveSuffix(fullFilename)
fmt.Println(suffix)
fullFilename = "/root/home/test.txt"
suffix, _ = gotool.StrUtils.RemoveSuffix(fullFilename)
fmt.Println(suffix)
}
//out
== = RUN TestRemoveSuffix
test
test
--- PASS: TestRemoveSuffix (0.00s)
PASS
func TestGetSuffix(t *testing.T) {
fullFilename := "test.txt"
suffix, _ := gotool.StrUtils.GetSuffix(fullFilename)
fmt.Println(suffix)
fullFilename = "/root/home/test.txt"
suffix, _ = gotool.StrUtils.GetSuffix(fullFilename)
fmt.Println(suffix)
}
//out
== = RUN TestGetSuffix
.txt
.txt
--- PASS: TestGetSuffix (0.00s)
PASS
func TestHasStr(t *testing.T) {
str := ""
empty := gotool.StrUtils.HasEmpty(str)
fmt.Println(empty)
str = "11111"
empty = gotool.StrUtils.HasEmpty(str)
fmt.Println(empty)
}
//out
== = RUN TestHasStr
true
false
--- PASS: TestHasStr (0.00s)
PASS
1、gotool.StrArrayUtils.StringToInt64 Convert string array to int64 array, please make sure that the string arrays are all numbers before calling
func TestStringToInt64(t *testing.T) {
//String array to int64
strings := []string{"1", "23123", "232323"}
fmt.Println(reflect.TypeOf(strings[0]))
toInt64, err := gotool.StrArrayUtils.StringToInt64(strings)
if err != nil {
t.Fatal(err)
}
fmt.Println(reflect.TypeOf(toInt64[0]))
}
//out
== = RUN TestStringToInt64
string
int64
--- PASS: TestStringToInt64 (0.00s)
PASS
2、gotool.StrArrayUtils.StringToInt32 Convert string array to int64 array, please make sure that the string arrays are all numbers before calling
func TestStringToInt32(t *testing.T) {
//String array to int32
strings := []string{"1", "23123", "232323"}
fmt.Println(reflect.TypeOf(strings[0]))
toInt64, err := gotool.StrArrayUtils.StringToInt32(strings)
if err != nil {
t.Fatal(err)
}
fmt.Println(reflect.TypeOf(toInt64[0]))
}
//out
== = RUN TestStringToInt32
string
int32
--- PASS: TestStringToInt32 (0.00s)
PASS
func TestArrayDuplication(t *testing.T) {
//string array deduplication
strings := []string{"hello", "word", "gotool", "word"}
fmt.Println("Before weight removal----------------->", strings)
duplication := gotool.StrArrayUtils.ArrayDuplication(strings)
fmt.Println("After weight removal----------------->", duplication)
}
//out
== = RUN TestArrayDuplication
Before weight removal-----------------> [hello word gotool word]
After weight removal-----------------> [hello word gotool]
--- PASS: TestArrayDuplication (0.00s)
PASS
Golang is a time operation tool set, which basically covers the tools frequently used in development, and is currently being improved.
func TestFormatToString(t *testing.T) {
now := gotool.DateUtil.Now()
toString := gotool.DateUtil.FormatToString(&now, "YYYY-MM-DD hh:mm:ss")
fmt.Println(toString)
toString = gotool.DateUtil.FormatToString(&now, "YYYYMMDD hhmmss")
fmt.Println(toString)
}
//Year, month and day correspond to YYYY MM DD hour, minute and second hhmmss can be combined in any combination, such as YYYY hh YYYY-DD hh:mm, etc.
//out
== = RUN TestFormatToString
2021-07-07 16:13:30
20210707 161330
--- PASS: TestFormatToString (0.00s)
PASS
//Time is empty true otherwise false
func TestDate_IsZero(t *testing.T) {
t2 := time.Time{}
zero := gotool.DateUtil.IsZero(t2)
fmt.Println(zero)
zero = gotool.DateUtil.IsZero(gotool.DateUtil.Now())
fmt.Println(zero)
}
//out
== = RUN TestDate_IsZero
true
false
--- PASS: TestDate_IsZero (0.00s)
PASS
3、gotool.DateUtil.Now Get the current time is equivalent to time.Now(), so this method is also included in the tool for unification
//Parameter one is the time string to be formatted. Parameter two is the string format, which needs to be consistent with the format of the string to be formatted.
//For example, 2021-6-4 corresponds to YYYY-MM-DD 2021.6.4 corresponds to YYYY.MM.DD
func TestInterpretStringToTimestamp(t *testing.T) {
timestamp, err := gotool.DateUtil.InterpretStringToTimestamp("2021-05-04 15:12:59", "YYYY-MM-DD hh:mm:ss")
if err != nil {
gotool.Logs.ErrorLog().Println(err.Error())
}
fmt.Println(timestamp)
}
//out
== = RUN TestInterpretStringToTimestamp
1620112379
--- PASS: TestInterpretStringToTimestamp (0.00s)
PASS
func TestUnixToTime(t *testing.T) {
unix := gotool.DateUtil.Now().Unix()
fmt.Println("Timestamp----------------------->", unix)
toTime := gotool.DateUtil.UnixToTime(unix)
fmt.Println(toTime)
}
//out
== = RUN TestUnixToTime
Timestamp-----------------------> 1625645682
2021-07-07 16:14:42 +0800 CST
--- PASS: TestUnixToTime (0.00s)
PASS
func TestGetWeekDay(t *testing.T) {
now := gotool.DateUtil.Now()
day := gotool.DateUtil.GetWeekDay(now)
fmt.Println("Today is-----------------week", day)
}
//out
== = RUN TestGetWeekDay
Today is-----------------week 3
--- PASS: TestGetWeekDay (0.00s)
PASS
//Time calculation
func TestTimeAddOrSub(t *testing.T) {
now := gotool.DateUtil.Now()
fmt.Println("The time is now--------------------->", now)
sub := gotool.DateUtil.MinuteAddOrSub(now, 10)
fmt.Println("Minute calculation result-------------------->", sub)
sub = gotool.DateUtil.MinuteAddOrSub(now, -10)
fmt.Println("Minute calculation result-------------------->", sub)
sub = gotool.DateUtil.HourAddOrSub(now, 10)
fmt.Println("Hourly calculation result-------------------->", sub)
sub = gotool.DateUtil.HourAddOrSub(now, -10)
fmt.Println("Hourly calculation result-------------------->", sub)
sub = gotool.DateUtil.DayAddOrSub(now, 10)
fmt.Println("Day calculation result-------------------->", sub)
sub = gotool.DateUtil.DayAddOrSub(now, -10)
fmt.Println("Day calculation result-------------------->", sub)
}
//The time is now---------------------> 2021-07-07 11:18:17.8295757 +0800 CST m=+0.012278001
//Minute calculation result--------------------> 2021-07-07 11:28:17.8295757 +0800 CST m=+600.012278001
//Minute calculation result--------------------> 2021-07-07 11:08:17.8295757 +0800 CST m=-599.987721999
//Hourly calculation result--------------------> 2021-07-07 21:18:17.8295757 +0800 CST m=+36000.012278001
//Hourly calculation result--------------------> 2021-07-07 01:18:17.8295757 +0800 CST m=-35999.987721999
//Day calculation result--------------------> 2021-07-17 11:18:17.8295757 +0800 CST m=+864000.012278001
//Day calculation result--------------------> 2021-06-27 11:18:17.8295757 +0800 CST m=-863999.987721999
1、gotool.ConvertUtils.GregorianToLunarCalendar(Gregorian calendar to lunar calendar),GetLunarYearDays(Lunar calendar to Gregorian calendar),GetLunarYearDays(Get the number of days in the lunar calendar year)
func TestConvertTest(t *testing.T) {
calendar := gotool.ConvertUtils.GregorianToLunarCalendar(2020, 2, 1)
fmt.Println(calendar)
gregorian := gotool.ConvertUtils.LunarToGregorian(calendar[0], calendar[1], calendar[2], false)
fmt.Println(gregorian)
days := gotool.ConvertUtils.GetLunarYearDays(2021)
fmt.Println(days)
}
//[2020 1 8]
//[2020 2 1]
//354
2、gotool.ConvertUtils.GetSolarMonthDays(2021,7) Get the number of days in a certain month in the Gregorian calendar, the number of days in July 2021
1、gotool.BcryptUtils.Generate Encryption processing, mostly used for database storage after password encryption, irreversible
2、gotool.BcryptUtils.CompareHash Compared with the unencrypted password after encryption, it is mostly used for login authentication.
func TestGenerate(t *testing.T) {
//Encrypt
generate := gotool.BcryptUtils.Generate("123456789")
fmt.Println(generate)
//Encrypted comparison
hash := gotool.BcryptUtils.CompareHash(generate, "123456789")
fmt.Println(hash)
}
//out
== = RUN TestGenerate
$2a$10$IACJ6zGuNuzaumrvDz58Q.vJUzz4JGqougYKrdCs48rQYIRjAXcU2
true
--- PASS: TestGenerate (0.11s)
PASS
func TestMd5(t *testing.T) {
md5 := gotool.BcryptUtils.MD5("123456789")
fmt.Println(md5)
}
//out
== = RUN TestMd5
25f9e794323b453885f5181f1b624d0b
--- PASS: TestMd5 (0.00s)
PASS
func TestRsa(t *testing.T) {
//rsa Key file generation
fmt.Println("-------------------------------Obtain RSA public and private keys-----------------------------------------")
prvKey, pubKey := gotool.BcryptUtils.GenRsaKey()
fmt.Println(string(prvKey))
fmt.Println(string(pubKey))
fmt.Println("-------------------------------Sign and verify operations-----------------------------------------")
var data = "I am the encrypted data remember me-------------------------------"
fmt.Println("Sign the message...")
signData := gotool.BcryptUtils.RsaSignWithSha256([]byte(data), prvKey)
fmt.Println("Signature information of the message: ", hex.EncodeToString(signData))
fmt.Println("\nVerify the signature information...")
if gotool.BcryptUtils.RsaVerySignWithSha256([]byte(data), signData, pubKey) {
fmt.Println("The signature information is verified successfully, and it is determined that it is the correct private key signature!!")
}
fmt.Println("-------------------------------Perform encryption and decryption operations-----------------------------------------")
ciphertext := gotool.BcryptUtils.RsaEncrypt([]byte(data), pubKey)
fmt.Println("Public key encrypted data:", hex.EncodeToString(ciphertext))
sourceData := gotool.BcryptUtils.RsaDecrypt(ciphertext, prvKey)
fmt.Println("Data decrypted by the private key:", string(sourceData))
}
//out
== = RUN TestRsa
-------------------------------Obtain RSA public and private keys-----------------------------------------
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCgHh1ZYFjlxrIJYjjWGFaLwC8Oov8KqyMtHa+GauF121dperr3
i46JyDoskoSBhbkmqv70LMNrjqVdttdIsC0BtH9ThWLBwKVLH56EqfzqlzClKZEh
WTNaddCSuxoZpN33mwS82DCjZe3d7nAPdEGD5pSBx6TVt5bG1c3NVAmcBQIDAQAB
AoGAWc5KO9T0R3xYYzb6Fer0r9GNEzKMxdkTE7zws/3Cky4BKyIxN6LIwbLSHinX
tCXioTOLaDyrJuqNCbEBsr1NoCIPxnswA5Jm5QDYO5x9aq4u8+SZ9KqLbMrO1JDS
ZV7Cbiblz1xNMfdVIvlVjD5RdEotbYTbHI2CZUoPsjHng8kCQQDHi6TJYJqvej8r
q46ZceuWHDgE81Wu16RrA/kZKi6MJAApQtfO/4HM6W/ImbCjZ2rSYxqnAlIg/GxA
dT6iJABjAkEAzWra06RyhGm3lk9j9Xxc0YPX6VX7qT5Iq6c7ry1JtTSeVOksKANG
elaNnCj8YYUgj7BeBBcMMvLd39hP1h06dwJAINTyHQwfB2ZGxImqocajq4QjF3Vu
EKF8dPsnXiOZmwdFW4Sa+30Av1VdRhU7gfc/FTSnKvlvx+ugaA6iao0f3wJBALa8
sTCH4WwUE8K+m4DeAkBMVn34BKnZg5JYcgrzcdemmJeW2rY5u6/HYbCi8WnboUzS
K8Dds/d7AJBKgTNLyx8CQBAeU0St3Vk6SJ6H71J8YtVxlRGDjS2fE0JfUBrpI/bg
r/QI8yMAMyFkt1YshN+UNWJcvR5SXQnyT/udnWJIdg4 =
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgHh1ZYFjlxrIJYjjWGFaLwC8O
ov8KqyMtHa+GauF121dperr3i46JyDoskoSBhbkmqv70LMNrjqVdttdIsC0BtH9T
hWLBwKVLH56EqfzqlzClKZEhWTNaddCSuxoZpN33mwS82DCjZe3d7nAPdEGD5pSB
x6TVt5bG1c3NVAmcBQIDAQAB
-----END PUBLIC KEY-----
-------------------------------Sign and verify operations-----------------------------------------
Sign the message...
Signature information of the message: 1fcf20c4fb548c8fc0906e369287feb84c861bf488d822d78a0eada23d1af66ed3a12e9440d7181b1748fd0ad805222cf2ce7ce1f6772b330ef11b717700ba26945dda9d749a5c4d8c108ede103c17bed92801a4c3fbc1ebf38d10bf4bf183713eeb7f429acc3dcc3812366a324737f756720f3f9e75ddda1e024a7698b89163
Verify the signature information...
The signature information is verified successfully, and it is determined that it is the correct private key signature!!
-------------------------------Perform encryption and decryption operations-----------------------------------------
Public key encrypted data: 637b05798c1cf95cfcc63adf228645c77f8e9a9f34b12b722e6938ded8c9560a0430171a4f940d3fb2d96bc6c470c80a817d81f4a2669b991adbff5b22b335129e514c921083ce3e64c1c876409d9b763d5e8e269797283ef951a364da6a59a1d8454391356cb0cd0808092e9dd7ac371f9247a43760f3c82b7ad26a32a7a807
Data decrypted by the private key: I am the encrypted data, remember me-------------------------------
--- PASS: TestRsa (0.02s)
PASS
Compression and decompression tools, single file compression, directory compression, or cross-directory compression
- files File array can be multi-directory files
- dest Compressed file storage address
func TestCompress(t *testing.T) {
open, err := os.Open("/Users/fanyanan/Downloads/gotool")
if err != nil {
t.Fatal(err)
}
files := []*os.File{open}
flag, err := gotool.ZipUtils.Compress(files, "/Users/fanyanan/Downloads/test.zip")
if err != nil {
t.Fatal(err)
}
if flag {
fmt.Println("Compressed successfully")
}
}
//out
== = RUN TestCompress
Compressed successfully
--- PASS: TestCompress (0.12s)
PASS
- zipFile Compressed package path
- dest Path to decompress
func TestDeCompress(t *testing.T) {
compress, err := gotool.ZipUtils.DeCompress("/Users/fanyanan/Downloads/test.zip", "/Users/fanyanan/Downloads")
if err != nil {
t.Fatal(err)
}
if compress {
fmt.Println("Successfully decompressed")
}
}
//out
== = RUN TestDeCompress
Successfully decompressed
--- PASS: TestDeCompress (0.44s)
PASS
File operation tools, making io operations easier and more convenient, making io operations not so difficult
func TestFileExists(t *testing.T) {
//Determine whether the file or directory exists
exists := gotool.FileUtils.Exists("F:/go-test/test")
fmt.Println("Before creation------------------------>", exists)
err := os.MkdirAll("F:/go-test/test", os.ModePerm)
if err != nil {
t.Fatal(err)
}
exists = gotool.FileUtils.Exists("F:/go-test/test")
fmt.Println("After creation------------------------>", exists)
}
//out
== = RUN TestFileExists
Before creation------------------------> false
After creation------------------------> true
--- PASS: TestFileExists (0.00s)
PASS
func TestIsDir(t *testing.T) {
//Determine whether it is a directory
dir := gotool.FileUtils.IsDir("F:/go-test/test")
fmt.Println("Is it a directory--------------------->", dir)
dir = gotool.FileUtils.IsDir("F:/go-test/test/test.txt")
fmt.Println("Is it a directory--------------------->", dir)
}
//out
== = RUN TestIsDir
Is it a directory---------------------> true
Is it a directory---------------------> false
--- PASS: TestIsDir (0.00s)
PASS
func TestIsFile(t *testing.T) {
//Determine whether it is a file
file := gotool.FileUtils.IsFile("F:/go-test/test")
fmt.Println("Is it a file--------------------->", file)
file = gotool.FileUtils.IsFile("F:/go-test/test/test.txt")
fmt.Println("Is it a file--------------------->", file)
}
//out
== = RUN TestIsFile
Is it a file---------------------> false
Is it a file---------------------> true
--- PASS: TestIsFile (0.00s)
PASS
func TestRemove(t *testing.T) {
//Delete Files
file, err := gotool.FileUtils.RemoveFile("F:/go-test/test/test.txt")
if err != nil {
t.Fatal(err)
}
if file {
//Check if the file still exists
exists := gotool.FileUtils.Exists("F:/go-test/test/test.txt")
fmt.Println("Does the file exist------------------------>", exists)
}
}
//out
== = RUN TestRemove
Does the file exist------------------------> false
--- PASS: TestRemove (0.00s)
PASS
5、gotool.FileUtils.OpenFileWronly Open the file in write-only mode, it will be automatically created if it is not, write to the internal slave for testing
func TestOpenFileWronly(t *testing.T) {
//Open a file in write-only mode and write 5 pieces of content. If the file does not exist, one will be created
path := "F:/go-test/test/test.txt"
str := "hello word gotool \n"
wronly, err := gotool.FileUtils.OpenFileWronly(path)
if err != nil {
t.Fatal(err)
}
defer wronly.Close()
write := bufio.NewWriter(wronly)
for i := 0; i < 5; i++ {
write.WriteString(str)
}
//Flush actually writes the cached file to the file
write.Flush()
//Read files and write to the console
files, err := gotool.FileUtils.OpenFileRdonly(path)
if err != nil {
t.Fatal(err)
}
defer files.Close()
reader := bufio.NewReader(files)
for {
str, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print(str)
}
}
//out
== = RUN TestOpenFileWronly
hello word gotool
hello word gotool
hello word gotool
hello word gotool
hello word gotool
--- PASS: TestOpenFileWronly (0.00s)
PASS
6、gotool.FileUtils.OpenFileRdonly Open the file in read-only mode, read the content and output to the console
func TestOpenFileRdonly(t *testing.T) {
path := "F:/go-test/test/test.txt"
files, err := gotool.FileUtils.OpenFileRdonly(path)
if err != nil {
t.Fatal(err)
}
defer files.Close()
reader := bufio.NewReader(files)
for {
str, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print(str)
}
}
//out
== = RUN TestOpenFileRdonly
hello word gotool
hello word gotool
hello word gotool
hello word gotool
hello word gotool
--- PASS: TestOpenFileRdonly (0.00s)
PASS
7、gotool.FileUtils.OpenFileAppend Open the file and append the content after the file, if not, the file will be created automatically
func TestOpenFileAppend(t *testing.T) {
//Open the file and append data after the file
path := "F:/go-test/test/test.txt"
str := "Additional content \n"
wronly, err := gotool.FileUtils.OpenFileAppend(path)
if err != nil {
t.Fatal(err)
}
defer wronly.Close()
write := bufio.NewWriter(wronly)
for i := 0; i < 5; i++ {
write.WriteString(str)
}
//Flush actually writes the cached file to the file
write.Flush()
//Read files and write to the console
files, err := gotool.FileUtils.OpenFileRdonly(path)
if err != nil {
t.Fatal(err)
}
defer files.Close()
reader := bufio.NewReader(files)
for {
str, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print(str)
}
}
//out
== = RUN TestOpenFileAppend
hello word gotool
hello word gotool
hello word gotool
hello word gotool
hello word gotool
Additional content
Additional content
Additional content
Additional content
Additional content
--- PASS: TestOpenFileAppend (0.00s)
PASS
func TestFileCopy(t *testing.T) {
//File copy function
path := "F:/go-test/test/test.txt"
copyPath := "F:/go-test/test/test.txt1"
//Copy money
exists := gotool.FileUtils.Exists(copyPath)
fmt.Println("Does the file exist before copying------------------>", exists)
//After copying
fileCopy, err := gotool.FileUtils.FileCopy(path, copyPath)
if err != nil {
t.Fatal(err)
}
if fileCopy {
exists := gotool.FileUtils.Exists(copyPath)
fmt.Println("Does the file exist before copying------------------>", exists)
}
}
//out
== = RUN TestFileCopy
Does the file exist before copying------------------> false
Does the file exist before copying------------------> true
--- PASS: TestFileCopy (0.00s)
PASS
func TestCaptcha(t *testing.T) {
//Generate verification code string, which can be stored in redis for verification logic
str := gotool.CaptchaUtils.GetRandStr(6)
fmt.Println(str)
}
//out
== = RUN TestCaptcha
Generate verification code string-------------------> qK5DME
--- PASS: TestCaptcha (0.01s)
PASS
2、gotool.CaptchaUtils.ImgText Generate image []byte array, which can be converted into base64 or image file
func TestCaptcha(t *testing.T) {
str := gotool.CaptchaUtils.GetRandStr(6)
fmt.Println("Generate verification code string------------------->", str)
//Generate image byte data, which can be converted into base64 or image file as needed
text := gotool.CaptchaUtils.ImgText(100, 40, str)
sourcestring := base64.StdEncoding.EncodeToString(text)
fmt.Println(sourcestring)
}
//out
== = RUN TestCaptcha
Generate verification code string-------------------> qK5DME
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
--- PASS: TestCaptcha (0.01s)
PASS
func TestLogs(t *testing.T) {
gotool.Logs.ErrorLog().Println("Error Log test")
gotool.Logs.InfoLog().Println("Info Log test")
gotool.Logs.DebugLog().Println("Debug Log test")
}
//out
== = RUN TestLogs
[ERROR] 2021/07/07 15:58:10 logs_test.go:9: Error Log test
[INFO] 2021/07/07 15:58:10 logs_test.go:10: Info Log test
[DEBUG] 2021/07/07 15:58:10 logs_test.go:11: Debug Log test
--- PASS: TestLogs (0.00s)
PASS
func TestPage(t *testing.T) {
paginator := gotool.PageUtils.Paginator(5, 20, 500)
fmt.Println(paginator)
}
//out
== = RUN TestPage
map[AfterPage:6 beforePage:4 currPage:5 pages:[3 4 5 6 7] totalPages:25]
--- PASS: TestPage (0.00s)
PASS
//Description AfterPage next page beforePage previous page currPage current page pages page number totalPages total number of pages
id generation tool, can generate string id and int type id, choose the generation rules you need according to your needs
1、gotool.IdUtils.IdUUIDToTime According to the UUID rules generated by time, enter the parameter true to eliminate "-" false to retain "-"
func TestUUID(t *testing.T) {
time, err := gotool.IdUtils.IdUUIDToTime(true)
if err == nil {
fmt.Println("Generate UUID removal based on time--------------------->'-'----->", time)
}
time, err = gotool.IdUtils.IdUUIDToTime(false)
if err == nil {
fmt.Println("Generate according to time without removing--------------------->'-'----->", time)
}
}
//out
== = RUN TestUUID
Generate UUID removal based on time--------------------->'-'-----> 6fb94fe4dfd511ebbc4418c04d462680
Generate according to time without removing--------------------->'-'-----> 6fb9c783-dfd5-11eb-bc44-18c04d462680
--- PASS: TestUUID (0.00s)
PASS
It is recommended to use this method based on the UUID generated by the random number, and there will be no duplication in concurrency. Parameter true to eliminate "-" false to retain "-"
time, err := gotool.IdUtils.IdUUIDToTime(true)
if err == nil {
fmt.Println("Generate UUID removal based on time--------------------->'-'----->", time)
}
time, err = gotool.IdUtils.IdUUIDToTime(false)
if err == nil {
fmt.Println("Generate according to time without removing--------------------->'-'----->", time)
}
//out
== = RUN TestUUID
Generate UUID removal based on time--------------------->'-'-----> cf5bcdc585454cda95447aae186d14e6
Generate according to time without removing--------------------->'-'-----> 72035dba-d45f-480f-b1fd-508d1e036f71
--- PASS: TestUUID (0.00s)
PASS
3、gotool.IdUtils.CreateCaptcha Generate a random number id, int type, enter the parameter int 1-18, if it exceeds 18, it will cause the int to exceed the length
func TestCreateCaptcha(t *testing.T) {
captcha, err := gotool.IdUtils.CreateCaptcha(18)
if err != nil {
fmt.Println(err)
}
fmt.Println("18 bits------------------------------------------>", captcha)
captcha, err = gotool.IdUtils.CreateCaptcha(10)
if err != nil {
fmt.Println(err)
}
fmt.Println("10 bits------------------------------------------>", captcha)
}
//out
== = RUN TestCreateCaptcha
18 bits------------------------------------------> 492457482855750014
10 bits------------------------------------------> 2855750014
--- PASS: TestCreateCaptcha (0.00s)
PASS
4、gotool.IdUtils.GetIdWorkAccording to the timestamp, it is calculated to obtain the id of int64. The length is 16 bits
func TestGetIdWork(t *testing.T) {
work := gotool.IdUtils.GetIdWork()
fmt.Println("Calculate according to the timestamp to obtain the int64 type id-------->", work)
}
//out
== = RUN TestGetIdWork
Calculate according to the timestamp to obtain the int64 type id--------> 1625746675366450
--- PASS: TestGetIdWork (0.00s)
PASS
A simple "HTTP request" package for golang GET
POST
DELETE
PUT
req.SetHeaders(map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "keep-alive",
})
req.SetHeaders(map[string]string{
"Source":"api",
})
req.SetCookies(map[string]string{
"name":"json",
"token":"",
})
OR
gotool.HttpUtils.SetCookies(map[string]string{
"age":"19",
}).Post()
req.SetTimeout(5) //default 30s
resp, err := req.Get("http://127.0.0.1:8000")
resp, err := req.Get("http://127.0.0.1:8000",nil)
resp, err := req.Get("http://127.0.0.1:8000?id=10&title=HttpRequest")
resp, err := req.Get("http://127.0.0.1:8000?id=10&title=HttpRequest", "address=beijing")
OR
resp, err := gotool.HttpUtils.Get("http://127.0.0.1:8000")
resp, err := gotool.HttpUtils.Debug(true).SetHeaders(map[string]string{}).Get("http://127.0.0.1:8000")
resp, err := req.Get("http://127.0.0.1:8000?id=10&title=HttpRequest", map[string]interface{}{
"name": "jason",
"score": 100,
})
defer resp.Close()
body, err := resp.Body()
if err != nil {
return
}
return string(body)
// Send nil
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000")
// Send integer
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000", 100)
// Send []byte
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000", []byte("bytes data"))
// Send io.Reader
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000", bytes.NewReader(buf []byte))
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000", strings.NewReader("string data"))
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000", bytes.NewBuffer(buf []byte))
// Send string
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000", "title=github&type=1")
// Send JSON
resp, err := gotool.HttpUtils.JSON().Post("http://127.0.0.1:8000", "{\"id\":10,\"title\":\"HttpRequest\"}")
// Send map[string]interface{}{}
resp, err := req.Post("http://127.0.0.1:8000", map[string]interface{}{
"id": 10,
"title": "HttpRequest",
})
defer resp.Close()
body, err := resp.Body()
if err != nil {
return
}
return string(body)
resp, err := gotool.HttpUtils.Post("http://127.0.0.1:8000")
resp, err := gotool.HttpUtils.JSON().Post("http://127.0.0.1:8000", map[string]interface{}{"title":"github"})
resp, err := gotool.HttpUtils.Debug(true).SetHeaders(map[string]string{}).JSON().Post("http://127.0.0.1:8000","{\"title\":\"github\"}")
proxy, err := url.Parse("http://proxyip:proxyport")
if err != nil {
log.Println(err)
}
resp, err := gotool.HttpUtils.Proxy(http.ProxyURL(proxy)).Get("http://127.0.0.1:8000/ip")
defer resp.Close()
if err != nil {
log.Println("Request error:%v", err.Error())
}
body, err := resp.Body()
if err != nil {
log.Println("Get body error:%v", err.Error())
}
log.Println(string(body))
Params: url, filename, fileinput
resp, err := req.Upload("http://127.0.0.1:8000/upload", "/root/demo.txt", "uploadFile")
body, err := resp.Body()
defer resp.Close()
if err != nil {
return
}
return string(body)
req.Debug(true)
[HttpRequest]
-------------------------------------------------------------------
Request: GET http: //127.0.0.1:8000?name=iceview&age=19&score=100
Headers: map[Content-Type:application/x-www-form-urlencoded]
Cookies: map[]
Timeout: 30s
ReqBody: map[age:19 score:100]
-------------------------------------------------------------------
Post JSON request
req.SetHeaders(map[string]string{"Content-Type": "application/json"})
Or
req.JSON().Post("http://127.0.0.1:8000", map[string]interface{}{
"id": 10,
"title": "github",
})
req.JSON().Post("http://127.0.0.1:8000", "{\"title\":\"github\",\"id\":10}")
resp, err := req.Post("http://127.0.0.1:8000", map[string]interface{}{
"id": 10,
"title": "HttpRequest",
})
str, err := resp.Export()
if err != nil {
return
}
var u User
err := resp.Json(&u)
if err != nil {
return err
}
var m map[string]interface{}
err := resp.Json(&m)
if err != nil {
return err
}
The quick menu tree generation is realized in gotool, including the selected state, half-selected state of the menu node, and the search of the menu.
The GenerateTree
custom structure implements the INode
interface and calls this method to generate the tree structure.
FindRelationNode
queries all the parent and child nodes of the node in nodes
in allNodes
Return respNodes
(including nodes
, and all its parent and child nodes)
package test
import (
"encoding/json"
"fmt"
"github.com/druidcaesa/gotool"
"github.com/druidcaesa/gotool/pretty"
"github.com/druidcaesa/gotool/tree"
"testing"
)
// Define our own menu object
type SystemMenu struct {
Id int `json:"id"` //id
Pid int `json:"pid"` //Upper menu id
Name string `json:"name"` //Menu name
Route string `json:"route"` //Page path
Icon string `json:"icon"` //Icon path
}
// region Implement all interfaces of ITree
func (s SystemMenu) GetTitle() string {
return s.Name
}
func (s SystemMenu) GetId() int {
return s.Id
}
func (s SystemMenu) GetPid() int {
return s.Pid
}
func (s SystemMenu) GetData() interface{} {
return s
}
func (s SystemMenu) IsRoot() bool {
// Here, FatherId is equal to 0 or FatherId is equal to its own Id to indicate the top-level root node
return s.Pid == 0 || s.Pid == s.Id
}
// endregion
type SystemMenus []SystemMenu
// ConvertToINodeArray Convert the current array to the parent INode interface array
func (s SystemMenus) ConvertToINodeArray() (nodes []tree.INode) {
for _, v := range s {
nodes = append(nodes, v)
}
return
}
func TestGenerateTree(t *testing.T) {
// Simulate to obtain all the menus in the database. In all other queries, first query all the data in the database and put them in the array.
// The subsequent traversal and recursion are all performed in this allMenu instead of recursive query in the database to reduce database pressure.
allMenu := []SystemMenu{
{Id: 1, Pid: 0, Name: "SystemOverview", Route: "/systemOverview", Icon: "icon-system"},
{Id: 2, Pid: 0, Name: "SystemConfiguration", Route: "/systemConfig", Icon: "icon-config"},
{Id: 3, Pid: 1, Name: "assets", Route: "/asset", Icon: "icon-asset"},
{Id: 4, Pid: 1, Name: "MovingRing", Route: "/pe", Icon: "icon-pe"},
{Id: 5, Pid: 2, Name: "MenuConfiguration", Route: "/menuConfig", Icon: "icon-menu-config"},
{Id: 6, Pid: 3, Name: "equipment", Route: "/device", Icon: "icon-device"},
{Id: 7, Pid: 3, Name: "Cabinet", Route: "/device", Icon: "icon-device"},
}
// Complete cabinet generation tree
resp := gotool.TreeUtils.GenerateTree(SystemMenus.ConvertToINodeArray(allMenu), nil)
bytes, _ := json.MarshalIndent(resp, "", "\t")
// Simulate selecting the'Assets' menu
selectedNode := []SystemMenu{allMenu[2]}
resp = gotool.TreeUtils.GenerateTree(SystemMenus.ConvertToINodeArray(allMenu), SystemMenus.ConvertToINodeArray(selectedNode))
bytes, _ = json.Marshal(resp)
// Simulate querying the'equipment' from the database
device := []SystemMenu{allMenu[5]}
// Query all parent nodes of the device
respNodes := gotool.TreeUtils.FindRelationNode(SystemMenus.ConvertToINodeArray(device), SystemMenus.ConvertToINodeArray(allMenu))
resp = gotool.TreeUtils.GenerateTree(respNodes, nil)
bytes, _ = json.Marshal(resp)
fmt.Println(string(pretty.Color(pretty.PrettyOptions(bytes, pretty.DefaultOptions), nil)))
}
- Output structure`
[
{
"title": "SystemOverview",
"data": {
"id": 1,
"pid": 0,
"name": "SystemOverview",
"route": "/systemOverview",
"icon": "icon-system"
},
"leaf": false,
"checked": false,
"partiallySelected": false,
"children": [
{
"title": "assets",
"data": {
"id": 3,
"pid": 1,
"name": "assets",
"route": "/asset",
"icon": "icon-asset"
},
"leaf": false,
"checked": false,
"partiallySelected": false,
"children": [
{
"title": "equipment",
"data": {
"id": 6,
"pid": 3,
"name": "equipment",
"route": "/device",
"icon": "icon-device"
},
"leaf": true,
"checked": false,
"partiallySelected": false,
"children": null
}
]
}
]
}
]
Thanks for this feature azhengyongqin
In data processing or cleaning, a lot of desensitization of private information may be involved, so gotool encapsulates some desensitization methods for commonly used information.
- Desensitization of Chinese ID cards, mobile phones, and ID cards
- General mailbox desensitization
func TestDesensitized(t *testing.T) {
//mail desensitization
mail := "testhello@gmail.com"
star := gotool.DesensitizedUtils.DefaultDesensitized(mail)
fmt.Println("mail-------------------->", star)
//phone desensitization
phone := "13333333333"
desensitized := gotool.DesensitizedUtils.DefaultDesensitized(phone)
fmt.Println("phone------------------->", desensitized)
}
//out
=== RUN TestDesensitized
mail--------------------> tes***@gmail.com
phone-------------------> 133****3333
--- PASS: TestDesensitized (0.00s)
PASS
- Custom desensitization
str
data to be desensitizedstart
start positionend
end position
func TestDesensitized(t *testing.T) {
//customize desensitization
customize := "sadasdasdkljkldfjlkdjflkjsdf"
hideStar := gotool.DesensitizedUtils.CustomizeHash(customize, 4, 14)
fmt.Println("customize--------------->", hideStar)
}
//out
=== RUN TestDesensitized
customize---------------> sada**********dfjlkdjflkjsdf
--- PASS: TestDesensitized (0.00s)
PASS
PrettyUtils is a gotool package that provides methods for formatting JSON for human readability, or to compact JSON for smaller payloads.
Using this example:
{"name": {"first":"Tom","last":"Anderson"}, "age":37,
"children": ["Sara","Alex","Jack"],
"fav.movie": "Deer Hunter", "friends": [
{"first": "Janet", "last": "Murphy", "age": 44}
]}
The following code:
result = pretty.Pretty(example)
Will format the json to:
{
"name": {
"first": "Tom",
"last": "Anderson"
},
"age": 37,
"children": ["Sara", "Alex", "Jack"],
"fav.movie": "Deer Hunter",
"friends": [
{
"first": "Janet",
"last": "Murphy",
"age": 44
}
]
}
Color will colorize the json for outputing to the screen.
result = pretty.Color(json, nil)
Will add color to the result for printing to the terminal.
The second param is used for a customizing the style, and passing nil will use the default pretty.TerminalStyle
.
The following code:
result = pretty.Ugly(example)
Will format the json to:
{"name":{"first":"Tom","last":"Anderson"},"age":37,"children":["Sara","Alex","Jack"],"fav.movie":"Deer Hunter","friends":[{"first":"Janet","last":"Murphy","age":44}]}```
There's a PrettyOptions(json, opts)
function which allows for customizing the output with the following options:
type Options struct {
// Width is an max column width for single line arrays
// Default is 80
Width int
// Prefix is a prefix for all lines
// Default is an empty string
Prefix string
// Indent is the nested indentation
// Default is two spaces
Indent string
// SortKeys will sort the keys alphabetically
// Default is false
SortKeys bool
}