mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 21:02:27 +08:00
Compare commits
261 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fafb59dad6 | ||
|
|
e36c01cac9 | ||
|
|
aa0afa8d94 | ||
|
|
18e0031e0e | ||
|
|
a5018c110c | ||
|
|
142deb83b2 | ||
|
|
ccc0188352 | ||
|
|
98dba83107 | ||
|
|
9c6aff9030 | ||
|
|
7fd9a94922 | ||
|
|
dd3b1f3aed | ||
|
|
f9dce592e8 | ||
|
|
c4b0967623 | ||
|
|
41613061d5 | ||
|
|
50ef63e27d | ||
|
|
3ae4a35d04 | ||
|
|
89ea0ee15a | ||
|
|
85399e23ed | ||
|
|
19a6f218e6 | ||
|
|
ccaf290b63 | ||
|
|
54745d512c | ||
|
|
39234d4722 | ||
|
|
4b4310265b | ||
|
|
d8a982bf07 | ||
|
|
0334a6f02b | ||
|
|
ae0c613b8e | ||
|
|
40b2560752 | ||
|
|
50c6e51393 | ||
|
|
1434e00712 | ||
|
|
76c941cff0 | ||
|
|
bb03f31a8b | ||
|
|
c939b26cb8 | ||
|
|
af480efa8c | ||
|
|
bc913d70b1 | ||
|
|
2bc87d8a6b | ||
|
|
2185c48eab | ||
|
|
59b5046a15 | ||
|
|
569902b528 | ||
|
|
78519088ab | ||
|
|
0c06cdb29f | ||
|
|
7ac6816532 | ||
|
|
81c4216699 | ||
|
|
2e30389703 | ||
|
|
0e1d5cf04b | ||
|
|
4e2d84e4fc | ||
|
|
e8b8ff8927 | ||
|
|
13ee045b99 | ||
|
|
06bd407a0c | ||
|
|
aa28479d11 | ||
|
|
bf7db0ded2 | ||
|
|
dd1cbf2ee3 | ||
|
|
9d5db895c9 | ||
|
|
f1fd4c876b | ||
|
|
cd63b2b18f | ||
|
|
bab9b4a6b3 | ||
|
|
b3c34578bf | ||
|
|
f26477904e | ||
|
|
6b09da6e6e | ||
|
|
b2b6710a1b | ||
|
|
e7ee2ed7cf | ||
|
|
85886cf618 | ||
|
|
a19a861552 | ||
|
|
1dfd1ec1d3 | ||
|
|
96d57a6d24 | ||
|
|
b48155c249 | ||
|
|
41685022c0 | ||
|
|
2e8834a2c1 | ||
|
|
df098392c2 | ||
|
|
4e7274ce05 | ||
|
|
2384b0e51f | ||
|
|
6b6b938d1e | ||
|
|
29d8987909 | ||
|
|
43fb3f1a06 | ||
|
|
34c28fece3 | ||
|
|
40c2402493 | ||
|
|
c965e79bfc | ||
|
|
eeadb1fecb | ||
|
|
5e318a78d2 | ||
|
|
d872d64fe0 | ||
|
|
c2257493a8 | ||
|
|
48c1f8ffad | ||
|
|
8a4c8218d2 | ||
|
|
92e1321d43 | ||
|
|
43fb907a81 | ||
|
|
f551c56921 | ||
|
|
85e1f711f5 | ||
|
|
ade567a620 | ||
|
|
a26e519a3f | ||
|
|
797e47363f | ||
|
|
20e1836eb7 | ||
|
|
5ae746a1f0 | ||
|
|
17d271190b | ||
|
|
310f8bd1e1 | ||
|
|
bf7a4e729f | ||
|
|
1dd826f050 | ||
|
|
8b04aa5f31 | ||
|
|
6855fe0bce | ||
|
|
300be9e3dc | ||
|
|
384be2e2e9 | ||
|
|
1d71a0ad3a | ||
|
|
0e0ed316f1 | ||
|
|
8d0ff28304 | ||
|
|
cee9bb538f | ||
|
|
eb59d02a08 | ||
|
|
10ed71a3a2 | ||
|
|
0e86244559 | ||
|
|
5ab150cad3 | ||
|
|
3546afe86c | ||
|
|
961eedda04 | ||
|
|
f4881d2f49 | ||
|
|
a3eb269bdb | ||
|
|
e367123070 | ||
|
|
0f1d3fb553 | ||
|
|
a4658b2341 | ||
|
|
739113ef9e | ||
|
|
1629b861cd | ||
|
|
acce85557f | ||
|
|
05aefbaa62 | ||
|
|
6988fdc451 | ||
|
|
5963830879 | ||
|
|
134aded4d8 | ||
|
|
35780d9dc1 | ||
|
|
c40ac9bb9b | ||
|
|
51bd974cc9 | ||
|
|
0b93fbffd9 | ||
|
|
349f8b6c97 | ||
|
|
70077a6010 | ||
|
|
efdf36a817 | ||
|
|
e233788f69 | ||
|
|
957e6356f6 | ||
|
|
887eaa528a | ||
|
|
33126570bd | ||
|
|
5937183af0 | ||
|
|
5899921054 | ||
|
|
ec19014578 | ||
|
|
1ad990ce9d | ||
|
|
4eaa0a39d5 | ||
|
|
18ec73839b | ||
|
|
89aef977a2 | ||
|
|
2612569500 | ||
|
|
acc8b59387 | ||
|
|
8bb102cb6e | ||
|
|
e07d54d1da | ||
|
|
6f035f710e | ||
|
|
2878d389c8 | ||
|
|
92967e0add | ||
|
|
6a1a0b8677 | ||
|
|
ca88687f3d | ||
|
|
aa64bf5bee | ||
|
|
a3399503f7 | ||
|
|
3ca096b4ac | ||
|
|
3f8effb7a3 | ||
|
|
bd30855ae6 | ||
|
|
0efe2f57c3 | ||
|
|
28317a1683 | ||
|
|
2ab898741d | ||
|
|
454efd486d | ||
|
|
8868fcabed | ||
|
|
efa20a97c4 | ||
|
|
25ef78bc64 | ||
|
|
261370e30d | ||
|
|
dfbb9e30e0 | ||
|
|
b22be7cade | ||
|
|
87da6c6816 | ||
|
|
764a6fe107 | ||
|
|
f3749c52b9 | ||
|
|
f368854b2d | ||
|
|
912f7052a3 | ||
|
|
c424b88d40 | ||
|
|
e6f9b0954c | ||
|
|
98e861cf3b | ||
|
|
43e0ca7edf | ||
|
|
d491bea263 | ||
|
|
6f1feb96d6 | ||
|
|
aeebd63eda | ||
|
|
22b3c4dd42 | ||
|
|
bd976642f6 | ||
|
|
d46d12f949 | ||
|
|
e31fb28003 | ||
|
|
fd271fe176 | ||
|
|
6890bbfe05 | ||
|
|
c6fc92a94c | ||
|
|
24ae47a12f | ||
|
|
f4fa790b72 | ||
|
|
d8d85efedf | ||
|
|
22798fd750 | ||
|
|
ba73847b80 | ||
|
|
69453eba19 | ||
|
|
907df56f86 | ||
|
|
f147f78a41 | ||
|
|
3dadfa234b | ||
|
|
f1d7154179 | ||
|
|
dc47b9ce98 | ||
|
|
6e626851cf | ||
|
|
c906d8aea7 | ||
|
|
e5e4e09308 | ||
|
|
7ed173849a | ||
|
|
24c0d95112 | ||
|
|
e9fed34729 | ||
|
|
9caefdb67d | ||
|
|
681d5b6bdf | ||
|
|
b0e9758e0d | ||
|
|
7b9a8a55e7 | ||
|
|
44ac82e8b8 | ||
|
|
c4b4cb1173 | ||
|
|
bbfc5b7060 | ||
|
|
1f45937190 | ||
|
|
52c5a91606 | ||
|
|
49f62c3550 | ||
|
|
23701e6998 | ||
|
|
1199c30ef3 | ||
|
|
b0e17c7bc4 | ||
|
|
d3525dfe8f | ||
|
|
9da7115169 | ||
|
|
9cb9aa2f2f | ||
|
|
e4cd7dad35 | ||
|
|
31e08197d4 | ||
|
|
642d0b8077 | ||
|
|
25b2ae6b98 | ||
|
|
65719515bd | ||
|
|
3ffd81a98a | ||
|
|
f490ef2404 | ||
|
|
3438f3b18a | ||
|
|
73f4ae7b35 | ||
|
|
30d798366b | ||
|
|
3e9a2b5c59 | ||
|
|
1343683b08 | ||
|
|
a8996933bf | ||
|
|
3905c0bde1 | ||
|
|
c7e961704d | ||
|
|
cb7df1b57d | ||
|
|
eeff28606e | ||
|
|
86d4b25a2b | ||
|
|
ad287ed99a | ||
|
|
df9de3065b | ||
|
|
71a2ea3f20 | ||
|
|
955f2e6de6 | ||
|
|
4aef9d6d22 | ||
|
|
4752725dd6 | ||
|
|
07d1704cb2 | ||
|
|
74d262e609 | ||
|
|
97e0789ea4 | ||
|
|
bc39b0887b | ||
|
|
4fd8a18677 | ||
|
|
3de906d7c9 | ||
|
|
56fc12c660 | ||
|
|
7a9b0847f9 | ||
|
|
9266d99249 | ||
|
|
f15131f032 | ||
|
|
b4a49fccfd | ||
|
|
94b1a1d383 | ||
|
|
7db46696f6 | ||
|
|
d4f49af2ad | ||
|
|
ed4acc1c67 | ||
|
|
042a00296f | ||
|
|
b42aac53b3 | ||
|
|
c625a88067 | ||
|
|
e15ae9eb98 | ||
|
|
bb4ac01209 | ||
|
|
147c1625b5 | ||
|
|
2aed55f704 |
6
.github/workflows/codecov.yml
vendored
6
.github/workflows/codecov.yml
vendored
@@ -1,11 +1,13 @@
|
||||
name: Test and coverage
|
||||
name: test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# - v2
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# - v2
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -15,7 +17,7 @@ jobs:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: "1.16"
|
||||
go-version: "1.18"
|
||||
- name: Run coverage
|
||||
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
|
||||
- name: Upload coverage to Codecov
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,7 @@
|
||||
.DS_Store
|
||||
cryptor/*.txt
|
||||
fileutil/*.txt
|
||||
fileutil/*.zip
|
||||
fileutil/*.link
|
||||
fileutil/unzip/*
|
||||
cryptor/*.pem
|
||||
713
README.md
713
README.md
@@ -1,44 +1,54 @@
|
||||
<div align="center">
|
||||
<h1 style="width: 100%; text-align: center;">Lancet</h1>
|
||||
<p style="font-size: 18px">
|
||||
Lancet is a comprehensive, efficient, and reusable util function library of go. Inspired by the java apache common package and lodash.js.
|
||||
</p>
|
||||
<div align="center" style="text-align: center;">
|
||||
<div align=center>
|
||||
<img src="./logo.png" width="200" height="200"/>
|
||||
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
[](https://codecov.io/gh/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||
|
||||
</div>
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
<p style="font-size: 20px">
|
||||
Lancet is a comprehensive, efficient, and reusable util function library of go. Inspired by the java apache common package and lodash.js.
|
||||
</p>
|
||||
|
||||
English | [简体中文](./README_zh-CN.md)
|
||||
|
||||
</div>
|
||||
|
||||
### Feature
|
||||
## Feature
|
||||
|
||||
- 👏 Comprehensive, efficient and reusable.
|
||||
- 💪 100+ common go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💪 250+ go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💅 Only depend on the go standard library.
|
||||
- 🌍 Unit test for exery exported function.
|
||||
- 🌍 Unit test for every exported function.
|
||||
|
||||
### Installation
|
||||
## Installation
|
||||
### Note:
|
||||
|
||||
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause v2.x.x rewrite all functions with generics of go1.18.</b>
|
||||
```go
|
||||
go get github.com/duke-git/lancet
|
||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||
```
|
||||
|
||||
### Usage
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.2.7. </b>
|
||||
```go
|
||||
go get github.com/duke-git/lancet@v1.2.7 // below go1.18, install latest version of v1.x.x
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Lancet organizes the code into package structure, and you need to import the corresponding package name when use it. For example, if you use string-related functions,import the strutil package like below:
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/strutil"
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
```
|
||||
|
||||
### Example
|
||||
## Example
|
||||
|
||||
Here takes the string function ReverseStr (reverse order string) as an example, and the strutil package needs to be imported.
|
||||
|
||||
@@ -47,7 +57,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/strutil"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -57,436 +67,363 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### API Documentation
|
||||
## API Documentation
|
||||
|
||||
#### 1. convertor contains some functions for data convertion
|
||||
|
||||
- Support conversion between commonly used data types.
|
||||
- Usage: import "github.com/duke-git/lancet/cryptor"
|
||||
### Algorithm package implements some basic algorithm. eg. sort, search.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := "12.3"
|
||||
f, err := convertor.ToFloat(s)
|
||||
if err != nil {
|
||||
fmt.Errorf("error is %s", err.Error())
|
||||
}
|
||||
fmt.Println(f) // 12.3
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/algorithm"
|
||||
```
|
||||
#### Function list:
|
||||
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BubbleSort)
|
||||
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#CountSort)
|
||||
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#HeapSort)
|
||||
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#InsertionSort)
|
||||
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#MergeSort)
|
||||
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#QuickSort)
|
||||
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#SelectionSort)
|
||||
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#ShellSort)
|
||||
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinarySearch)
|
||||
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinaryIterativeSearch)
|
||||
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LinearSearch)
|
||||
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)
|
||||
|
||||
- Function list:
|
||||
|
||||
### Convertor package contains some functions for data convertion.
|
||||
|
||||
```go
|
||||
func ColorHexToRGB(colorHex string) (red, green, blue int) //convert color hex to color rgb
|
||||
func ColorRGBToHex(red, green, blue int) string //convert color rgb to color hex
|
||||
func ToBool(s string) (bool, error) //convert string to a boolean
|
||||
func ToBytes(data interface{}) ([]byte, error) //convert interface to bytes
|
||||
func ToChar(s string) []string //convert string to char slice
|
||||
func ToFloat(value interface{}) (float64, error) //convert value to float64, if input is not a float return 0.0 and error
|
||||
func ToInt(value interface{}) (int64, error) //convert value to int64, if input is not a numeric format return 0 and error
|
||||
func ToJson(value interface{}) (string, error) //convert value to a valid json string
|
||||
func ToString(value interface{}) string //convert value to string
|
||||
func StructToMap(value interface{}) (map[string]interface{}, error) //convert struct to map, only convert exported field, tag `json` should be set
|
||||
import "github.com/duke-git/lancet/v2/convertor"
|
||||
```
|
||||
|
||||
#### 2. cryptor is for data encryption and decryption
|
||||
|
||||
- Support md5, hmac, aes, des, ras.
|
||||
- Usage: import "github.com/duke-git/lancet/cryptor"
|
||||
#### Function list:
|
||||
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
|
||||
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorRGBToHex)
|
||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
|
||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
|
||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
|
||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
|
||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
|
||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
|
||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
|
||||
|
||||
### Cryptor package is for data encryption and decryption.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) // hello
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/cryptor"
|
||||
```
|
||||
|
||||
- Function list:
|
||||
#### Function list:
|
||||
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbEncrypt)
|
||||
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbDecrypt)
|
||||
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt)
|
||||
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode)
|
||||
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode)
|
||||
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt)
|
||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)
|
||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)
|
||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)
|
||||
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)
|
||||
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)
|
||||
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)
|
||||
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)
|
||||
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)
|
||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)
|
||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt)
|
||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)
|
||||
|
||||
### Datetime package supports date and time format and compare.
|
||||
|
||||
|
||||
```go
|
||||
func AesEcbEncrypt(data, key []byte) []byte //AES ECB encrypt
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte //AES ECB decrypt
|
||||
func AesCbcEncrypt(data, key []byte) []byte //AES CBC encrypt
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte //AES CBC decrypt
|
||||
func AesCtrCrypt(data, key []byte) []byte //AES CTR encrypt / decrypt
|
||||
func AesCfbEncrypt(data, key []byte) []byte //AES CFB encrypt
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte //AES CFB decrypt
|
||||
func AesOfbEncrypt(data, key []byte) []byte //AES OFB encrypt
|
||||
func AesOfbDecrypt(data, key []byte) []byte //AES OFB decrypt
|
||||
func Base64StdEncode(s string) string //base64 encode
|
||||
func Base64StdDecode(s string) string //base64 decode
|
||||
func DesCbcEncrypt(data, key []byte) []byte //DES CBC encrypt
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte //DES CBC decrypt
|
||||
func DesCtrCrypt(data, key []byte) []byte //DES CTR encrypt/decrypt
|
||||
func DesCfbEncrypt(data, key []byte) []byte //DES CFB encrypt
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte //DES CFB decrypt
|
||||
func DesOfbEncrypt(data, key []byte) []byte //DES OFB encrypt
|
||||
func DesOfbDecrypt(data, key []byte) []byte //DES OFB decrypt
|
||||
func HmacMd5(data, key string) string //get hmac md5 value
|
||||
func HmacSha1(data, key string) string //get hmac sha1 value
|
||||
func HmacSha256(data, key string) string //get hmac sha256 value
|
||||
func HmacSha512(data, key string) string //get hmac sha512 value
|
||||
func Sha1(data string) string //get sha1 value
|
||||
func Sha256(data string) string //getsha256 value
|
||||
func Sha512(data string) string //get sha512 value
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) //generate RSA pem file
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte //RSA encrypt
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte //RSA decrypt
|
||||
|
||||
import "github.com/duke-git/lancet/v2/datetime"
|
||||
```
|
||||
#### Function list:
|
||||
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay)
|
||||
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddHour)
|
||||
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)
|
||||
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)
|
||||
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)
|
||||
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)
|
||||
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
|
||||
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
|
||||
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
|
||||
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
|
||||
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
|
||||
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
|
||||
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
|
||||
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
|
||||
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
|
||||
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDate)
|
||||
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowTime)
|
||||
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime)
|
||||
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetZeroHourTimestamp)
|
||||
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)
|
||||
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)
|
||||
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)
|
||||
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)
|
||||
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)
|
||||
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)
|
||||
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)
|
||||
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)
|
||||
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)
|
||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)
|
||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)
|
||||
|
||||
#### 3. datetime parse and format datetime
|
||||
|
||||
- Parse and format datetime
|
||||
- Usage: import "github.com/duke-git/lancet/datetime"
|
||||
### Fileutil package implements some basic functions for file operations.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
s := datetime.FormatTimeToStr(now, "yyyy-mm-dd hh:mm:ss")
|
||||
fmt.Println(s) // 2021-11-24 11:16:55
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
```
|
||||
|
||||
- Function list:
|
||||
#### Function list:
|
||||
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)
|
||||
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsExist)
|
||||
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsLink)
|
||||
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsDir)
|
||||
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ListFileNames)
|
||||
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#RemoveFile)
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
|
||||
|
||||
### Formatter contains some functions for data formatting.
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time //add or sub days to time
|
||||
func AddHour(t time.Time, hour int64) time.Time //add or sub hours to time
|
||||
func AddMinute(t time.Time, minute int64) time.Time //add or sub minutes to time
|
||||
func GetNowDate() string //get current date, format is yyyy-mm-dd
|
||||
func GetNowTime() string //get current time, format is hh:mm:ss
|
||||
func GetNowDateTime() string //get current date and time, format is yyyy-mm-dd hh:mm:ss
|
||||
func GetZeroHourTimestamp() int64 //return timestamp of zero hour (timestamp of 00:00)
|
||||
func GetNightTimestamp() int64 //return timestamp of zero hour (timestamp of 23:59)
|
||||
func FormatTimeToStr(t time.Time, format string) string //convert time to string
|
||||
func FormatStrToTime(str, format string) time.Time //convert string to time
|
||||
import "github.com/duke-git/lancet/v2/formatter"
|
||||
```
|
||||
#### Function list:
|
||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
|
||||
|
||||
#### 4. fileutil basic functions for file operations
|
||||
|
||||
- Basic functions for file operations.
|
||||
- Usage: import "github.com/duke-git/lancet/fileutil"
|
||||
### Function package can control the flow of function execution and support part of functional programming
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(fileutil.IsDir("./")) // true
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/function"
|
||||
```
|
||||
|
||||
- Function list:
|
||||
#### Function list:
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/function.md#After)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/function.md#Before)
|
||||
- [Curry](https://github.com/duke-git/lancet/blob/main/docs/function.md#Curry)
|
||||
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function.md#Compose)
|
||||
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function.md#Debounced)
|
||||
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function.md#Delay)
|
||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
|
||||
|
||||
|
||||
### Mathutil package implements some functions for math calculation.
|
||||
|
||||
```go
|
||||
func ClearFile(path string) error //write empty string to path file
|
||||
func CreateFile(path string) bool // create a file in path
|
||||
func CopyFile(srcFilePath string, dstFilePath string) error //copy src file to dst file
|
||||
func IsExist(path string) bool //checks if a file or directory exists
|
||||
func IsDir(path string) bool //checks if the path is directy or not
|
||||
func ListFileNames(path string) ([]string, error) //return all file names in the path
|
||||
func RemoveFile(path string) error //remove the path file
|
||||
func ReadFileToString(path string) (string, error) //return string of file content
|
||||
func ReadFileByLine(path string)([]string, error) //read file content by line
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
```
|
||||
|
||||
#### 5. formatter is for data format
|
||||
#### Function list:
|
||||
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Average)
|
||||
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)
|
||||
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)
|
||||
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)
|
||||
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Max)
|
||||
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Min)
|
||||
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)
|
||||
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)
|
||||
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)
|
||||
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)
|
||||
|
||||
- Contain some formatting function
|
||||
- Usage: import "github.com/duke-git/lancet/formatter"
|
||||
|
||||
### Netutil package contains functions to get net information and send http request.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(formatter.Comma("12345", "")) // "12,345"
|
||||
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/netutil"
|
||||
```
|
||||
|
||||
- Function list:
|
||||
#### Function list:
|
||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)
|
||||
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp)
|
||||
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
||||
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
||||
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo)
|
||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)
|
||||
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
|
||||
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
|
||||
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
|
||||
- [HttpPut](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)
|
||||
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)
|
||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)
|
||||
|
||||
### Random package implements some basic functions to generate random int and string.
|
||||
|
||||
```go
|
||||
func Comma(v interface{}, symbol string) string //add comma to number by every 3 numbers from right. ahead by symbol char
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
```
|
||||
|
||||
#### 6. function can control the function execution and support functional programming
|
||||
#### Function list:
|
||||
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
|
||||
- Control function execution and support functional programming.
|
||||
- Usage: import "github.com/duke-git/lancet/function"
|
||||
### Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var print = func(s string) {
|
||||
fmt.Println(s)
|
||||
}
|
||||
function.Delay(2*time.Second, print, "hello world")
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/retry"
|
||||
```
|
||||
|
||||
- Function list:
|
||||
#### Function list:
|
||||
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Context)
|
||||
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Retry)
|
||||
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc)
|
||||
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)
|
||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)
|
||||
|
||||
### Slice contains some functions to manipulate slice.
|
||||
|
||||
```go
|
||||
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value //creates a function that invokes func once it's called n or more times
|
||||
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value //creates a function that invokes func once it's called less than n times
|
||||
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //make a curryed function
|
||||
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} //compose the functions from right to left
|
||||
func Delay(delay time.Duration, fn interface{}, args ...interface{}) //invoke function after delayed time
|
||||
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool //invoke function every duration time, util close the returned bool chan
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
```
|
||||
|
||||
#### 7. netutil is for net process
|
||||
#### Function list:
|
||||
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)
|
||||
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
|
||||
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
|
||||
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)
|
||||
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)
|
||||
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
|
||||
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
|
||||
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
|
||||
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
||||
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
|
||||
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
|
||||
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
|
||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
|
||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
|
||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
|
||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
|
||||
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
|
||||
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
|
||||
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
|
||||
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
|
||||
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
|
||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
|
||||
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
|
||||
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
|
||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
|
||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)
|
||||
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)
|
||||
|
||||
- Ip and http request method.
|
||||
- Usage: import "github.com/duke-git/lancet/netutil".
|
||||
- The Http function params order:url, header, query string, body, httpclient.
|
||||
### Strutil package contains some functions to manipulate string.
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)
|
||||
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)
|
||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)
|
||||
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#CamelCase)
|
||||
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)
|
||||
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)
|
||||
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)
|
||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)
|
||||
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)
|
||||
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)
|
||||
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
|
||||
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReverseStr)
|
||||
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
|
||||
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
|
||||
|
||||
### System package contain some functions about os, runtime, shell command.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://gutendex.com/books?"
|
||||
header := make(map[string]string)
|
||||
header["Content-Type"] = "application/json"
|
||||
queryParams := make(map[string]interface{})
|
||||
queryParams["ids"] = "1"
|
||||
|
||||
resp, err := netutil.HttpGet(url, header, queryParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/system"
|
||||
```
|
||||
#### Function list:
|
||||
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
|
||||
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
|
||||
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)
|
||||
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)
|
||||
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)
|
||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
|
||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
|
||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
|
||||
|
||||
- Function list:
|
||||
### Validator package contains some functions for data validation.
|
||||
|
||||
```go
|
||||
func GetInternalIp() string //get internal ip
|
||||
func GetPublicIpInfo() (*PublicIpInfo, error) //get public ip info: country, region, isp, city, lat, lon, ip
|
||||
func IsPublicIP(IP net.IP) bool //判断ip是否为公共ip
|
||||
func HttpGet(url string, params ...interface{}) (*http.Response, error) //http get request
|
||||
func HttpPost(url string, params ...interface{}) (*http.Response, error) //http post request
|
||||
func HttpPut(url string, params ...interface{}) (*http.Response, error) //http put request
|
||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete request
|
||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch request
|
||||
func ConvertMapToQueryString(param map[string]interface{}) string //convert map to url query string
|
||||
func ParseHttpResponse(resp *http.Response, obj interface{}) error //decode http response to specified interface
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
```
|
||||
|
||||
#### 8. random is for rand string and int generation
|
||||
#### Function list:
|
||||
|
||||
- Generate random string and int.
|
||||
- Usage: import "github.com/duke-git/lancet/random".
|
||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
|
||||
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLetter)
|
||||
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLower)
|
||||
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainUpper)
|
||||
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAlpha)
|
||||
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllUpper)
|
||||
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllLower)
|
||||
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsBase64)
|
||||
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseMobile)
|
||||
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseIdNum)
|
||||
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChinesePhone)
|
||||
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsCreditCard)
|
||||
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsDns)
|
||||
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmail)
|
||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)
|
||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloatStr)
|
||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)
|
||||
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)
|
||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)
|
||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)
|
||||
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIp)
|
||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV4)
|
||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV6)
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
|
||||
### xerror package implements helpers for errors.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr)
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/xerror"
|
||||
```
|
||||
#### Function list:
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
|
||||
|
||||
|
||||
- Function list:
|
||||
## How to Contribute
|
||||
|
||||
```go
|
||||
func RandBytes(length int) []byte //generate random []byte
|
||||
func RandInt(min, max int) int //generate random int
|
||||
func RandString(length int) string //generate random string
|
||||
```
|
||||
I really appreciate any code commits which make lancet lib powerful. Please follow the rules below to create your pull request.
|
||||
|
||||
#### 9. slice is for process slice
|
||||
|
||||
- Contain function for process slice.
|
||||
- Usage: import "github.com/duke-git/lancet/slice"
|
||||
- Due to the unstable support of generic, most of the slice processing function parameter and return value is interface {}. After go generic is stable, the related functions will be refactored.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 4, 3, 4, 6, 7, 3}
|
||||
uniqueNums, _ := slice.IntSlice(slice.Unique(nums))
|
||||
fmt.Println(uniqueNums) //[1 4 3 6 7]
|
||||
}
|
||||
```
|
||||
|
||||
- Function list:
|
||||
|
||||
```go
|
||||
func Contain(slice interface{}, value interface{}) bool //check if the value is in the slice or not
|
||||
func Chunk(slice []interface{}, size int) [][]interface{} //creates an slice of elements split into groups the length of `size`.
|
||||
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //convert originalSlice to newSliceType
|
||||
func Difference(slice1, slice2 interface{}) interface{} //creates an slice of whose element not included in the other given slice
|
||||
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //delete the element of slice from start index to end index - 1
|
||||
func Every(slice, function interface{}) bool //return true if all of the values in the slice pass the predicate function, function signature should be func(index int, value interface{}) bool
|
||||
func Filter(slice, function interface{}) interface{} //filter slice, function signature should be func(index int, value interface{}) bool
|
||||
func Find(slice, function interface{}) interface{} //iterates over elements of slice, returning the first one that passes a truth test on function.function signature should be func(index int, value interface{}) bool .
|
||||
func IntSlice(slice interface{}) ([]int, error) //convert value to int slice
|
||||
func InterfaceSlice(slice interface{}) []interface{} //convert value to interface{} slice
|
||||
func Intersection(slices ...interface{}) interface{} //creates a slice of unique values that included by all slices.
|
||||
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //insert the element into slice at index.
|
||||
func Map(slice, function interface{}) interface{} //map lisce, function signature should be func(index int, value interface{}) interface{}
|
||||
func ReverseSlice(slice interface{}) //revere slice
|
||||
func Reduce(slice, function, zero interface{}) interface{} //reduce slice, function signature should be func(index int, value1, value2 interface{}) interface{}
|
||||
func SortByField(slice interface{}, field string, sortType ...string) error //sort struct slice by field
|
||||
func Some(slice, function interface{}) bool //return true if any of the values in the list pass the predicate function, function signature should be func(index int, value interface{}) bool
|
||||
func StringSlice(slice interface{}) []string //convert value to string slice
|
||||
func Unique(slice interface{}) interface{} //remove duplicate elements in slice
|
||||
func Union(slices ...interface{}) interface{} //Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
|
||||
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //update the slice element at index.
|
||||
func Without(slice interface{}, values ...interface{}) interface{} //creates a slice excluding all given values
|
||||
```
|
||||
|
||||
#### 10. strutil is for processing string
|
||||
|
||||
- Contain functions to precess string
|
||||
- Usage: import "github.com/duke-git/lancet/strutil"
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "Foo-Bar"
|
||||
camelCaseStr := strutil.CamelCase(str)
|
||||
fmt.Println(camelCaseStr) //fooBar
|
||||
}
|
||||
```
|
||||
|
||||
- Function list:
|
||||
|
||||
```go
|
||||
func After(s, char string) string //create substring in source string after position when char first appear
|
||||
func AfterLast(s, char string) string //create substring in source string after position when char last appear
|
||||
func Before(s, char string) string //create substring in source string before position when char first appear
|
||||
func BeforeLast(s, char string) string //create substring in source string before position when char last appear
|
||||
func CamelCase(s string) string //covert string to camelCase string. "foo bar" -> "fooBar"
|
||||
func Capitalize(s string) string //convert the first character of a string to upper case, "fOO" -> "Foo"
|
||||
func IsString(v interface{}) bool //check if the value data type is string or not
|
||||
func KebabCase(s string) string //covert string to kebab-case, "foo_Bar" -> "foo-bar"
|
||||
func LowerFirst(s string) string //convert the first character of string to lower case
|
||||
func PadEnd(source string, size int, padStr string) string //pads string on the right side if it's shorter than size
|
||||
func PadStart(source string, size int, padStr string) string//pads string on the left side if it's shorter than size
|
||||
func ReverseStr(s string) string //return string whose char order is reversed to the given string
|
||||
func SnakeCase(s string) string //covert string to snake_case "fooBar" -> "foo_bar"
|
||||
```
|
||||
|
||||
#### 11. validator is for data validation
|
||||
|
||||
- Contain function for data validation.
|
||||
- Usage: import "github.com/duke-git/lancet/validator".
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "Foo-Bar"
|
||||
isAlpha := validator.IsAlpha(str)
|
||||
fmt.Println(isAlpha) //false
|
||||
}
|
||||
```
|
||||
|
||||
- Function list:
|
||||
|
||||
```go
|
||||
func ContainChinese(s string) bool //check if the string contain mandarin chinese
|
||||
func IsAlpha(s string) bool //checks if the string contains only letters (a-zA-Z)
|
||||
func IsBase64(base64 string) bool //check if the string is base64 string
|
||||
func IsChineseMobile(mobileNum string) bool //check if the string is chinese mobile number
|
||||
func IsChineseIdNum(id string) bool //check if the string is chinese id number
|
||||
func IsChinesePhone(phone string) bool //check if the string is chinese phone number
|
||||
func IsCreditCard(creditCart string) bool //check if the string is credit card
|
||||
func IsDns(dns string) bool //check if the string is dns
|
||||
func IsEmail(email string) bool //check if the string is a email address
|
||||
func IsEmptyString(s string) bool //check if the string is empty
|
||||
func IsFloatStr(s string) bool //check if the string can convert to a float
|
||||
func IsNumberStr(s string) bool //check if the string can convert to a number
|
||||
func IsRegexMatch(s, regex string) bool //check if the string match the regexp
|
||||
func IsIntStr(s string) bool //check if the string can convert to a integer
|
||||
func IsIp(ipstr string) bool //check if the string is a ip address
|
||||
func IsIpV4(ipstr string) bool //check if the string is a ipv4 address
|
||||
func IsIpV6(ipstr string) bool //check if the string is a ipv6 address
|
||||
func IsStrongPassword(password string, length int) bool //check if the string is strong password (alpha(lower+upper) + number + special chars(!@#$%^&*()?><))
|
||||
func IsWeakPassword(password string) bool //check if the string is weak password(only letter or only number or letter + number)
|
||||
```
|
||||
1. Fork the repository.
|
||||
2. Create your feature branch.
|
||||
3. Commit your changes.
|
||||
4. Push to the branch
|
||||
5. Create new pull request.
|
||||
|
||||
702
README_zh-CN.md
702
README_zh-CN.md
@@ -1,45 +1,54 @@
|
||||
<div align="center">
|
||||
<h1 style="width: 100%; text-align: center;">Lancet</h1>
|
||||
<p style="font-size: 18px">
|
||||
lancet(柳叶刀)是一个全面、高效、可复用的go语言工具函数库。 lancet受到了java apache common包和lodash.js的启发。
|
||||
</p>
|
||||
<div align="center" style="text-align: center;">
|
||||
<div align=center>
|
||||
<img src="./logo.png" width="200" height="200"/>
|
||||
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
[](https://codecov.io/gh/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||
|
||||
</div>
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
<p style="font-size: 18px">
|
||||
lancet(柳叶刀)是一个全面、高效、可复用的go语言工具函数库。 lancet受到了java apache common包和lodash.js的启发。
|
||||
</p>
|
||||
|
||||
简体中文 | [English](./README.md)
|
||||
|
||||
</div>
|
||||
|
||||
### 特性
|
||||
## 特性
|
||||
|
||||
- 👏 全面、高效、可复用
|
||||
- 💪 100+常用go工具函数,支持string、slice、datetime、net、crypt...
|
||||
- 💪 250+常用go工具函数,支持string、slice、datetime、net、crypt...
|
||||
- 💅 只依赖go标准库
|
||||
- 🌍 所有导出函数单元测试覆盖率100%
|
||||
|
||||
### 安装
|
||||
## 安装
|
||||
### Note:
|
||||
1. <b>对于使用go1.18及以上的用户,建议安装v2.x.x。 因为v2.x.x用go1.18的泛型重写了大部分函数。</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet
|
||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||
```
|
||||
|
||||
### 用法
|
||||
2. <b>使用go1.18以下版本的用户,必须安装v1.x.x。目前最新的v1版本是v1.2.7。</b>
|
||||
```go
|
||||
go get github.com/duke-git/lancet@v1.2.7 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||
```
|
||||
|
||||
## 用法
|
||||
|
||||
lancet是以包的结构组织代码的,使用时需要导入相应的包名。例如:如果使用字符串相关函数,需要导入strutil包:
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/strutil"
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
```
|
||||
|
||||
### 例子
|
||||
## 例子
|
||||
|
||||
此处以字符串工具函数ReverseStr(逆序字符串)为例,需要导入strutil包:
|
||||
|
||||
@@ -48,7 +57,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/strutil"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -58,436 +67,365 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### API文档
|
||||
## API文档
|
||||
|
||||
#### 1. convertor数据转换包
|
||||
|
||||
- 转换函数支持常用数据类型之间的转换
|
||||
- 导入包:import "github.com/duke-git/lancet/convertor"
|
||||
### algorithm算法包实现一些基本算法。eg. sort, search.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := "12.3"
|
||||
f, err := convertor.ToFloat(s)
|
||||
if err != nil {
|
||||
fmt.Errorf("error is %s", err.Error())
|
||||
}
|
||||
fmt.Println(f) // 12.3
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/algorithm"
|
||||
```
|
||||
#### Function list:
|
||||
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)
|
||||
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#CountSort)
|
||||
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#HeapSort)
|
||||
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#InsertionSort)
|
||||
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#MergeSort)
|
||||
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#QuickSort)
|
||||
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#SelectionSort)
|
||||
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#ShellSort)
|
||||
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinarySearch)
|
||||
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinaryIterativeSearch)
|
||||
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LinearSearch)
|
||||
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)
|
||||
|
||||
- 函数列表:
|
||||
### convertor转换器包支持一些常见的数据类型转换。
|
||||
|
||||
```go
|
||||
func ColorHexToRGB(colorHex string) (red, green, blue int) //颜色值16进制转rgb
|
||||
func ColorRGBToHex(red, green, blue int) string //颜色值rgb转16进制
|
||||
func ToBool(s string) (bool, error) //字符串转成Bool
|
||||
func ToBytes(data interface{}) ([]byte, error) //interface转成byte slice
|
||||
func ToChar(s string) []string //字符串转成字符slice
|
||||
func ToFloat(value interface{}) (float64, error) //interface转成float64
|
||||
func ToInt(value interface{}) (int64, error) //interface转成int64
|
||||
func ToJson(value interface{}) (string, error) //interface转成json string
|
||||
func ToString(value interface{}) string //interface转成string
|
||||
func StructToMap(value interface{}) (map[string]interface{}, error) //struct串转成map, 需要设置struct tag `json`
|
||||
import "github.com/duke-git/lancet/v2/convertor"
|
||||
```
|
||||
|
||||
#### 2. cryptor加解密包
|
||||
|
||||
- 加密函数支持md5, hmac, aes, des, ras
|
||||
- 导入包:import "github.com/duke-git/lancet/cryptor"
|
||||
#### 函数列表:
|
||||
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorHexToRGB)
|
||||
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorRGBToHex)
|
||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBool)
|
||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBytes)
|
||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChar)
|
||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInt)
|
||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToJson)
|
||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString)
|
||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap)
|
||||
|
||||
### cryptor加密包支持数据加密和解密,获取md5,hash值。支持base64, md5, hmac, aes, des, rsa。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) // hello
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/cryptor"
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
#### 函数列表:
|
||||
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt)
|
||||
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt)
|
||||
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt)
|
||||
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode)
|
||||
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode)
|
||||
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt)
|
||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)
|
||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)
|
||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)
|
||||
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)
|
||||
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)
|
||||
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)
|
||||
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)
|
||||
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)
|
||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)
|
||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)
|
||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)
|
||||
|
||||
### datetime日期时间处理包,格式化日期,比较日期。
|
||||
|
||||
|
||||
```go
|
||||
func AesEcbEncrypt(data, key []byte) []byte //AES ECB模式加密
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte //AES ECB模式解密
|
||||
func AesCbcEncrypt(data, key []byte) []byte //AES CBC模式加密
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte //AES CBC模式解密
|
||||
func AesCtrCrypt(data, key []byte) []byte //AES CTR模式加密/解密
|
||||
func AesCfbEncrypt(data, key []byte) []byte //AES CFB模式加密
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte //AES CFB模式解密
|
||||
func AesOfbEncrypt(data, key []byte) []byte //AES OFB模式加密
|
||||
func AesOfbDecrypt(data, key []byte) []byte //AES OFB模式解密
|
||||
func Base64StdEncode(s string) string //base64编码
|
||||
func Base64StdDecode(s string) string //base64解码
|
||||
func DesCbcEncrypt(data, key []byte) []byte //DES CBC模式加密
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte //DES CBC模式解密
|
||||
func DesCtrCrypt(data, key []byte) []byte //DES CTR模式加密/解密
|
||||
func DesCfbEncrypt(data, key []byte) []byte //DES CFB模式加密
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte //DES CFB模式解密
|
||||
func DesOfbEncrypt(data, key []byte) []byte //DES OFB模式加密
|
||||
func DesOfbDecrypt(data, key []byte) []byte //DES OFB模式解密
|
||||
func HmacMd5(data, key string) string //获取hmac md5值
|
||||
func HmacSha1(data, key string) string //获取hmac sha1值
|
||||
func HmacSha256(data, key string) string //获取hmac sha256值
|
||||
func HmacSha512(data, key string) string //获取hmac sha512值
|
||||
func Sha1(data string) string //获取sha1值
|
||||
func Sha256(data string) string //获取sha256值
|
||||
func Sha512(data string) string //获取sha512值
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) //生成RSA私钥文件
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte //RSA加密
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte //RSA解密
|
||||
|
||||
import "github.com/duke-git/lancet/v2/datetime"
|
||||
```
|
||||
#### 函数列表:
|
||||
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay)
|
||||
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddHour)
|
||||
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)
|
||||
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)
|
||||
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)
|
||||
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)
|
||||
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
|
||||
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
|
||||
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
|
||||
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
|
||||
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
|
||||
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
|
||||
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
|
||||
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
|
||||
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
|
||||
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDate)
|
||||
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowTime)
|
||||
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime)
|
||||
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetZeroHourTimestamp)
|
||||
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)
|
||||
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)
|
||||
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)
|
||||
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)
|
||||
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)
|
||||
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)
|
||||
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)
|
||||
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)
|
||||
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)
|
||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)
|
||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)
|
||||
|
||||
#### 3. datetime日期时间处理包
|
||||
|
||||
- 处理日期时间
|
||||
- 导入包:import "github.com/duke-git/lancet/datetime"
|
||||
### fileutil包支持文件基本操作。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
s := datetime.FormatTimeToStr(now, "yyyy-mm-dd hh:mm:ss")
|
||||
fmt.Println(s) // 2021-11-24 11:16:55
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
#### 函数列表:
|
||||
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)
|
||||
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsExist)
|
||||
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsLink)
|
||||
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsDir)
|
||||
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ListFileNames)
|
||||
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#RemoveFile)
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
|
||||
|
||||
### formatter格式化器包含一些数据格式化处理方法。
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time //加减天数
|
||||
func AddHour(t time.Time, hour int64) time.Time //加减小时数
|
||||
func AddMinute(t time.Time, minute int64) time.Time //加减分钟数
|
||||
func GetNowDate() string //获取当天日期 格式yyyy-mm-dd
|
||||
func GetNowTime() string //获取当前时间 格式hh:mm:ss
|
||||
func GetNowDateTime() string //获取当前日期时间 格式yyyy-mm-dd hh:mm:ss
|
||||
func GetZeroHourTimestamp() int64 //获取当天零时时间戳(00:00)
|
||||
func GetNightTimestamp() int64 //获取当天23时时间戳(23:59)
|
||||
func FormatTimeToStr(t time.Time, format string) string //时间格式化字符串
|
||||
func FormatStrToTime(str, format string) time.Time //字符串转换成时间
|
||||
import "github.com/duke-git/lancet/v2/formatter"
|
||||
```
|
||||
#### 函数列表:
|
||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
|
||||
|
||||
#### 4. fileutil文件处理包
|
||||
|
||||
- 文件处理常用函数
|
||||
- 导入包:import "github.com/duke-git/lancet/fileutil"
|
||||
### function函数包控制函数执行流程,包含部分函数式编程。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(fileutil.IsDir("./")) // true
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/function"
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
#### 函数列表:
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#After)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Before)
|
||||
- [Curry](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Curry)
|
||||
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Compose)
|
||||
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Debounced)
|
||||
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
|
||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
|
||||
|
||||
### mathutil包实现了一些数学计算的函数。
|
||||
|
||||
```go
|
||||
func ClearFile(path string) error //清空文件内容
|
||||
func IsExist(path string) bool //判断文件/目录是否存在
|
||||
func CreateFile(path string) bool //创建文件
|
||||
func IsDir(path string) bool //判断是否为目录
|
||||
func RemoveFile(path string) error //删除文件
|
||||
func CopyFile(srcFilePath string, dstFilePath string) error //复制文件
|
||||
func ListFileNames(path string) ([]string, error) //列出目录下所有文件名称
|
||||
func ReadFileToString(path string) (string, error) //读取文件内容为字符串
|
||||
func ReadFileByLine(path string)([]string, error) //按行读取文件内容
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
```
|
||||
|
||||
#### 5. formatter格式化处理包
|
||||
#### Function list:
|
||||
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)
|
||||
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)
|
||||
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)
|
||||
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)
|
||||
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Max)
|
||||
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Min)
|
||||
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)
|
||||
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)
|
||||
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
|
||||
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)
|
||||
|
||||
- 格式化相关处理函数
|
||||
- 导入包:import "github.com/duke-git/lancet/formatter"
|
||||
### netutil网络包支持获取ip地址,发送http请求。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(formatter.Comma("12345", "")) // "12,345"
|
||||
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/netutil"
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
#### 函数列表:
|
||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)
|
||||
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)
|
||||
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
||||
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
||||
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)
|
||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)
|
||||
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
|
||||
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
|
||||
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
|
||||
- [HttpPut](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)
|
||||
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)
|
||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)
|
||||
|
||||
### random随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
|
||||
```go
|
||||
func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
```
|
||||
|
||||
#### 6. function包可以控制函数执行,支持部分函数式编程
|
||||
|
||||
- 控制函数执行,支持部分函数式编程
|
||||
- 导入包:import "github.com/duke-git/lancet/function"
|
||||
#### 函数列表:
|
||||
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
### retry重试执行函数直到函数运行成功或被context cancel。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var print = func(s string) {
|
||||
fmt.Println(s)
|
||||
}
|
||||
function.Delay(2*time.Second, print, "hello world")
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/retry"
|
||||
```
|
||||
|
||||
- Function list:
|
||||
#### 函数列表:
|
||||
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context)
|
||||
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry)
|
||||
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc)
|
||||
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryDuration)
|
||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)
|
||||
|
||||
|
||||
### slice包包含操作切片的方法集合。
|
||||
|
||||
```go
|
||||
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value //创建一个函数, 只有在运行了n次之后才有效果
|
||||
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value //创建一个函数,调用不超过n次。 当n已经达到时,最后一个函数调用的结果将被记住并返回
|
||||
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //函数柯里化
|
||||
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} //从右至左组合函数
|
||||
func Delay(delay time.Duration, fn interface{}, args ...interface{}) //延迟调用函数
|
||||
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool //每隔duration时间调用函数, 关闭返回通道可以停止调用
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
```
|
||||
|
||||
#### 7. netutil网络处理包
|
||||
#### 函数列表:
|
||||
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)
|
||||
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)
|
||||
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)
|
||||
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)
|
||||
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)
|
||||
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)
|
||||
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)
|
||||
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)
|
||||
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
||||
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)
|
||||
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)
|
||||
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
|
||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)
|
||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)
|
||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)
|
||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)
|
||||
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
|
||||
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)
|
||||
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)
|
||||
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertAt)
|
||||
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)
|
||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)
|
||||
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)
|
||||
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)
|
||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
|
||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
|
||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)
|
||||
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)
|
||||
|
||||
- 处理ip, http请求相关函数
|
||||
- 导入包:import "github.com/duke-git/lancet/netutil"
|
||||
- http方法params参数顺序:header, query string, body, httpclient
|
||||
|
||||
### strutil包含处理字符串的相关函数。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://gutendex.com/books?"
|
||||
header := make(map[string]string)
|
||||
header["Content-Type"] = "application/json"
|
||||
queryParams := make(map[string]interface{})
|
||||
queryParams["ids"] = "1"
|
||||
|
||||
resp, err := netutil.HttpGet(url, header, queryParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
#### 函数列表:
|
||||
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#After)
|
||||
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#AfterLast)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Before)
|
||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BeforeLast)
|
||||
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#CamelCase)
|
||||
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)
|
||||
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)
|
||||
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)
|
||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)
|
||||
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)
|
||||
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)
|
||||
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
|
||||
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReverseStr)
|
||||
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
|
||||
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
|
||||
|
||||
|
||||
### system包含os, runtime, shell command相关函数。
|
||||
|
||||
```go
|
||||
func GetInternalIp() string //获取内部ip
|
||||
func GetPublicIpInfo() (*PublicIpInfo, error) //获取公共ip信息: country, region, isp, city, lat, lon, ip
|
||||
func IsPublicIP(IP net.IP) bool //判断ip是否为公共ip
|
||||
func HttpGet(url string, params ...interface{}) (*http.Response, error) //http get请求
|
||||
func HttpPost(url string, params ...interface{}) (*http.Response, error) //http post请求
|
||||
func HttpPut(url string, params ...interface{}) (*http.Response, error) //http put请求
|
||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete请求
|
||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch请求
|
||||
func ConvertMapToQueryString(param map[string]interface{}) string //将map转换成url query string
|
||||
func ParseHttpResponse(resp *http.Response, obj interface{}) error //将http响应解码成特定interface
|
||||
import "github.com/duke-git/lancet/v2/system"
|
||||
```
|
||||
|
||||
#### 8. random随机数处理包
|
||||
#### 函数列表:
|
||||
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#IsWindows)
|
||||
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#IsLinux)
|
||||
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#IsMac)
|
||||
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#GetOsEnv)
|
||||
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#SetOsEnv)
|
||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#RemoveOsEnv)
|
||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#CompareOsEnv)
|
||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#ExecCommand)
|
||||
|
||||
- 生成和处理随机数
|
||||
- 导入包:import "github.com/duke-git/lancet/random"
|
||||
### validator验证器包,包含常用字符串格式验证函数。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr)
|
||||
}
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
```
|
||||
#### 函数列表:
|
||||
|
||||
- 函数列表:
|
||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainChinese)
|
||||
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLetter)
|
||||
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLower)
|
||||
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainUpper)
|
||||
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAlpha)
|
||||
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllUpper)
|
||||
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)
|
||||
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)
|
||||
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseMobile)
|
||||
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseIdNum)
|
||||
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChinesePhone)
|
||||
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)
|
||||
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)
|
||||
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmail)
|
||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)
|
||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloatStr)
|
||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)
|
||||
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)
|
||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)
|
||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)
|
||||
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)
|
||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)
|
||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
|
||||
|
||||
validator.md#IsWeakPassword)
|
||||
### xerror包实现一些错误处理函数
|
||||
|
||||
```go
|
||||
func RandBytes(length int) []byte //生成随机[]byte
|
||||
func RandInt(min, max int) int //生成随机int
|
||||
func RandString(length int) string //生成随机string
|
||||
import "github.com/duke-git/lancet/v2/xerror"
|
||||
```
|
||||
#### 函数列表:
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)
|
||||
|
||||
#### 9. slice切片操作包
|
||||
## 如何贡献代码
|
||||
|
||||
- 切片操作相关函数
|
||||
- 导入包:import "github.com/duke-git/lancet/slice"
|
||||
- 由于go目前对范型支持不稳定,slice处理函数参数和返回值大部分为interface{}, 待范型特性稳定后,会重构相关函数
|
||||
非常感激任何的代码提交以使lancet的功能越来越强大。创建pull request时请遵守以下规则。
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 4, 3, 4, 6, 7, 3}
|
||||
uniqueNums, _ := slice.IntSlice(slice.Unique(nums))
|
||||
fmt.Println(uniqueNums) //[1 4 3 6 7]
|
||||
}
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
|
||||
```go
|
||||
func Contain(slice interface{}, value interface{}) bool //判断slice是否包含value
|
||||
func Chunk(slice []interface{}, size int) [][]interface{} //均分slice
|
||||
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //将originalSlice转换为 newSliceType
|
||||
func Difference(slice1, slice2 interface{}) interface{} //返回
|
||||
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //删除切片中start到end位置的值
|
||||
func Every(slice, function interface{}) bool //slice中所有元素都符合函数条件时返回true, 否则返回false. 函数签名:func(index int, value interface{}) bool
|
||||
func Find(slice, function interface{}) interface{} //查找slice中第一个符合条件的元素,函数签名:func(index int, value interface{}) bool
|
||||
func Filter(slice, function interface{}) interface{} //过滤slice, 函数签名:func(index int, value interface{}) bool
|
||||
func IntSlice(slice interface{}) ([]int, error) //转成int切片
|
||||
func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
|
||||
func Intersection(slices ...interface{}) interface{} //slice交集,去重
|
||||
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置插入value
|
||||
func Map(slice, function interface{}) interface{} //遍历切片, 函数签名:func(index int, value interface{}) interface{}
|
||||
func ReverseSlice(slice interface{}) //反转切片
|
||||
func Reduce(slice, function, zero interface{}) interface{} //切片reduce操作, 函数签名:func(index int, value1, value2 interface{}) interface{}
|
||||
func Some(slice, function interface{}) bool //slice中任意一个元素都符合函数条件时返回true, 否则返回false. 函数签名:func(index int, value interface{}) bool
|
||||
func SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序
|
||||
func StringSlice(slice interface{}) []string //转为string切片
|
||||
func Unique(slice interface{}) interface{} //去重切片
|
||||
func Union(slices ...interface{}) interface{} //slice并集, 去重
|
||||
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置更新value
|
||||
func Without(slice interface{}, values ...interface{}) interface{} //slice去除values
|
||||
```
|
||||
|
||||
#### 10. strutil字符串处理包
|
||||
|
||||
- 字符串操作相关函数
|
||||
- 导入包:import "github.com/duke-git/lancet/strutil"
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "Foo-Bar"
|
||||
camelCaseStr := strutil.CamelCase(str)
|
||||
fmt.Println(camelCaseStr) //fooBar
|
||||
}
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
|
||||
```go
|
||||
func After(s, char string) string //截取字符串中char第一次出现之后的字符串
|
||||
func AfterLast(s, char string) string //截取字符串中char最后一次出现之后的字符串
|
||||
func Before(s, char string) string //截取字符串中char第一次出现之前的字符串
|
||||
func BeforeLast(s, char string) string //截取字符串中char最后一次出现之前的字符串
|
||||
func CamelCase(s string) string //字符串转为cameCase, "foo bar" -> "fooBar"
|
||||
func Capitalize(s string) string //字符串转为Capitalize, "fOO" -> "Foo"
|
||||
func IsString(v interface{}) bool //判断是否是字符串
|
||||
func KebabCase(s string) string //字符串转为KebabCase, "foo_Bar" -> "foo-bar"
|
||||
func LowerFirst(s string) string //字符串的第一个字母转为小写字母
|
||||
func PadEnd(source string, size int, padStr string) string //字符串末尾填充size个字符
|
||||
func PadStart(source string, size int, padStr string) string//字符串开头填充size个字符
|
||||
func ReverseStr(s string) string //字符串逆袭
|
||||
func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar"
|
||||
```
|
||||
|
||||
#### 11. validator验证器包
|
||||
|
||||
- 数据校验相关函数
|
||||
- 导入包:import "github.com/duke-git/lancet/validator"
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "Foo-Bar"
|
||||
isAlpha := validator.IsAlpha(str)
|
||||
fmt.Println(isAlpha) //false
|
||||
}
|
||||
```
|
||||
|
||||
- 函数列表:
|
||||
|
||||
```go
|
||||
func ContainChinese(s string) bool //判断字符串中是否含有中文字符
|
||||
func IsAlpha(s string) bool //判断字符串是否只含有字母
|
||||
func IsBase64(base64 string) bool //判断字符串是base64
|
||||
func IsChineseMobile(mobileNum string) bool //判断字符串是否是手机号
|
||||
func IsChineseIdNum(id string) bool //判断字符串是否是身份证号
|
||||
func IsChinesePhone(phone string) bool //判断字符串是否是座机电话号码
|
||||
func IsCreditCard(creditCart string) bool //判断字符串是否是信用卡
|
||||
func IsDns(dns string) bool //判断字符串是否是DNS
|
||||
func IsEmail(email string) bool //判断字符串是否是邮箱
|
||||
func IsEmptyString(s string) bool //判断字符串是否为空
|
||||
func IsFloatStr(s string) bool //判断字符串是否可以转成float
|
||||
func IsNumberStr(s string) bool //判断字符串是否可以转成数字
|
||||
func IsRegexMatch(s, regex string) bool //判断字符串是否match正则表达式
|
||||
func IsIntStr(s string) bool //判断字符串是否可以转成整数
|
||||
func IsIp(ipstr string) bool //判断字符串是否是ip
|
||||
func IsIpV4(ipstr string) bool //判断字符串是否是ipv4
|
||||
func IsIpV6(ipstr string) bool //判断字符串是否是ipv6
|
||||
func IsStrongPassword(password string, length int) bool //判断字符串是否是强密码(大小写字母+数字+特殊字符)
|
||||
func IsWeakPassword(password string) bool //判断字符串是否是弱密码(只有字母或数字)
|
||||
```
|
||||
1. Fork lancet仓库。
|
||||
2. 创建自己的特性分支。
|
||||
3. 提交变更。
|
||||
4. Push分支。
|
||||
5. 创建新的pull request。
|
||||
|
||||
102
algorithm/lru_cache.go
Normal file
102
algorithm/lru_cache.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package algorithm
|
||||
|
||||
type lruNode[K comparable, V any] struct {
|
||||
key K
|
||||
value V
|
||||
pre *lruNode[K, V]
|
||||
next *lruNode[K, V]
|
||||
}
|
||||
|
||||
// newLruNode return a lruNode pointer
|
||||
func newLruNode[K comparable, V any](key K, value V) *lruNode[K, V] {
|
||||
return &lruNode[K, V]{
|
||||
key: key,
|
||||
value: value,
|
||||
pre: nil,
|
||||
next: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// LRUCache lru cache (thread unsafe)
|
||||
type LRUCache[K comparable, V any] struct {
|
||||
cache map[K]*lruNode[K, V]
|
||||
head *lruNode[K, V]
|
||||
tail *lruNode[K, V]
|
||||
capacity int
|
||||
length int
|
||||
}
|
||||
|
||||
// NewLRUCache return a LRUCache pointer
|
||||
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
|
||||
return &LRUCache[K, V]{
|
||||
cache: make(map[K]*lruNode[K, V], capacity),
|
||||
head: nil,
|
||||
tail: nil,
|
||||
capacity: capacity,
|
||||
length: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Get value of key from lru cache
|
||||
func (l *LRUCache[K, V]) Get(key K) (V, bool) {
|
||||
var value V
|
||||
|
||||
node, ok := l.cache[key]
|
||||
if ok {
|
||||
l.moveToHead(node)
|
||||
return node.value, true
|
||||
}
|
||||
|
||||
return value, false
|
||||
}
|
||||
|
||||
// Put value of key into lru cache
|
||||
func (l *LRUCache[K, V]) Put(key K, value V) {
|
||||
node, ok := l.cache[key]
|
||||
if !ok {
|
||||
newNode := newLruNode(key, value)
|
||||
l.cache[key] = newNode
|
||||
l.addNode(newNode)
|
||||
|
||||
if len(l.cache) > l.capacity {
|
||||
oldKey := l.deleteNode(l.head)
|
||||
delete(l.cache, oldKey)
|
||||
}
|
||||
} else {
|
||||
node.value = value
|
||||
l.moveToHead(node)
|
||||
}
|
||||
l.length = len(l.cache)
|
||||
}
|
||||
|
||||
func (l *LRUCache[K, V]) addNode(node *lruNode[K, V]) {
|
||||
if l.tail != nil {
|
||||
l.tail.next = node
|
||||
node.pre = l.tail
|
||||
node.next = nil
|
||||
}
|
||||
l.tail = node
|
||||
if l.head == nil {
|
||||
l.head = node
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) K {
|
||||
if node == l.tail {
|
||||
l.tail = l.tail.pre
|
||||
} else if node == l.head {
|
||||
l.head = l.head.next
|
||||
} else {
|
||||
node.pre.next = node.next
|
||||
node.next.pre = node.pre
|
||||
}
|
||||
return node.key
|
||||
}
|
||||
|
||||
func (l *LRUCache[K, V]) moveToHead(node *lruNode[K, V]) {
|
||||
if l.tail == node {
|
||||
return
|
||||
}
|
||||
l.deleteNode(node)
|
||||
l.addNode(node)
|
||||
}
|
||||
36
algorithm/lru_cache_test.go
Normal file
36
algorithm/lru_cache_test.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package algorithm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestLRUCache(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestLRUCache")
|
||||
|
||||
cache := NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0)
|
||||
asssert.Equal(false, ok)
|
||||
|
||||
v, ok := cache.Get(1)
|
||||
asssert.Equal(true, ok)
|
||||
asssert.Equal(1, v)
|
||||
|
||||
v, ok = cache.Get(2)
|
||||
asssert.Equal(true, ok)
|
||||
asssert.Equal(2, v)
|
||||
|
||||
cache.Put(3, 3)
|
||||
v, ok = cache.Get(1)
|
||||
asssert.Equal(false, ok)
|
||||
asssert.NotEqual(1, v)
|
||||
|
||||
v, ok = cache.Get(3)
|
||||
asssert.Equal(true, ok)
|
||||
asssert.Equal(3, v)
|
||||
}
|
||||
63
algorithm/search.go
Normal file
63
algorithm/search.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph. TODO
|
||||
package algorithm
|
||||
|
||||
import "github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
|
||||
// Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search
|
||||
|
||||
// LinearSearch Simple linear search algorithm that iterates over all elements of an slice
|
||||
// If a target is found, the index of the target is returned. Else the function return -1
|
||||
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int {
|
||||
for i, v := range slice {
|
||||
if comparator.Compare(v, target) == 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// BinarySearch search for target within a sorted slice, recursive call itself.
|
||||
// If a target is found, the index of the target is returned. Else the function return -1
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
|
||||
if highIndex < lowIndex || len(sortedSlice) == 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
midIndex := int(lowIndex + (highIndex-lowIndex)/2)
|
||||
isMidValGreatTarget := comparator.Compare(sortedSlice[midIndex], target) == 1
|
||||
isMidValLessTarget := comparator.Compare(sortedSlice[midIndex], target) == -1
|
||||
|
||||
if isMidValGreatTarget {
|
||||
return BinarySearch(sortedSlice, target, lowIndex, midIndex-1, comparator)
|
||||
} else if isMidValLessTarget {
|
||||
return BinarySearch(sortedSlice, target, midIndex+1, highIndex, comparator)
|
||||
}
|
||||
|
||||
return midIndex
|
||||
}
|
||||
|
||||
// BinaryIterativeSearch search for target within a sorted slice.
|
||||
// If a target is found, the index of the target is returned. Else the function return -1
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
|
||||
startIndex := lowIndex
|
||||
endIndex := highIndex
|
||||
|
||||
var midIndex int
|
||||
for startIndex <= endIndex {
|
||||
midIndex = int(startIndex + (endIndex-startIndex)/2)
|
||||
isMidValGreatTarget := comparator.Compare(sortedSlice[midIndex], target) == 1
|
||||
isMidValLessTarget := comparator.Compare(sortedSlice[midIndex], target) == -1
|
||||
|
||||
if isMidValGreatTarget {
|
||||
endIndex = midIndex - 1
|
||||
} else if isMidValLessTarget {
|
||||
startIndex = midIndex + 1
|
||||
} else {
|
||||
return midIndex
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
33
algorithm/search_test.go
Normal file
33
algorithm/search_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package algorithm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
|
||||
func TestLinearSearch(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestLinearSearch")
|
||||
|
||||
comparator := &intComparator{}
|
||||
asssert.Equal(4, LinearSearch(sortedNumbers, 5, comparator))
|
||||
asssert.Equal(-1, LinearSearch(sortedNumbers, 9, comparator))
|
||||
}
|
||||
|
||||
func TestBinarySearch(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestBinarySearch")
|
||||
|
||||
comparator := &intComparator{}
|
||||
asssert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
|
||||
asssert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
|
||||
}
|
||||
|
||||
func TestBinaryIterativeSearch(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestBinaryIterativeSearch")
|
||||
|
||||
comparator := &intComparator{}
|
||||
asssert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
|
||||
asssert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
|
||||
}
|
||||
208
algorithm/sorter.go
Normal file
208
algorithm/sorter.go
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package algorithm contain some basic algorithm functions. eg. sort, search
|
||||
package algorithm
|
||||
|
||||
import "github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
|
||||
// BubbleSort use bubble to sort slice.
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
for j := 0; j < len(slice)-1-i; j++ {
|
||||
isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
|
||||
if isCurrGreatThanNext {
|
||||
swap(slice, j, j+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return slice
|
||||
}
|
||||
|
||||
// InsertionSort use insertion to sort slice.
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
size := len(slice)
|
||||
if size <= 1 {
|
||||
return slice
|
||||
}
|
||||
|
||||
for i := 1; i < size; i++ {
|
||||
currentItem := slice[i]
|
||||
preIndex := i - 1
|
||||
preItem := slice[preIndex]
|
||||
|
||||
isPreLessThanCurrent := comparator.Compare(preItem, currentItem) == -1
|
||||
for preIndex >= 0 && isPreLessThanCurrent {
|
||||
slice[preIndex+1] = slice[preIndex]
|
||||
preIndex--
|
||||
}
|
||||
|
||||
slice[preIndex+1] = currentItem
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
||||
// SelectionSort use selection to sort slice.
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
min := i
|
||||
|
||||
for j := i + 1; j < len(slice); j++ {
|
||||
if comparator.Compare(slice[j], slice[min]) == -1 {
|
||||
min = j
|
||||
}
|
||||
}
|
||||
swap(slice, i, min)
|
||||
}
|
||||
return slice
|
||||
}
|
||||
|
||||
// ShellSort shell sort slice.
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
size := len(slice)
|
||||
if size <= 1 {
|
||||
return slice
|
||||
}
|
||||
|
||||
gap := 1
|
||||
for gap < size/3 {
|
||||
gap = 3*gap + 1
|
||||
}
|
||||
|
||||
for gap >= 1 {
|
||||
for i := gap; i < size; i++ {
|
||||
for j := i; j >= gap && comparator.Compare(slice[j], slice[j-gap]) == -1; j -= gap {
|
||||
swap(slice, j, j-gap)
|
||||
}
|
||||
}
|
||||
gap /= 3
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
||||
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1
|
||||
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T {
|
||||
if lowIndex < highIndex {
|
||||
p := partition(slice, lowIndex, highIndex, comparator)
|
||||
QuickSort(slice, lowIndex, p-1, comparator)
|
||||
QuickSort(slice, p+1, highIndex, comparator)
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
||||
// partition split slice into two parts
|
||||
func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
|
||||
p := slice[highIndex]
|
||||
i := lowIndex
|
||||
for j := lowIndex; j < highIndex; j++ {
|
||||
if comparator.Compare(slice[j], p) == -1 { //slice[j] < p
|
||||
swap(slice, i, j)
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
swap(slice, i, highIndex)
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// HeapSort use heap to sort slice
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
size := len(slice)
|
||||
|
||||
for i := size/2 - 1; i >= 0; i-- {
|
||||
sift(slice, i, size-1, comparator)
|
||||
}
|
||||
for j := size - 1; j > 0; j-- {
|
||||
swap(slice, 0, j)
|
||||
sift(slice, 0, j-1, comparator)
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
||||
func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
i := lowIndex
|
||||
j := 2*i + 1
|
||||
|
||||
temp := slice[i]
|
||||
for j <= highIndex {
|
||||
if j < highIndex && comparator.Compare(slice[j], slice[j+1]) == -1 { //slice[j] < slice[j+1]
|
||||
j++
|
||||
}
|
||||
if comparator.Compare(temp, slice[j]) == -1 { //tmp < slice[j]
|
||||
slice[i] = slice[j]
|
||||
i = j
|
||||
j = 2*i + 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
slice[i] = temp
|
||||
}
|
||||
|
||||
// MergeSort merge sorting for slice
|
||||
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T {
|
||||
if lowIndex < highIndex {
|
||||
mid := (lowIndex + highIndex) / 2
|
||||
MergeSort(slice, lowIndex, mid, comparator)
|
||||
MergeSort(slice, mid+1, highIndex, comparator)
|
||||
merge(slice, lowIndex, mid, highIndex, comparator)
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
||||
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
i := lowIndex
|
||||
j := midIndex + 1
|
||||
temp := []T{}
|
||||
|
||||
for i <= midIndex && j <= highIndex {
|
||||
//slice[i] < slice[j]
|
||||
if comparator.Compare(slice[i], slice[j]) == -1 {
|
||||
temp = append(temp, slice[i])
|
||||
i++
|
||||
} else {
|
||||
temp = append(temp, slice[j])
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
if i <= midIndex {
|
||||
temp = append(temp, slice[i:midIndex+1]...)
|
||||
} else {
|
||||
temp = append(temp, slice[j:highIndex+1]...)
|
||||
}
|
||||
|
||||
for k := 0; k < len(temp); k++ {
|
||||
slice[lowIndex+k] = temp[k]
|
||||
}
|
||||
}
|
||||
|
||||
// CountSort use count sorting for slice
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
size := len(slice)
|
||||
out := make([]T, size)
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
count := 0
|
||||
for j := 0; j < size; j++ {
|
||||
//slice[i] > slice[j]
|
||||
if comparator.Compare(slice[i], slice[j]) == 1 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
out[count] = slice[i]
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// swap two slice value at index i and j
|
||||
func swap[T any](slice []T, i, j int) {
|
||||
slice[i], slice[j] = slice[j], slice[i]
|
||||
}
|
||||
177
algorithm/sorter_test.go
Normal file
177
algorithm/sorter_test.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package algorithm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
// People test mock data
|
||||
type people struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
// PeopleAageComparator sort people slice by age field
|
||||
type peopleAgeComparator struct{}
|
||||
|
||||
// Compare implements github.com/duke-git/lancet/v2/lancetconstraints/constraints.go/Comparator
|
||||
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
p1, _ := v1.(people)
|
||||
p2, _ := v2.(people)
|
||||
|
||||
//ascending order
|
||||
if p1.Age < p2.Age {
|
||||
return -1
|
||||
} else if p1.Age > p2.Age {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
|
||||
//decending order
|
||||
// if p1.Age > p2.Age {
|
||||
// return -1
|
||||
// } else if p1.Age < p2.Age {
|
||||
// return 1
|
||||
// }
|
||||
}
|
||||
|
||||
var peoples = []people{
|
||||
{Name: "a", Age: 20},
|
||||
{Name: "b", Age: 10},
|
||||
{Name: "c", Age: 17},
|
||||
{Name: "d", Age: 8},
|
||||
{Name: "e", Age: 28},
|
||||
}
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var intSlice = []int{2, 1, 5, 3, 6, 4}
|
||||
|
||||
func TestBubbleSortForStructSlice(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := BubbleSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBubbleSortForIntSlice(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
|
||||
|
||||
comparator := &intComparator{}
|
||||
sortedInt := BubbleSort(intSlice, comparator)
|
||||
expected := []int{1, 2, 3, 4, 5, 6}
|
||||
|
||||
asssert.Equal(expected, sortedInt)
|
||||
}
|
||||
|
||||
func TestInsertionSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestInsertionSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := InsertionSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{e 28} {a 20} {c 17} {b 10} {d 8}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestSelectionSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestSelectionSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := SelectionSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestShellSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestShellSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := ShellSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestQuickSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestQuickSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := QuickSort(peoples, 0, len(peoples)-1, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestHeapSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestHeapSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := HeapSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestMergeSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestMergeSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := MergeSort(peoples, 0, len(peoples)-1, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestCountSort(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestCountSort")
|
||||
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := CountSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
}
|
||||
@@ -6,9 +6,10 @@ package convertor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -21,14 +22,44 @@ func ToBool(s string) (bool, error) {
|
||||
}
|
||||
|
||||
// ToBytes convert interface to bytes
|
||||
func ToBytes(data interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
err := enc.Encode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func ToBytes(value any) ([]byte, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
number := v.Int()
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
buf.Reset()
|
||||
err := binary.Write(buf, binary.BigEndian, number)
|
||||
return buf.Bytes(), err
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
number := v.Uint()
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
buf.Reset()
|
||||
err := binary.Write(buf, binary.BigEndian, number)
|
||||
return buf.Bytes(), err
|
||||
case float32:
|
||||
number := float32(v.Float())
|
||||
bits := math.Float32bits(number)
|
||||
bytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(bytes, bits)
|
||||
return bytes, nil
|
||||
case float64:
|
||||
number := v.Float()
|
||||
bits := math.Float64bits(number)
|
||||
bytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(bytes, bits)
|
||||
return bytes, nil
|
||||
case bool:
|
||||
return strconv.AppendBool([]byte{}, v.Bool()), nil
|
||||
case string:
|
||||
return []byte(v.String()), nil
|
||||
case []byte:
|
||||
return v.Bytes(), nil
|
||||
default:
|
||||
newValue, err := json.Marshal(value)
|
||||
return newValue, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// ToChar convert string to char slice
|
||||
@@ -44,59 +75,49 @@ func ToChar(s string) []string {
|
||||
}
|
||||
|
||||
// ToString convert value to string
|
||||
func ToString(value interface{}) string {
|
||||
var res string
|
||||
func ToString(value any) string {
|
||||
res := ""
|
||||
if value == nil {
|
||||
return res
|
||||
}
|
||||
switch v := value.(type) {
|
||||
case float64:
|
||||
res = strconv.FormatFloat(v, 'f', -1, 64)
|
||||
case float32:
|
||||
res = strconv.FormatFloat(float64(v), 'f', -1, 64)
|
||||
case int:
|
||||
res = strconv.Itoa(v)
|
||||
case uint:
|
||||
res = strconv.Itoa(int(v))
|
||||
case int8:
|
||||
res = strconv.Itoa(int(v))
|
||||
case uint8:
|
||||
res = strconv.Itoa(int(v))
|
||||
case int16:
|
||||
res = strconv.Itoa(int(v))
|
||||
case uint16:
|
||||
res = strconv.Itoa(int(v))
|
||||
case int32:
|
||||
res = strconv.Itoa(int(v))
|
||||
case uint32:
|
||||
res = strconv.Itoa(int(v))
|
||||
case int64:
|
||||
res = strconv.FormatInt(v, 10)
|
||||
case uint64:
|
||||
res = strconv.FormatUint(v, 10)
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch value.(type) {
|
||||
case float32, float64:
|
||||
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
return res
|
||||
case int, int8, int16, int32, int64:
|
||||
res = strconv.FormatInt(v.Int(), 10)
|
||||
return res
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = strconv.FormatUint(v.Uint(), 10)
|
||||
return res
|
||||
case string:
|
||||
res = value.(string)
|
||||
res = v.String()
|
||||
return res
|
||||
case []byte:
|
||||
res = string(value.([]byte))
|
||||
res = string(v.Bytes())
|
||||
return res
|
||||
default:
|
||||
newValue, _ := json.Marshal(value)
|
||||
res = string(newValue)
|
||||
return res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ToJson convert value to a valid json string
|
||||
func ToJson(value interface{}) (string, error) {
|
||||
func ToJson(value any) (string, error) {
|
||||
res, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
res = []byte("")
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(res), err
|
||||
return string(res), nil
|
||||
}
|
||||
|
||||
// ToFloat convert value to a float64, if input is not a float return 0.0 and error
|
||||
func ToFloat(value interface{}) (float64, error) {
|
||||
func ToFloat(value any) (float64, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
res := 0.0
|
||||
@@ -123,7 +144,7 @@ func ToFloat(value interface{}) (float64, error) {
|
||||
}
|
||||
|
||||
// ToInt convert value to a int64, if input is not a numeric format return 0 and error
|
||||
func ToInt(value interface{}) (int64, error) {
|
||||
func ToInt(value any) (int64, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
var res int64
|
||||
@@ -151,7 +172,7 @@ func ToInt(value interface{}) (int64, error) {
|
||||
|
||||
// StructToMap convert struct to map, only convert exported struct field
|
||||
// map key is specified same as struct field tag `json` value
|
||||
func StructToMap(value interface{}) (map[string]interface{}, error) {
|
||||
func StructToMap(value any) (map[string]any, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
t := reflect.TypeOf(value)
|
||||
|
||||
@@ -162,7 +183,7 @@ func StructToMap(value interface{}) (map[string]interface{}, error) {
|
||||
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
|
||||
}
|
||||
|
||||
res := make(map[string]interface{})
|
||||
res := make(map[string]any)
|
||||
|
||||
fieldNum := t.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
|
||||
@@ -2,13 +2,14 @@ package convertor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestToChar(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToChar")
|
||||
|
||||
cases := []string{"", "abc", "1 2#3"}
|
||||
expected := [][]string{
|
||||
{""},
|
||||
@@ -16,50 +17,52 @@ func TestToChar(t *testing.T) {
|
||||
{"1", " ", "2", "#", "3"},
|
||||
}
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res := ToChar(cases[i])
|
||||
if !reflect.DeepEqual(res, expected[i]) {
|
||||
utils.LogFailedTestInfo(t, "ToChar", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(expected[i], ToChar(cases[i]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestToBool(t *testing.T) {
|
||||
cases := []string{"true", "True", "false", "False", "0", "1", "123"}
|
||||
expected := []bool{true, true, false, false, false, true, false}
|
||||
assert := internal.NewAssert(t, "TestToBool")
|
||||
|
||||
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
|
||||
expected := []bool{true, true, true, false, false, false, false, false, false}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res, _ := ToBool(cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "ToBool", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual, _ := ToBool(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToBytes(t *testing.T) {
|
||||
cases := []interface{}{
|
||||
assert := internal.NewAssert(t, "TestToBytes")
|
||||
|
||||
cases := []any{
|
||||
0,
|
||||
false,
|
||||
"1",
|
||||
}
|
||||
expected := [][]byte{
|
||||
{3, 4, 0, 0},
|
||||
{3, 2, 0, 0},
|
||||
{4, 12, 0, 1, 49},
|
||||
{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{102, 97, 108, 115, 101},
|
||||
{49},
|
||||
}
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res, _ := ToBytes(cases[i])
|
||||
fmt.Println(res)
|
||||
if !reflect.DeepEqual(res, expected[i]) {
|
||||
utils.LogFailedTestInfo(t, "ToBytes", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual, _ := ToBytes(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
|
||||
bytesData, err := ToBytes("abc")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fail()
|
||||
}
|
||||
assert.Equal("abc", ToString(bytesData))
|
||||
}
|
||||
|
||||
func TestToInt(t *testing.T) {
|
||||
cases := []interface{}{"123", "-123", 123,
|
||||
assert := internal.NewAssert(t, "TestToInt")
|
||||
|
||||
cases := []any{"123", "-123", 123,
|
||||
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||
float32(12.3), float64(12.3),
|
||||
"abc", false, "111111111111111111111111111111111111111"}
|
||||
@@ -67,16 +70,15 @@ func TestToInt(t *testing.T) {
|
||||
expected := []int64{123, -123, 123, 123, 123, 123, 123, 123, 12, 12, 0, 0, 0}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res, _ := ToInt(cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "ToInt", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual, _ := ToInt(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToFloat(t *testing.T) {
|
||||
cases := []interface{}{
|
||||
assert := internal.NewAssert(t, "TestToFloat")
|
||||
|
||||
cases := []any{
|
||||
"", "-1", "-.11", "1.23e3", ".123e10", "abc",
|
||||
int(0), int8(1), int16(-1), int32(123), int64(123),
|
||||
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||
@@ -86,108 +88,74 @@ func TestToFloat(t *testing.T) {
|
||||
0, 1, -1, 123, 123, 123, 123, 123, 123, 123, 12.3, 12.300000190734863}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res, _ := ToFloat(cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "ToFloat", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual, _ := ToFloat(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
// map
|
||||
assert := internal.NewAssert(t, "TestToString")
|
||||
|
||||
aMap := make(map[string]int)
|
||||
aMap["a"] = 1
|
||||
aMap["b"] = 2
|
||||
aMap["c"] = 3
|
||||
|
||||
// struct
|
||||
type TestStruct struct {
|
||||
Name string
|
||||
}
|
||||
aStruct := TestStruct{Name: "TestStruct"}
|
||||
|
||||
cases := []interface{}{
|
||||
cases := []any{
|
||||
"", nil,
|
||||
int(0), int8(1), int16(-1), int32(123), int64(123),
|
||||
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||
float64(12.3), float32(12.3),
|
||||
true, false,
|
||||
[]int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111}}
|
||||
|
||||
expected := []string{"0", "1", "-1", "123", "123", "123", "123", "123",
|
||||
"123", "123", "12.3", "12.300000190734863", "true", "false",
|
||||
expected := []string{
|
||||
"", "",
|
||||
"0", "1", "-1",
|
||||
"123", "123", "123", "123", "123", "123", "123",
|
||||
"12.3", "12.300000190734863",
|
||||
"true", "false",
|
||||
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello"}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res := ToString(cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "ToString", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual := ToString(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
func TestToJson(t *testing.T) {
|
||||
// map
|
||||
aMap := make(map[string]int)
|
||||
aMap["a"] = 1
|
||||
aMap["b"] = 2
|
||||
aMap["c"] = 3
|
||||
assert := internal.NewAssert(t, "TestToJson")
|
||||
|
||||
mapJson := "{\"a\":1,\"b\":2,\"c\":3}"
|
||||
r1, _ := ToJson(aMap)
|
||||
if r1 != mapJson {
|
||||
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
|
||||
t.FailNow()
|
||||
}
|
||||
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
mapJsonStr, _ := ToJson(aMap)
|
||||
assert.Equal("{\"a\":1,\"b\":2,\"c\":3}", mapJsonStr)
|
||||
|
||||
// struct
|
||||
type TestStruct struct {
|
||||
Name string
|
||||
}
|
||||
aStruct := TestStruct{Name: "TestStruct"}
|
||||
structJson := "{\"Name\":\"TestStruct\"}"
|
||||
r2, _ := ToJson(aStruct)
|
||||
if r2 != structJson {
|
||||
utils.LogFailedTestInfo(t, "ToJson", aMap, mapJson, r1)
|
||||
t.FailNow()
|
||||
}
|
||||
structJsonStr, _ := ToJson(aStruct)
|
||||
assert.Equal("{\"Name\":\"TestStruct\"}", structJsonStr)
|
||||
}
|
||||
|
||||
func TestStructToMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStructToMap")
|
||||
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
age int
|
||||
}
|
||||
|
||||
p1 := People{
|
||||
p := People{
|
||||
"test",
|
||||
100,
|
||||
}
|
||||
|
||||
pm1, _ := StructToMap(p1)
|
||||
m1 := make(map[string]interface{})
|
||||
m1["name"] = "test"
|
||||
//exp1["100"] = 100
|
||||
|
||||
if !reflect.DeepEqual(pm1, m1) {
|
||||
utils.LogFailedTestInfo(t, "StructToMap", p1, m1, pm1)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
p2 := People{
|
||||
"test",
|
||||
100,
|
||||
}
|
||||
|
||||
pm2, _ := StructToMap(p1)
|
||||
m2 := make(map[string]interface{})
|
||||
m2["name"] = "test"
|
||||
m2["100"] = 100
|
||||
|
||||
if reflect.DeepEqual(pm2, m2) {
|
||||
utils.LogFailedTestInfo(t, "StructToMap", p2, m2, pm2)
|
||||
t.FailNow()
|
||||
}
|
||||
pm, _ := StructToMap(p)
|
||||
var expected = map[string]any{"name": "test"}
|
||||
assert.Equal(expected, pm)
|
||||
}
|
||||
|
||||
func TestColorHexToRGB(t *testing.T) {
|
||||
@@ -196,22 +164,17 @@ func TestColorHexToRGB(t *testing.T) {
|
||||
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
|
||||
expected := "0,51,102"
|
||||
|
||||
if colorRGB != expected {
|
||||
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorHex, expected, colorRGB)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestColorHexToRGB")
|
||||
assert.Equal(expected, colorRGB)
|
||||
}
|
||||
|
||||
func TestColorRGBToHex(t *testing.T) {
|
||||
r := 0
|
||||
g := 51
|
||||
b := 102
|
||||
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
|
||||
colorHex := ColorRGBToHex(r, g, b)
|
||||
expected := "#003366"
|
||||
|
||||
if colorHex != expected {
|
||||
utils.LogFailedTestInfo(t, "ColorHexToRGB", colorRGB, expected, colorHex)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestColorRGBToHex")
|
||||
assert.Equal(expected, colorHex)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package cryptor
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestAesEcbEncrypt(t *testing.T) {
|
||||
@@ -13,10 +13,8 @@ func TestAesEcbEncrypt(t *testing.T) {
|
||||
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
|
||||
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
|
||||
|
||||
if string(aesEcbDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "AesEcbEncrypt/AesEcbDecrypt", data, data, string(aesEcbDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
|
||||
assert.Equal(data, string(aesEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCbcEncrypt(t *testing.T) {
|
||||
@@ -26,10 +24,8 @@ func TestAesCbcEncrypt(t *testing.T) {
|
||||
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
|
||||
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
|
||||
|
||||
if string(aesCbcDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "AesCbcEncrypt/AesCbcDecrypt", data, data, string(aesCbcDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
|
||||
assert.Equal(data, string(aesCbcDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCtrCrypt(t *testing.T) {
|
||||
@@ -39,10 +35,8 @@ func TestAesCtrCrypt(t *testing.T) {
|
||||
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
|
||||
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
|
||||
|
||||
if string(aesCtrDeCrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "AesCtrCrypt", data, data, string(aesCtrDeCrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestAesCtrCrypt")
|
||||
assert.Equal(data, string(aesCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestAesCfbEncrypt(t *testing.T) {
|
||||
@@ -52,10 +46,8 @@ func TestAesCfbEncrypt(t *testing.T) {
|
||||
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
|
||||
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
|
||||
|
||||
if string(aesCfbDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "AesCfbEncrypt/AesCfbDecrypt", data, data, string(aesCfbDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
|
||||
assert.Equal(data, string(aesCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesOfbEncrypt(t *testing.T) {
|
||||
@@ -65,8 +57,6 @@ func TestAesOfbEncrypt(t *testing.T) {
|
||||
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
|
||||
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
|
||||
|
||||
if string(aesOfbDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "AesOfbEncrypt/AesOfbDecrypt", data, data, string(aesOfbDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
|
||||
assert.Equal(data, string(aesOfbDecrypt))
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
@@ -13,7 +14,9 @@ import (
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Base64StdEncode encode string with base64 encoding
|
||||
@@ -36,14 +39,34 @@ func Md5String(s string) string {
|
||||
|
||||
// Md5File return the md5 value of file
|
||||
func Md5File(filename string) (string, error) {
|
||||
f, err := ioutil.ReadFile(filename)
|
||||
if fileInfo, err := os.Stat(filename); err != nil {
|
||||
return "", err
|
||||
} else if fileInfo.IsDir() {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
h := md5.New()
|
||||
h.Write(f)
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
hash := md5.New()
|
||||
|
||||
chunkSize := 65536
|
||||
for buf, reader := make([]byte, chunkSize), bufio.NewReader(file); ; {
|
||||
n, err := reader.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
hash.Write(buf[:n])
|
||||
}
|
||||
|
||||
checksum := fmt.Sprintf("%x", hash.Sum(nil))
|
||||
return checksum, nil
|
||||
}
|
||||
|
||||
// HmacMd5 return the hmac hash of string use md5
|
||||
|
||||
@@ -1,66 +1,36 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestBase64StdEncode(t *testing.T) {
|
||||
s := "hello world"
|
||||
bs := Base64StdEncode(s)
|
||||
|
||||
if bs != "aGVsbG8gd29ybGQ=" {
|
||||
utils.LogFailedTestInfo(t, "Base64StdEncode", s, "aGVsbG8gd29ybGQ=", bs)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestBase64StdEncode")
|
||||
assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world"))
|
||||
}
|
||||
|
||||
func TestBase64StdDecode(t *testing.T) {
|
||||
bs := "aGVsbG8gd29ybGQ="
|
||||
s := Base64StdDecode(bs)
|
||||
|
||||
if s != "hello world" {
|
||||
utils.LogFailedTestInfo(t, "Base64StdDecode", bs, "hello world=", s)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestBase64StdDecode")
|
||||
assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ="))
|
||||
}
|
||||
|
||||
func TestMd5String(t *testing.T) {
|
||||
s := "hello"
|
||||
smd5 := Md5String(s)
|
||||
expected := "5d41402abc4b2a76b9719d911017c592"
|
||||
|
||||
if smd5 != expected {
|
||||
utils.LogFailedTestInfo(t, "Md5String", s, expected, smd5)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestMd5String")
|
||||
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
|
||||
}
|
||||
|
||||
func TestMd5File(t *testing.T) {
|
||||
file, _ := os.Create("./hello.txt")
|
||||
defer file.Close()
|
||||
file.WriteString("hello\n")
|
||||
|
||||
fileMd5, err := Md5File("./hello.txt")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
fmt.Println(fileMd5)
|
||||
fileMd5, err := Md5File("./basic.go")
|
||||
assert := internal.NewAssert(t, "TestMd5File")
|
||||
assert.IsNotNil(fileMd5)
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
func TestHmacMd5(t *testing.T) {
|
||||
s := "hello world"
|
||||
key := "12345"
|
||||
hmacMd5 := HmacMd5(s, key)
|
||||
expected := "5f4c9faaff0a1ad3007d9ddc06abe36d"
|
||||
|
||||
if hmacMd5 != expected {
|
||||
utils.LogFailedTestInfo(t, "HmacMd5", s, expected, hmacMd5)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestHmacMd5")
|
||||
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
|
||||
}
|
||||
|
||||
func TestHmacSha1(t *testing.T) {
|
||||
@@ -69,10 +39,8 @@ func TestHmacSha1(t *testing.T) {
|
||||
hmacSha1 := HmacSha1(s, key)
|
||||
expected := "3826f812255d8683f051ee97346d1359234d5dbd"
|
||||
|
||||
if hmacSha1 != expected {
|
||||
utils.LogFailedTestInfo(t, "HmacSha1", s, expected, hmacSha1)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestHmacSha1")
|
||||
assert.Equal(expected, hmacSha1)
|
||||
}
|
||||
|
||||
func TestHmacSha256(t *testing.T) {
|
||||
@@ -81,10 +49,8 @@ func TestHmacSha256(t *testing.T) {
|
||||
hmacSha256 := HmacSha256(s, key)
|
||||
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
|
||||
|
||||
if hmacSha256 != expected {
|
||||
utils.LogFailedTestInfo(t, "HmacSha256", s, expected, hmacSha256)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestHmacSha256")
|
||||
assert.Equal(expected, hmacSha256)
|
||||
}
|
||||
|
||||
func TestHmacSha512(t *testing.T) {
|
||||
@@ -93,10 +59,8 @@ func TestHmacSha512(t *testing.T) {
|
||||
hmacSha512 := HmacSha512(s, key)
|
||||
expected := "5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175"
|
||||
|
||||
if hmacSha512 != expected {
|
||||
utils.LogFailedTestInfo(t, "HmacSha512", s, expected, hmacSha512)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestHmacSha512")
|
||||
assert.Equal(expected, hmacSha512)
|
||||
}
|
||||
|
||||
func TestSha1(t *testing.T) {
|
||||
@@ -104,10 +68,8 @@ func TestSha1(t *testing.T) {
|
||||
sha1 := Sha1(s)
|
||||
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
|
||||
|
||||
if sha1 != expected {
|
||||
utils.LogFailedTestInfo(t, "Sha1", s, expected, sha1)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestSha1")
|
||||
assert.Equal(expected, sha1)
|
||||
}
|
||||
|
||||
func TestSha256(t *testing.T) {
|
||||
@@ -115,10 +77,8 @@ func TestSha256(t *testing.T) {
|
||||
sha256 := Sha256(s)
|
||||
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
||||
|
||||
if sha256 != expected {
|
||||
utils.LogFailedTestInfo(t, "Sha256", s, expected, sha256)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestSha256")
|
||||
assert.Equal(expected, sha256)
|
||||
}
|
||||
|
||||
func TestSha512(t *testing.T) {
|
||||
@@ -126,8 +86,6 @@ func TestSha512(t *testing.T) {
|
||||
sha512 := Sha512(s)
|
||||
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
|
||||
|
||||
if sha512 != expected {
|
||||
utils.LogFailedTestInfo(t, "Sha512", s, expected, sha512)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestSha512")
|
||||
assert.Equal(expected, sha512)
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@ func DesEcbEncrypt(data, key []byte) []byte {
|
||||
length := (len(data) + des.BlockSize) / des.BlockSize
|
||||
plain := make([]byte, length*des.BlockSize)
|
||||
copy(plain, data)
|
||||
|
||||
pad := byte(len(plain) - len(data))
|
||||
for i := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
@@ -36,7 +38,7 @@ func DesEcbEncrypt(data, key []byte) []byte {
|
||||
func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
//
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
@@ -59,6 +61,7 @@ func DesCbcEncrypt(data, key []byte) []byte {
|
||||
|
||||
encrypted := make([]byte, len(data))
|
||||
blockMode.CryptBlocks(encrypted, data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
@@ -72,6 +75,7 @@ func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
blockMode.CryptBlocks(decrypted, encrypted)
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
|
||||
return decrypted
|
||||
}
|
||||
|
||||
@@ -105,6 +109,7 @@ func DesCfbEncrypt(data, key []byte) []byte {
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
@@ -120,6 +125,7 @@ func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
@@ -139,6 +145,7 @@ func DesOfbEncrypt(data, key []byte) []byte {
|
||||
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
@@ -161,6 +168,6 @@ func DesOfbDecrypt(data, key []byte) []byte {
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
return decrypted
|
||||
|
||||
return decrypted
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package cryptor
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestDesEcbEncrypt(t *testing.T) {
|
||||
@@ -13,10 +13,8 @@ func TestDesEcbEncrypt(t *testing.T) {
|
||||
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
|
||||
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
|
||||
|
||||
if string(desEcbDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "DesEcbEncrypt/DesEcbDecrypt", data, data, string(desEcbDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
|
||||
assert.Equal(data, string(desEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCbcEncrypt(t *testing.T) {
|
||||
@@ -26,10 +24,8 @@ func TestDesCbcEncrypt(t *testing.T) {
|
||||
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
|
||||
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
|
||||
|
||||
if string(desCbcDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "DesCbcEncrypt/DesCbcDecrypt", data, data, string(desCbcDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
|
||||
assert.Equal(data, string(desCbcDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCtrCrypt(t *testing.T) {
|
||||
@@ -39,10 +35,8 @@ func TestDesCtrCrypt(t *testing.T) {
|
||||
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
|
||||
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
|
||||
|
||||
if string(desCtrDeCrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "DesCtrCrypt", data, data, string(desCtrDeCrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestDesCtrCrypt")
|
||||
assert.Equal(data, string(desCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestDesCfbEncrypt(t *testing.T) {
|
||||
@@ -52,10 +46,8 @@ func TestDesCfbEncrypt(t *testing.T) {
|
||||
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
|
||||
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
|
||||
|
||||
if string(desCfbDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "DesCfbEncrypt/DesCfbDecrypt", data, data, string(desCfbDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
|
||||
assert.Equal(data, string(desCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesOfbEncrypt(t *testing.T) {
|
||||
@@ -65,8 +57,6 @@ func TestDesOfbEncrypt(t *testing.T) {
|
||||
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
|
||||
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
|
||||
|
||||
if string(desOfbDecrypt) != data {
|
||||
utils.LogFailedTestInfo(t, "DesOfbEncrypt/DesOfbDecrypt", data, data, string(desOfbDecrypt))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
|
||||
assert.Equal(data, string(desOfbDecrypt))
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ import (
|
||||
|
||||
// GenerateRsaKey make a rsa private key, and return key file name
|
||||
// Generated key file is `rsa_private.pem` and `rsa_public.pem` in current path
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) {
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
|
||||
// private key
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
derText := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||
@@ -41,7 +41,7 @@ func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) {
|
||||
|
||||
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
block = pem.Block{
|
||||
@@ -52,10 +52,12 @@ func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) {
|
||||
//file,err = os.Create("rsa_public.pem")
|
||||
file, err = os.Create(pubKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
pem.Encode(file, &block)
|
||||
file.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RsaEncrypt encrypt data with ras algorithm
|
||||
|
||||
@@ -3,17 +3,18 @@ package cryptor
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestRsaEncrypt(t *testing.T) {
|
||||
GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
if string(data) != string(decrypted) {
|
||||
utils.LogFailedTestInfo(t, "RsaEncrypt/RsaDecrypt", string(data), string(data), string(decrypted))
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestRsaEncrypt")
|
||||
assert.Equal(string(data), string(decrypted))
|
||||
}
|
||||
|
||||
241
datastructure/link/doublylink.go
Normal file
241
datastructure/link/doublylink.go
Normal file
@@ -0,0 +1,241 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
)
|
||||
|
||||
// DoublyLink is a linked list. Whose node has a generic Value, Pre pointer points to a previous node of the link, Next pointer points to a next node of the link.
|
||||
type DoublyLink[T any] struct {
|
||||
Head *datastructure.LinkNode[T]
|
||||
length int
|
||||
}
|
||||
|
||||
// NewDoublyLink return *DoublyLink instance
|
||||
func NewDoublyLink[T any]() *DoublyLink[T] {
|
||||
return &DoublyLink[T]{Head: nil}
|
||||
}
|
||||
|
||||
// InsertAtHead insert value into doubly linklist at head index
|
||||
func (link *DoublyLink[T]) InsertAtHead(value T) {
|
||||
newNode := datastructure.NewLinkNode(value)
|
||||
size := link.Size()
|
||||
|
||||
if size == 0 {
|
||||
link.Head = newNode
|
||||
link.length++
|
||||
return
|
||||
}
|
||||
|
||||
newNode.Next = link.Head
|
||||
newNode.Pre = nil
|
||||
|
||||
link.Head.Pre = newNode
|
||||
link.Head = newNode
|
||||
|
||||
link.length++
|
||||
}
|
||||
|
||||
// InsertAtTail insert value into doubly linklist at tail index
|
||||
func (link *DoublyLink[T]) InsertAtTail(value T) {
|
||||
current := link.Head
|
||||
if current == nil {
|
||||
link.InsertAtHead(value)
|
||||
return
|
||||
}
|
||||
|
||||
for current.Next != nil {
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
newNode := datastructure.NewLinkNode(value)
|
||||
newNode.Next = nil
|
||||
newNode.Pre = current
|
||||
current.Next = newNode
|
||||
|
||||
link.length++
|
||||
}
|
||||
|
||||
// InsertAt insert value into doubly linklist at index
|
||||
func (link *DoublyLink[T]) InsertAt(index int, value T) error {
|
||||
size := link.length
|
||||
if index < 0 || index > size {
|
||||
return errors.New("param index should between 0 and the length of doubly link.")
|
||||
}
|
||||
|
||||
if index == 0 {
|
||||
link.InsertAtHead(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
if index == size {
|
||||
link.InsertAtTail(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
i := 0
|
||||
current := link.Head
|
||||
|
||||
for current != nil {
|
||||
if i == index-1 {
|
||||
newNode := datastructure.NewLinkNode(value)
|
||||
newNode.Next = current.Next
|
||||
newNode.Pre = current
|
||||
|
||||
current.Next = newNode
|
||||
link.length++
|
||||
|
||||
return nil
|
||||
}
|
||||
i++
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
return errors.New("doubly link list no exist")
|
||||
}
|
||||
|
||||
// DeleteAtHead delete value in doubly linklist at head index
|
||||
func (link *DoublyLink[T]) DeleteAtHead() error {
|
||||
if link.Head == nil {
|
||||
return errors.New("doubly link list no exist")
|
||||
}
|
||||
current := link.Head
|
||||
link.Head = current.Next
|
||||
link.Head.Pre = nil
|
||||
link.length--
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAtTail delete value in doubly linklist at tail index
|
||||
func (link *DoublyLink[T]) DeleteAtTail() error {
|
||||
if link.Head == nil {
|
||||
return errors.New("doubly link list no exist")
|
||||
}
|
||||
current := link.Head
|
||||
if current.Next == nil {
|
||||
return link.DeleteAtHead()
|
||||
}
|
||||
|
||||
for current.Next.Next != nil {
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
current.Next = nil
|
||||
link.length--
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAt delete value in doubly linklist at index
|
||||
func (link *DoublyLink[T]) DeleteAt(index int) error {
|
||||
if link.Head == nil {
|
||||
return errors.New("doubly link list no exist")
|
||||
}
|
||||
current := link.Head
|
||||
if current.Next == nil || index == 0 {
|
||||
return link.DeleteAtHead()
|
||||
}
|
||||
|
||||
if index == link.length-1 {
|
||||
return link.DeleteAtTail()
|
||||
}
|
||||
|
||||
if index < 0 || index > link.length-1 {
|
||||
return errors.New("param index should between 0 and link size -1.")
|
||||
}
|
||||
|
||||
i := 0
|
||||
for current != nil {
|
||||
if i == index-1 {
|
||||
current.Next = current.Next.Next
|
||||
link.length--
|
||||
return nil
|
||||
}
|
||||
i++
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
return errors.New("delete error")
|
||||
}
|
||||
|
||||
// Reverse the linked list
|
||||
func (link *DoublyLink[T]) Reverse() {
|
||||
current := link.Head
|
||||
var temp *datastructure.LinkNode[T]
|
||||
|
||||
for current != nil {
|
||||
temp = current.Pre
|
||||
current.Pre = current.Next
|
||||
current.Next = temp
|
||||
current = current.Pre
|
||||
}
|
||||
|
||||
if temp != nil {
|
||||
link.Head = temp.Pre
|
||||
}
|
||||
}
|
||||
|
||||
// GetMiddleNode return node at middle index of linked list
|
||||
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
||||
if link.Head == nil {
|
||||
return nil
|
||||
}
|
||||
if link.Head.Next == nil {
|
||||
return link.Head
|
||||
}
|
||||
fast := link.Head
|
||||
slow := link.Head
|
||||
|
||||
for fast != nil {
|
||||
fast = fast.Next
|
||||
|
||||
if fast != nil {
|
||||
fast = fast.Next
|
||||
slow = slow.Next
|
||||
} else {
|
||||
return slow
|
||||
}
|
||||
}
|
||||
return slow
|
||||
}
|
||||
|
||||
// Size return the count of doubly linked list
|
||||
func (link *DoublyLink[T]) Size() int {
|
||||
return link.length
|
||||
}
|
||||
|
||||
// Values return slice of all doubly linklist node value
|
||||
func (link *DoublyLink[T]) Values() []T {
|
||||
res := []T{}
|
||||
current := link.Head
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Print all nodes info of a linked list
|
||||
func (link *DoublyLink[T]) Print() {
|
||||
current := link.Head
|
||||
info := "[ "
|
||||
for current != nil {
|
||||
info += fmt.Sprintf("%+v, ", current)
|
||||
current = current.Next
|
||||
}
|
||||
info += " ]"
|
||||
fmt.Println(info)
|
||||
}
|
||||
|
||||
// IsEmpty checks if link is empty or not
|
||||
func (link *DoublyLink[T]) IsEmpty() bool {
|
||||
return link.length == 0
|
||||
}
|
||||
|
||||
// Clear checks if link is empty or not
|
||||
func (link *DoublyLink[T]) Clear() {
|
||||
link.Head = nil
|
||||
link.length = 0
|
||||
}
|
||||
179
datastructure/link/doublylink_test.go
Normal file
179
datastructure/link/doublylink_test.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestDoublyLink_InsertAtFirst(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
link.InsertAtHead(1)
|
||||
link.InsertAtHead(2)
|
||||
link.InsertAtHead(3)
|
||||
link.Print()
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestDoublyLink_InsertAtTail(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.Print()
|
||||
|
||||
expected := []int{1, 2, 3}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestDoublyLink_InsertAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
|
||||
err := link.InsertAt(1, 1)
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAt(0, 1)
|
||||
link.InsertAt(1, 2)
|
||||
link.InsertAt(2, 4)
|
||||
link.InsertAt(2, 3)
|
||||
|
||||
link.Print()
|
||||
|
||||
expected := []int{1, 2, 3, 4}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
|
||||
}
|
||||
|
||||
func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
err := link.DeleteAtHead()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.DeleteAtHead()
|
||||
link.Print()
|
||||
|
||||
expected := []int{2, 3, 4}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
err := link.DeleteAtTail()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.DeleteAtTail()
|
||||
link.Print()
|
||||
|
||||
expected := []int{1, 2, 3}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestDoublyLink_DeleteAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
err := link.DeleteAt(0)
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
link.InsertAtTail(5)
|
||||
|
||||
err = link.DeleteAt(5)
|
||||
assert.IsNotNil(err)
|
||||
|
||||
err = link.DeleteAt(0)
|
||||
assert.IsNil(err)
|
||||
assert.Equal([]int{2, 3, 4, 5}, link.Values())
|
||||
|
||||
link.DeleteAt(3)
|
||||
assert.Equal([]int{2, 3, 4}, link.Values())
|
||||
|
||||
link.DeleteAt(1)
|
||||
assert.Equal(2, link.Size())
|
||||
assert.Equal([]int{2, 4}, link.Values())
|
||||
}
|
||||
|
||||
func TestDoublyLink_Reverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.Reverse()
|
||||
link.Print()
|
||||
assert.Equal([]int{4, 3, 2, 1}, link.Values())
|
||||
}
|
||||
|
||||
func TestDoublyLink_GetMiddleNode(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
middle1 := link.GetMiddleNode()
|
||||
assert.Equal(3, middle1.Value)
|
||||
|
||||
link.InsertAtTail(5)
|
||||
link.InsertAtTail(6)
|
||||
link.InsertAtTail(7)
|
||||
middle2 := link.GetMiddleNode()
|
||||
assert.Equal(4, middle2.Value)
|
||||
}
|
||||
|
||||
func TestDoublyLink_Clear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
|
||||
assert.Equal(true, link.IsEmpty())
|
||||
assert.Equal(0, link.Size())
|
||||
|
||||
link.InsertAtTail(1)
|
||||
assert.Equal(false, link.IsEmpty())
|
||||
assert.Equal(1, link.Size())
|
||||
|
||||
link.Clear()
|
||||
assert.Equal(true, link.IsEmpty())
|
||||
assert.Equal(0, link.Size())
|
||||
}
|
||||
246
datastructure/link/singlylink.go
Normal file
246
datastructure/link/singlylink.go
Normal file
@@ -0,0 +1,246 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
)
|
||||
|
||||
// SinglyLink is a linked list. Whose node has a Value generics and Next pointer points to a next node of the link.
|
||||
type SinglyLink[T any] struct {
|
||||
Head *datastructure.LinkNode[T]
|
||||
length int
|
||||
}
|
||||
|
||||
// NewSinglyLink return *SinglyLink instance
|
||||
func NewSinglyLink[T any]() *SinglyLink[T] {
|
||||
return &SinglyLink[T]{Head: nil}
|
||||
}
|
||||
|
||||
// InsertAtHead insert value into singly linklist at head index
|
||||
func (link *SinglyLink[T]) InsertAtHead(value T) {
|
||||
newNode := datastructure.NewLinkNode(value)
|
||||
newNode.Next = link.Head
|
||||
link.Head = newNode
|
||||
link.length++
|
||||
}
|
||||
|
||||
// InsertAtTail insert value into singly linklist at tail index
|
||||
func (link *SinglyLink[T]) InsertAtTail(value T) {
|
||||
current := link.Head
|
||||
if current == nil {
|
||||
link.InsertAtHead(value)
|
||||
return
|
||||
}
|
||||
|
||||
for current.Next != nil {
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
newNode := datastructure.NewLinkNode(value)
|
||||
newNode.Next = nil
|
||||
current.Next = newNode
|
||||
|
||||
link.length++
|
||||
}
|
||||
|
||||
// InsertAt insert value into singly linklist at index
|
||||
func (link *SinglyLink[T]) InsertAt(index int, value T) error {
|
||||
size := link.length
|
||||
if index < 0 || index > size {
|
||||
return errors.New("param index should between 0 and the length of singly link.")
|
||||
}
|
||||
|
||||
if index == 0 {
|
||||
link.InsertAtHead(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
if index == size {
|
||||
link.InsertAtTail(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
i := 0
|
||||
current := link.Head
|
||||
|
||||
for current != nil {
|
||||
if i == index-1 {
|
||||
newNode := datastructure.NewLinkNode(value)
|
||||
newNode.Next = current.Next
|
||||
current.Next = newNode
|
||||
link.length++
|
||||
|
||||
return nil
|
||||
}
|
||||
i++
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
return errors.New("singly link list no exist")
|
||||
}
|
||||
|
||||
// DeleteAtHead delete value in singly linklist at head index
|
||||
func (link *SinglyLink[T]) DeleteAtHead() error {
|
||||
if link.Head == nil {
|
||||
return errors.New("singly link list no exist")
|
||||
}
|
||||
current := link.Head
|
||||
link.Head = current.Next
|
||||
link.length--
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAtTail delete value in singly linklist at tail index
|
||||
func (link *SinglyLink[T]) DeleteAtTail() error {
|
||||
if link.Head == nil {
|
||||
return errors.New("singly link list no exist")
|
||||
}
|
||||
current := link.Head
|
||||
if current.Next == nil {
|
||||
return link.DeleteAtHead()
|
||||
}
|
||||
|
||||
for current.Next.Next != nil {
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
current.Next = nil
|
||||
link.length--
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAt delete value in singly linklist at index
|
||||
func (link *SinglyLink[T]) DeleteAt(index int) error {
|
||||
if link.Head == nil {
|
||||
return errors.New("singly link list no exist")
|
||||
}
|
||||
current := link.Head
|
||||
if current.Next == nil || index == 0 {
|
||||
return link.DeleteAtHead()
|
||||
}
|
||||
|
||||
if index == link.length-1 {
|
||||
return link.DeleteAtTail()
|
||||
}
|
||||
|
||||
if index < 0 || index > link.length-1 {
|
||||
return errors.New("param index should between 0 and link size -1.")
|
||||
}
|
||||
|
||||
i := 0
|
||||
for current != nil {
|
||||
if i == index-1 {
|
||||
current.Next = current.Next.Next
|
||||
link.length--
|
||||
return nil
|
||||
}
|
||||
i++
|
||||
current = current.Next
|
||||
}
|
||||
|
||||
return errors.New("delete error")
|
||||
}
|
||||
|
||||
// DeleteValue delete value in singly linklist
|
||||
func (link *SinglyLink[T]) DeleteValue(value T) {
|
||||
if link.Head == nil {
|
||||
return
|
||||
}
|
||||
dummyHead := datastructure.NewLinkNode(value)
|
||||
dummyHead.Next = link.Head
|
||||
current := dummyHead
|
||||
|
||||
for current.Next != nil {
|
||||
if reflect.DeepEqual(current.Next.Value, value) {
|
||||
current.Next = current.Next.Next
|
||||
link.length--
|
||||
} else {
|
||||
current = current.Next
|
||||
}
|
||||
}
|
||||
|
||||
link.Head = dummyHead.Next
|
||||
}
|
||||
|
||||
// Reverse the linked list
|
||||
func (link *SinglyLink[T]) Reverse() {
|
||||
var pre, next *datastructure.LinkNode[T]
|
||||
|
||||
current := link.Head
|
||||
|
||||
for current != nil {
|
||||
next = current.Next
|
||||
current.Next = pre
|
||||
pre = current
|
||||
current = next
|
||||
}
|
||||
|
||||
link.Head = pre
|
||||
}
|
||||
|
||||
// GetMiddleNode return node at middle index of linked list
|
||||
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
||||
if link.Head == nil {
|
||||
return nil
|
||||
}
|
||||
if link.Head.Next == nil {
|
||||
return link.Head
|
||||
}
|
||||
fast := link.Head
|
||||
slow := link.Head
|
||||
|
||||
for fast != nil {
|
||||
fast = fast.Next
|
||||
|
||||
if fast != nil {
|
||||
fast = fast.Next
|
||||
slow = slow.Next
|
||||
} else {
|
||||
return slow
|
||||
}
|
||||
}
|
||||
return slow
|
||||
}
|
||||
|
||||
// Size return the count of singly linked list
|
||||
func (link *SinglyLink[T]) Size() int {
|
||||
return link.length
|
||||
}
|
||||
|
||||
// Values return slice of all singly linklist node value
|
||||
func (link *SinglyLink[T]) Values() []T {
|
||||
res := []T{}
|
||||
current := link.Head
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// IsEmpty checks if link is empty or not
|
||||
func (link *SinglyLink[T]) IsEmpty() bool {
|
||||
return link.length == 0
|
||||
}
|
||||
|
||||
// Clear checks if link is empty or not
|
||||
func (link *SinglyLink[T]) Clear() {
|
||||
link.Head = nil
|
||||
link.length = 0
|
||||
}
|
||||
|
||||
// Print all nodes info of a linked list
|
||||
func (link *SinglyLink[T]) Print() {
|
||||
current := link.Head
|
||||
info := "[ "
|
||||
for current != nil {
|
||||
info += fmt.Sprintf("%+v, ", current)
|
||||
current = current.Next
|
||||
}
|
||||
info += " ]"
|
||||
fmt.Println(info)
|
||||
}
|
||||
208
datastructure/link/singlylink_test.go
Normal file
208
datastructure/link/singlylink_test.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestSinglyLink_InsertAtFirst(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
link.InsertAtHead(1)
|
||||
link.InsertAtHead(2)
|
||||
link.InsertAtHead(3)
|
||||
link.Print()
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestSinglyLink_InsertAtTail(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.Print()
|
||||
|
||||
expected := []int{1, 2, 3}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestSinglyLink_InsertAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
|
||||
err := link.InsertAt(1, 1)
|
||||
assert.IsNotNil(err)
|
||||
|
||||
err = link.InsertAt(0, 1)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
err = link.InsertAt(1, 2)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
err = link.InsertAt(2, 4)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
err = link.InsertAt(2, 3)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
link.Print()
|
||||
|
||||
expected := []int{1, 2, 3, 4}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
err := link.DeleteAtHead()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.DeleteAtHead()
|
||||
link.Print()
|
||||
|
||||
expected := []int{2, 3, 4}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
err := link.DeleteAtTail()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.DeleteAtTail()
|
||||
link.Print()
|
||||
|
||||
expected := []int{1, 2, 3}
|
||||
values := link.Values()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteValue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.DeleteValue(2)
|
||||
assert.Equal([]int{1, 3, 4}, link.Values())
|
||||
|
||||
link.DeleteValue(1)
|
||||
assert.Equal([]int{3, 4}, link.Values())
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
err := link.DeleteAt(0)
|
||||
assert.IsNotNil(err)
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
link.InsertAtTail(5)
|
||||
|
||||
err = link.DeleteAt(5)
|
||||
assert.IsNotNil(err)
|
||||
|
||||
err = link.DeleteAt(0)
|
||||
assert.IsNil(err)
|
||||
assert.Equal([]int{2, 3, 4, 5}, link.Values())
|
||||
|
||||
link.DeleteAt(3)
|
||||
assert.Equal([]int{2, 3, 4}, link.Values())
|
||||
|
||||
link.DeleteAt(1)
|
||||
assert.Equal(2, link.Size())
|
||||
assert.Equal([]int{2, 4}, link.Values())
|
||||
}
|
||||
|
||||
func TestSinglyLink_Reverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
link.Reverse()
|
||||
link.Print()
|
||||
assert.Equal([]int{4, 3, 2, 1}, link.Values())
|
||||
}
|
||||
|
||||
func TestSinglyLink_GetMiddleNode(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
link.InsertAtTail(4)
|
||||
|
||||
middle1 := link.GetMiddleNode()
|
||||
assert.Equal(3, middle1.Value)
|
||||
|
||||
link.InsertAtTail(5)
|
||||
link.InsertAtTail(6)
|
||||
link.InsertAtTail(7)
|
||||
middle2 := link.GetMiddleNode()
|
||||
assert.Equal(4, middle2.Value)
|
||||
}
|
||||
|
||||
func TestSinglyLink_Clear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_Clear")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
|
||||
assert.Equal(true, link.IsEmpty())
|
||||
assert.Equal(0, link.Size())
|
||||
|
||||
link.InsertAtTail(1)
|
||||
assert.Equal(false, link.IsEmpty())
|
||||
assert.Equal(1, link.Size())
|
||||
|
||||
link.Clear()
|
||||
assert.Equal(true, link.IsEmpty())
|
||||
assert.Equal(0, link.Size())
|
||||
}
|
||||
245
datastructure/list/list.go
Normal file
245
datastructure/list/list.go
Normal file
@@ -0,0 +1,245 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// List is a linear table, implemented with slice
|
||||
type List[T any] struct {
|
||||
data []T
|
||||
}
|
||||
|
||||
// NewList return a pointer of List
|
||||
func NewList[T any](data []T) *List[T] {
|
||||
return &List[T]{data: data}
|
||||
}
|
||||
|
||||
// Data return list data
|
||||
func (l *List[T]) Data() []T {
|
||||
return l.data
|
||||
}
|
||||
|
||||
// ValueOf return the value pointer at index of list data.
|
||||
func (l *List[T]) ValueOf(index int) (*T, bool) {
|
||||
if index < 0 || index >= len(l.data) {
|
||||
return nil, false
|
||||
}
|
||||
return &l.data[index], true
|
||||
}
|
||||
|
||||
// IndexOf reture the index of value. if not found return -1
|
||||
func (l *List[T]) IndexOf(value T) int {
|
||||
index := -1
|
||||
data := l.data
|
||||
for i, v := range data {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// Contain checks if the value in the list or not
|
||||
func (l *List[T]) Contain(value T) bool {
|
||||
data := l.data
|
||||
for _, v := range data {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Push append value to the list data
|
||||
func (l *List[T]) Push(value T) {
|
||||
l.data = append(l.data, value)
|
||||
}
|
||||
|
||||
// InsertAtFirst insert value into list at first index
|
||||
func (l *List[T]) InsertAtFirst(value T) {
|
||||
l.InsertAt(0, value)
|
||||
}
|
||||
|
||||
// InsertAtLast insert value into list at last index
|
||||
func (l *List[T]) InsertAtLast(value T) {
|
||||
l.InsertAt(len(l.data), value)
|
||||
}
|
||||
|
||||
// InsertAt insert value into list at index
|
||||
func (l *List[T]) InsertAt(index int, value T) {
|
||||
data := l.data
|
||||
size := len(data)
|
||||
|
||||
if index < 0 || index > size {
|
||||
return
|
||||
}
|
||||
l.data = append(data[:index], append([]T{value}, data[index:]...)...)
|
||||
}
|
||||
|
||||
// PopFirst delete the first value of list and return it
|
||||
func (l *List[T]) PopFirst() (*T, bool) {
|
||||
if len(l.data) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
v := l.data[0]
|
||||
l.DeleteAt(0)
|
||||
|
||||
return &v, true
|
||||
}
|
||||
|
||||
// PopLast delete the last value of list and return it
|
||||
func (l *List[T]) PopLast() (*T, bool) {
|
||||
size := len(l.data)
|
||||
if size == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
v := l.data[size-1]
|
||||
l.DeleteAt(size - 1)
|
||||
|
||||
return &v, true
|
||||
}
|
||||
|
||||
// DeleteAt delete the value of list at index
|
||||
func (l *List[T]) DeleteAt(index int) {
|
||||
data := l.data
|
||||
size := len(data)
|
||||
if index < 0 || index > size-1 {
|
||||
return
|
||||
}
|
||||
if index == size-1 {
|
||||
data = append(data[:index])
|
||||
} else {
|
||||
data = append(data[:index], data[index+1:]...)
|
||||
}
|
||||
l.data = data
|
||||
}
|
||||
|
||||
// UpdateAt update value of list at index, index shoud between 0 and list size -1
|
||||
func (l *List[T]) UpdateAt(index int, value T) {
|
||||
data := l.data
|
||||
size := len(data)
|
||||
|
||||
if index < 0 || index >= size {
|
||||
return
|
||||
}
|
||||
l.data = append(data[:index], append([]T{value}, data[index+1:]...)...)
|
||||
}
|
||||
|
||||
// Equtal compare list to other list, use reflect.DeepEqual
|
||||
func (l *List[T]) Equtal(other *List[T]) bool {
|
||||
if len(l.data) != len(other.data) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < len(l.data); i++ {
|
||||
if !reflect.DeepEqual(l.data[i], other.data[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsEmpty check if the list is empty or not
|
||||
func (l *List[T]) IsEmpty() bool {
|
||||
return len(l.data) == 0
|
||||
}
|
||||
|
||||
// Clear the data of list
|
||||
func (l *List[T]) Clear() {
|
||||
l.data = make([]T, 0, 0)
|
||||
}
|
||||
|
||||
// Clone return a copy of list
|
||||
func (l *List[T]) Clone() *List[T] {
|
||||
cl := NewList(make([]T, len(l.data)))
|
||||
copy(cl.data, l.data)
|
||||
|
||||
return cl
|
||||
}
|
||||
|
||||
// Merge two list, return new list, don't change original list
|
||||
func (l *List[T]) Merge(other *List[T]) *List[T] {
|
||||
l1, l2 := len(l.data), len(other.data)
|
||||
ml := NewList(make([]T, l1+l2, l1+l2))
|
||||
|
||||
data := append([]T{}, append(l.data, other.data...)...)
|
||||
ml.data = data
|
||||
|
||||
return ml
|
||||
}
|
||||
|
||||
// Size return number of list data items
|
||||
func (l *List[T]) Size() int {
|
||||
return len(l.data)
|
||||
}
|
||||
|
||||
// Swap the value of index i and j in list
|
||||
func (l *List[T]) Swap(i, j int) {
|
||||
size := len(l.data)
|
||||
if i < 0 || i >= size || j < 0 || j >= size {
|
||||
return
|
||||
}
|
||||
l.data[i], l.data[j] = l.data[j], l.data[i]
|
||||
}
|
||||
|
||||
// Reverse the item order of list
|
||||
func (l *List[T]) Reverse() {
|
||||
for i, j := 0, len(l.data)-1; i < j; i, j = i+1, j-1 {
|
||||
l.data[i], l.data[j] = l.data[j], l.data[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Unique remove duplicate items in list
|
||||
func (l *List[T]) Unique() {
|
||||
data := l.data
|
||||
size := len(data)
|
||||
|
||||
uniqueData := make([]T, 0, 0)
|
||||
for i := 0; i < size; i++ {
|
||||
value := data[i]
|
||||
skip := true
|
||||
for _, v := range uniqueData {
|
||||
if reflect.DeepEqual(value, v) {
|
||||
skip = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
uniqueData = append(uniqueData, value)
|
||||
}
|
||||
}
|
||||
|
||||
l.data = uniqueData
|
||||
}
|
||||
|
||||
// Union creates a new list contain all element in list l and other, remove duplicate element.
|
||||
func (l *List[T]) Union(other *List[T]) *List[T] {
|
||||
res := NewList([]T{})
|
||||
|
||||
res.data = append(res.data, l.data...)
|
||||
res.data = append(res.data, other.data...)
|
||||
res.Unique()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Intersection creates a new list whose element both be contained in list l and other
|
||||
func (l *List[T]) Intersection(other *List[T]) *List[T] {
|
||||
res := NewList(make([]T, 0, 0))
|
||||
|
||||
for _, v := range l.data {
|
||||
if other.Contain(v) {
|
||||
res.data = append(res.data, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
272
datastructure/list/list_test.go
Normal file
272
datastructure/list/list_test.go
Normal file
@@ -0,0 +1,272 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestListData(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestListData")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
assert.Equal([]int{1, 2, 3}, list.Data())
|
||||
}
|
||||
|
||||
func TestValueOf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestValueOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
v, ok := list.ValueOf(0)
|
||||
assert.Equal(1, *v)
|
||||
assert.Equal(true, ok)
|
||||
|
||||
_, ok = list.ValueOf(3)
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestIndexOf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
i := list.IndexOf(1)
|
||||
assert.Equal(0, i)
|
||||
|
||||
i = list.IndexOf(4)
|
||||
assert.Equal(-1, i)
|
||||
}
|
||||
|
||||
func TestContain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestContain")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
assert.Equal(true, list.Contain(1))
|
||||
assert.Equal(false, list.Contain(0))
|
||||
}
|
||||
|
||||
func TestPush(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestPush")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
list.Push(4)
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.Data())
|
||||
}
|
||||
|
||||
func TestInsertAtFirst(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestInsertAtFirst")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
list.InsertAtFirst(0)
|
||||
|
||||
assert.Equal([]int{0, 1, 2, 3}, list.Data())
|
||||
}
|
||||
|
||||
func TestInsertAtLast(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestInsertAtLast")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
list.InsertAtLast(4)
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.Data())
|
||||
}
|
||||
|
||||
func TestInsertAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestInsertAt")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
|
||||
list.InsertAt(-1, 0)
|
||||
assert.Equal([]int{1, 2, 3}, list.Data())
|
||||
|
||||
list.InsertAt(4, 0)
|
||||
assert.Equal([]int{1, 2, 3}, list.Data())
|
||||
|
||||
list.InsertAt(0, 0)
|
||||
assert.Equal([]int{0, 1, 2, 3}, list.Data())
|
||||
|
||||
list.InsertAt(4, 4)
|
||||
assert.Equal([]int{0, 1, 2, 3, 4}, list.Data())
|
||||
}
|
||||
|
||||
func TestPopFirst(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestPopFirst")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
v, ok := list.PopFirst()
|
||||
assert.Equal(1, *v)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal([]int{2, 3}, list.Data())
|
||||
|
||||
list2 := NewList([]int{})
|
||||
_, ok = list2.PopFirst()
|
||||
assert.Equal(false, ok)
|
||||
assert.Equal([]int{}, list2.Data())
|
||||
}
|
||||
|
||||
func TestPopLast(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestPopLast")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
v, ok := list.PopLast()
|
||||
assert.Equal(3, *v)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal([]int{1, 2}, list.Data())
|
||||
|
||||
list2 := NewList([]int{})
|
||||
_, ok = list2.PopLast()
|
||||
assert.Equal(false, ok)
|
||||
assert.Equal([]int{}, list2.Data())
|
||||
}
|
||||
|
||||
func TestDeleteAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDeleteAt")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
|
||||
list.DeleteAt(-1)
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.Data())
|
||||
|
||||
list.DeleteAt(4)
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.Data())
|
||||
|
||||
list.DeleteAt(0)
|
||||
assert.Equal([]int{2, 3, 4}, list.Data())
|
||||
|
||||
list.DeleteAt(2)
|
||||
assert.Equal([]int{2, 3}, list.Data())
|
||||
}
|
||||
|
||||
func TestUpdateAt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUpdateAt")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
|
||||
list.UpdateAt(-1, 0)
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.Data())
|
||||
|
||||
list.UpdateAt(4, 0)
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.Data())
|
||||
|
||||
list.UpdateAt(0, 5)
|
||||
assert.Equal([]int{5, 2, 3, 4}, list.Data())
|
||||
|
||||
list.UpdateAt(3, 1)
|
||||
assert.Equal([]int{5, 2, 3, 1}, list.Data())
|
||||
}
|
||||
|
||||
func TestEqutal(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqutal")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := NewList([]int{1, 2, 3, 4})
|
||||
list3 := NewList([]int{1, 2, 3})
|
||||
|
||||
assert.Equal(true, list1.Equtal(list2))
|
||||
assert.Equal(false, list1.Equtal(list3))
|
||||
}
|
||||
|
||||
func TestIsEmpty(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsEmpty")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := NewList([]int{})
|
||||
|
||||
assert.Equal(false, list1.IsEmpty())
|
||||
assert.Equal(true, list2.IsEmpty())
|
||||
}
|
||||
|
||||
func TestIsClear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsClear")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list1.Clear()
|
||||
empty := NewList([]int{})
|
||||
|
||||
assert.Equal(empty, list1)
|
||||
}
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestClone")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := list1.Clone()
|
||||
|
||||
assert.Equal(true, list1.Equtal(list2))
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMerge")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := NewList([]int{4, 5, 6})
|
||||
expected := NewList([]int{1, 2, 3, 4, 4, 5, 6})
|
||||
|
||||
list3 := list1.Merge(list2)
|
||||
assert.Equal(true, expected.Equtal(list3))
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSize")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
empty := NewList([]int{})
|
||||
|
||||
assert.Equal(4, list.Size())
|
||||
assert.Equal(0, empty.Size())
|
||||
}
|
||||
|
||||
func TestSwap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSwap")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
expected := NewList([]int{4, 2, 3, 1})
|
||||
|
||||
list.Swap(0, 3)
|
||||
|
||||
assert.Equal(true, expected.Equtal(list))
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReverse")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
expected := NewList([]int{4, 3, 2, 1})
|
||||
|
||||
list.Reverse()
|
||||
|
||||
assert.Equal(true, expected.Equtal(list))
|
||||
}
|
||||
|
||||
func TestUnique(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUnique")
|
||||
|
||||
list := NewList([]int{1, 2, 2, 3, 4})
|
||||
expected := NewList([]int{1, 2, 3, 4})
|
||||
|
||||
list.Unique()
|
||||
|
||||
assert.Equal(true, expected.Equtal(list))
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUnion")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := NewList([]int{4, 5, 6})
|
||||
expected := NewList([]int{1, 2, 3, 4, 5, 6})
|
||||
|
||||
list3 := list1.Union(list2)
|
||||
assert.Equal(true, expected.Equtal(list3))
|
||||
}
|
||||
|
||||
func TestIntersection(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIntersection")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
list2 := NewList([]int{4, 5, 6})
|
||||
expected := NewList([]int{4})
|
||||
|
||||
list3 := list1.Intersection(list2)
|
||||
assert.Equal(true, expected.Equtal(list3))
|
||||
}
|
||||
51
datastructure/node.go
Normal file
51
datastructure/node.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
package datastructure
|
||||
|
||||
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.
|
||||
type LinkNode[T any] struct {
|
||||
Value T
|
||||
Pre *LinkNode[T]
|
||||
Next *LinkNode[T]
|
||||
}
|
||||
|
||||
// NewLinkNode return a LinkNode pointer
|
||||
func NewLinkNode[T any](value T) *LinkNode[T] {
|
||||
return &LinkNode[T]{value, nil, nil}
|
||||
}
|
||||
|
||||
// StackNode is a node in stack, which have a Value and Next pointer points to next node in the stack.
|
||||
type StackNode[T any] struct {
|
||||
Value T
|
||||
Next *StackNode[T]
|
||||
}
|
||||
|
||||
// NewStackNode return a StackNode pointer
|
||||
func NewStackNode[T any](value T) *StackNode[T] {
|
||||
return &StackNode[T]{value, nil}
|
||||
}
|
||||
|
||||
// QueueNode is a node in a queue, which have a Value and Next pointer points to next node in the queue.
|
||||
type QueueNode[T any] struct {
|
||||
Value T
|
||||
Next *QueueNode[T]
|
||||
}
|
||||
|
||||
// NewQueueNode return a QueueNode pointer
|
||||
func NewQueueNode[T any](value T) *QueueNode[T] {
|
||||
return &QueueNode[T]{value, nil}
|
||||
}
|
||||
|
||||
// TreeNode is node of tree
|
||||
type TreeNode[T any] struct {
|
||||
Data T
|
||||
Left *TreeNode[T]
|
||||
Right *TreeNode[T]
|
||||
}
|
||||
|
||||
// NewTreeNode return a TreeNode pointer
|
||||
func NewTreeNode[T any](data T) *TreeNode[T] {
|
||||
return &TreeNode[T]{data, nil, nil}
|
||||
}
|
||||
92
datastructure/queue/arrayqueue.go
Normal file
92
datastructure/queue/arrayqueue.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ArrayQueue implements queue with slice
|
||||
type ArrayQueue[T any] struct {
|
||||
data []T
|
||||
length int
|
||||
}
|
||||
|
||||
// NewArrayQueue return a empty ArrayQueue pointer
|
||||
func NewArrayQueue[T any](values ...T) *ArrayQueue[T] {
|
||||
data := make([]T, len(values))
|
||||
for i, v := range values {
|
||||
data[i] = v
|
||||
}
|
||||
return &ArrayQueue[T]{data: data, length: len(values)}
|
||||
}
|
||||
|
||||
// Data return queue data
|
||||
func (q *ArrayQueue[T]) Data() []T {
|
||||
return q.data
|
||||
}
|
||||
|
||||
// Size return length of queue data
|
||||
func (q *ArrayQueue[T]) Size() int {
|
||||
return q.length
|
||||
}
|
||||
|
||||
// IsEmpty checks if queue is empty or not
|
||||
func (q *ArrayQueue[T]) IsEmpty() bool {
|
||||
return q.length == 0
|
||||
}
|
||||
|
||||
// Front return front value of queue
|
||||
func (q *ArrayQueue[T]) Front() T {
|
||||
return q.data[0]
|
||||
}
|
||||
|
||||
// Back return back value of queue
|
||||
func (q *ArrayQueue[T]) Back() T {
|
||||
return q.data[q.length-1]
|
||||
}
|
||||
|
||||
// EnQueue put element into queue
|
||||
func (q *ArrayQueue[T]) EnQueue(value T) {
|
||||
q.data = append(q.data, value)
|
||||
q.length++
|
||||
}
|
||||
|
||||
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
|
||||
func (q *ArrayQueue[T]) DeQueue() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
|
||||
headItem := q.data[0]
|
||||
q.data = q.data[1:]
|
||||
q.length--
|
||||
|
||||
return &headItem, nil
|
||||
}
|
||||
|
||||
// Clear the queue data
|
||||
func (q *ArrayQueue[T]) Clear() {
|
||||
q.data = []T{}
|
||||
q.length = 0
|
||||
}
|
||||
|
||||
// Contain checks if the value is in queue or not
|
||||
func (q *ArrayQueue[T]) Contain(value T) bool {
|
||||
for _, v := range q.data {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Print queue data
|
||||
func (q *ArrayQueue[T]) Print() {
|
||||
info := "["
|
||||
for _, v := range q.data {
|
||||
info += fmt.Sprintf("%+v, ", v)
|
||||
}
|
||||
info += "]"
|
||||
fmt.Println(info)
|
||||
}
|
||||
90
datastructure/queue/arrayqueue_test.go
Normal file
90
datastructure/queue/arrayqueue_test.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestArrayQueue_EnQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_EnQueue")
|
||||
|
||||
queue := NewArrayQueue[int]()
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
|
||||
expected := []int{1, 2, 3}
|
||||
data := queue.Data()
|
||||
size := queue.Size()
|
||||
|
||||
queue.Print()
|
||||
|
||||
assert.Equal(expected, data)
|
||||
assert.Equal(3, size)
|
||||
}
|
||||
|
||||
func TestArrayQueue_DeQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_DeQueue")
|
||||
|
||||
queue := NewArrayQueue(1, 2, 3)
|
||||
|
||||
val, err := queue.DeQueue()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
queue.Print()
|
||||
assert.Equal(1, *val)
|
||||
|
||||
assert.Equal([]int{2, 3}, queue.Data())
|
||||
}
|
||||
|
||||
func TestArrayQueue_Front(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Front")
|
||||
|
||||
queue := NewArrayQueue(1, 2, 3)
|
||||
val := queue.Front()
|
||||
|
||||
queue.Print()
|
||||
|
||||
assert.Equal(1, val)
|
||||
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||
}
|
||||
|
||||
func TestArrayQueue_Back(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Back")
|
||||
|
||||
queue := NewArrayQueue(1, 2, 3)
|
||||
val := queue.Back()
|
||||
|
||||
queue.Print()
|
||||
|
||||
assert.Equal(3, val)
|
||||
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||
}
|
||||
|
||||
func TestArrayQueue_Contain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
|
||||
|
||||
queue := NewArrayQueue(1, 2, 3)
|
||||
|
||||
assert.Equal(true, queue.Contain(1))
|
||||
assert.Equal(false, queue.Contain(4))
|
||||
}
|
||||
|
||||
func TestArrayQueue_Clear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
|
||||
|
||||
queue := NewArrayQueue[int]()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Size())
|
||||
|
||||
queue.EnQueue(1)
|
||||
assert.Equal(false, queue.IsEmpty())
|
||||
assert.Equal(1, queue.Size())
|
||||
|
||||
queue.Clear()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Size())
|
||||
}
|
||||
118
datastructure/queue/circularqueue.go
Normal file
118
datastructure/queue/circularqueue.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// CircularQueue implements circular queue with slice,
|
||||
// last index of CircularQueue don't contain value, so acturl capacity is size - 1
|
||||
type CircularQueue[T any] struct {
|
||||
data []T
|
||||
front int
|
||||
rear int
|
||||
size int
|
||||
}
|
||||
|
||||
// NewCircularQueue return a empty CircularQueue pointer
|
||||
func NewCircularQueue[T any](size int) *CircularQueue[T] {
|
||||
data := make([]T, size)
|
||||
return &CircularQueue[T]{data: data, front: 0, rear: 0, size: size}
|
||||
}
|
||||
|
||||
// Data return queue data
|
||||
func (q *CircularQueue[T]) Data() []T {
|
||||
data := []T{}
|
||||
|
||||
front := q.front
|
||||
rear := q.rear
|
||||
if front <= rear {
|
||||
return q.data[front:rear]
|
||||
}
|
||||
|
||||
data = append(data, q.data[front:]...)
|
||||
data = append(data, q.data[0:rear]...)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// Length return current data length of queue
|
||||
func (q *CircularQueue[T]) Length() int {
|
||||
if q.size == 0 {
|
||||
return 0
|
||||
}
|
||||
return (q.rear - q.front + q.size) % q.size
|
||||
}
|
||||
|
||||
// IsEmpty checks if queue is empty or not
|
||||
func (q *CircularQueue[T]) IsEmpty() bool {
|
||||
return q.front == q.rear
|
||||
}
|
||||
|
||||
// IsFull checks if queue is full or not
|
||||
func (q *CircularQueue[T]) IsFull() bool {
|
||||
return (q.rear+1)%q.size == q.front
|
||||
}
|
||||
|
||||
// Front return front value of queue
|
||||
func (q *CircularQueue[T]) Front() T {
|
||||
return q.data[q.front]
|
||||
}
|
||||
|
||||
// Back return back value of queue
|
||||
func (q *CircularQueue[T]) Back() T {
|
||||
if q.rear-1 >= 0 {
|
||||
return q.data[q.rear-1]
|
||||
}
|
||||
return q.data[q.size-1]
|
||||
}
|
||||
|
||||
// EnQueue put element into queue
|
||||
func (q *CircularQueue[T]) EnQueue(value T) error {
|
||||
if q.IsFull() {
|
||||
return errors.New("queue is full!")
|
||||
}
|
||||
|
||||
q.data[q.rear] = value
|
||||
q.rear = (q.rear + 1) % q.size
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
|
||||
func (q *CircularQueue[T]) DeQueue() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
|
||||
headItem := q.data[q.front]
|
||||
var t T
|
||||
q.data[q.front] = t
|
||||
q.front = (q.front + 1) % q.size
|
||||
|
||||
return &headItem, nil
|
||||
}
|
||||
|
||||
// Clear the queue data
|
||||
func (q *CircularQueue[T]) Clear() {
|
||||
q.data = []T{}
|
||||
q.front = 0
|
||||
q.rear = 0
|
||||
q.size = 0
|
||||
}
|
||||
|
||||
// Contain checks if the value is in queue or not
|
||||
func (q *CircularQueue[T]) Contain(value T) bool {
|
||||
for _, v := range q.data {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Print queue data
|
||||
func (q *CircularQueue[T]) Print() {
|
||||
fmt.Printf("%+v\n", q)
|
||||
}
|
||||
148
datastructure/queue/circularqueue_test.go
Normal file
148
datastructure/queue/circularqueue_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestCircularQueue_EnQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_EnQueue")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
|
||||
queue.Print()
|
||||
// assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||
assert.Equal(5, queue.Length())
|
||||
|
||||
err := queue.EnQueue(6)
|
||||
assert.IsNotNil(err)
|
||||
}
|
||||
|
||||
func TestCircularQueue_DeQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
|
||||
val, err := queue.DeQueue()
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(1, *val)
|
||||
assert.Equal(false, queue.IsFull())
|
||||
|
||||
val, _ = queue.DeQueue()
|
||||
queue.Print()
|
||||
assert.Equal(2, *val)
|
||||
|
||||
queue.EnQueue(6)
|
||||
queue.Print()
|
||||
assert.Equal(false, queue.IsFull())
|
||||
}
|
||||
|
||||
func TestCircularQueue_Front(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
|
||||
queue.Print()
|
||||
|
||||
queue.DeQueue()
|
||||
queue.DeQueue()
|
||||
queue.EnQueue(6)
|
||||
queue.EnQueue(7)
|
||||
|
||||
queue.Print()
|
||||
|
||||
val := queue.Front()
|
||||
assert.Equal(3, val)
|
||||
assert.Equal(5, queue.Length())
|
||||
}
|
||||
|
||||
func TestCircularQueue_Back(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal(5, queue.Back())
|
||||
|
||||
queue.DeQueue()
|
||||
queue.DeQueue()
|
||||
queue.EnQueue(6)
|
||||
queue.EnQueue(7)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal(7, queue.Back())
|
||||
}
|
||||
|
||||
func TestCircularQueue_Contain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
||||
|
||||
queue := NewCircularQueue[int](2)
|
||||
queue.EnQueue(1)
|
||||
assert.Equal(true, queue.Contain(1))
|
||||
assert.Equal(false, queue.Contain(2))
|
||||
}
|
||||
|
||||
func TestCircularQueue_Clear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
|
||||
|
||||
queue := NewCircularQueue[int](3)
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Length())
|
||||
|
||||
queue.EnQueue(1)
|
||||
assert.Equal(false, queue.IsEmpty())
|
||||
assert.Equal(1, queue.Length())
|
||||
|
||||
queue.Clear()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
assert.Equal(0, queue.Length())
|
||||
}
|
||||
|
||||
func TestCircularQueue_Data(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
queue.EnQueue(4)
|
||||
queue.EnQueue(5)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||
|
||||
queue.DeQueue()
|
||||
queue.DeQueue()
|
||||
queue.EnQueue(6)
|
||||
queue.EnQueue(7)
|
||||
|
||||
queue.Print()
|
||||
assert.Equal([]int{3, 4, 5, 6, 7}, queue.Data())
|
||||
|
||||
}
|
||||
104
datastructure/queue/linkedqueue.go
Normal file
104
datastructure/queue/linkedqueue.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
)
|
||||
|
||||
// LinkedQueue implements queue with link list
|
||||
type LinkedQueue[T any] struct {
|
||||
head *datastructure.QueueNode[T]
|
||||
tail *datastructure.QueueNode[T]
|
||||
length int
|
||||
}
|
||||
|
||||
// NewLinkedQueue return a empty LinkedQueue pointer
|
||||
func NewLinkedQueue[T any]() *LinkedQueue[T] {
|
||||
return &LinkedQueue[T]{head: nil, tail: nil, length: 0}
|
||||
}
|
||||
|
||||
// Data return queue data
|
||||
func (q *LinkedQueue[T]) Data() []T {
|
||||
res := []T{}
|
||||
current := q.head
|
||||
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Size return length of queue data
|
||||
func (q *LinkedQueue[T]) Size() int {
|
||||
return q.length
|
||||
}
|
||||
|
||||
// IsEmpty checks if queue is empty or not
|
||||
func (q *LinkedQueue[T]) IsEmpty() bool {
|
||||
return q.length == 0
|
||||
}
|
||||
|
||||
// EnQueue add element into queue
|
||||
func (q *LinkedQueue[T]) EnQueue(value T) {
|
||||
newNode := datastructure.NewQueueNode(value)
|
||||
|
||||
if q.IsEmpty() {
|
||||
q.head = newNode
|
||||
q.tail = newNode
|
||||
} else {
|
||||
q.tail.Next = newNode
|
||||
q.tail = newNode
|
||||
}
|
||||
q.length++
|
||||
}
|
||||
|
||||
// DeQueue delete head element of queue then return it, if queue is empty, return nil and error
|
||||
func (q *LinkedQueue[T]) DeQueue() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
|
||||
head := q.head
|
||||
q.head = q.head.Next
|
||||
q.length--
|
||||
|
||||
return &head.Value, nil
|
||||
}
|
||||
|
||||
// Front return front value of queue
|
||||
func (q *LinkedQueue[T]) Front() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
return &q.head.Value, nil
|
||||
}
|
||||
|
||||
// Back return back value of queue
|
||||
func (q *LinkedQueue[T]) Back() (*T, error) {
|
||||
if q.IsEmpty() {
|
||||
return nil, errors.New("queue is empty")
|
||||
}
|
||||
return &q.tail.Value, nil
|
||||
}
|
||||
|
||||
// Clear clear the queue data
|
||||
func (q *LinkedQueue[T]) Clear() {
|
||||
q.head = nil
|
||||
q.tail = nil
|
||||
q.length = 0
|
||||
}
|
||||
|
||||
// Print all nodes info of queue link
|
||||
func (q *LinkedQueue[T]) Print() {
|
||||
current := q.head
|
||||
info := "[ "
|
||||
for current != nil {
|
||||
info += fmt.Sprintf("%+v, ", current)
|
||||
current = current.Next
|
||||
}
|
||||
info += " ]"
|
||||
fmt.Println(info)
|
||||
}
|
||||
84
datastructure/queue/linkedqueue_test.go
Normal file
84
datastructure/queue/linkedqueue_test.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestLinkedQueue_EnQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_EnQueue")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
|
||||
queue.Print()
|
||||
|
||||
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||
assert.Equal(3, queue.Size())
|
||||
}
|
||||
|
||||
func TestLinkedQueue_DeQueue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
|
||||
val, _ := queue.DeQueue()
|
||||
|
||||
queue.Print()
|
||||
|
||||
assert.Equal([]int{2, 3}, queue.Data())
|
||||
assert.Equal(1, *val)
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Front(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
_, err := queue.Front()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
|
||||
val, err := queue.Front()
|
||||
assert.Equal(1, *val)
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Back(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
_, err := queue.Back()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
|
||||
val, err := queue.Back()
|
||||
assert.Equal(3, *val)
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Clear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
|
||||
queue.EnQueue(1)
|
||||
queue.EnQueue(2)
|
||||
queue.EnQueue(3)
|
||||
assert.Equal(false, queue.IsEmpty())
|
||||
|
||||
queue.Clear()
|
||||
assert.Equal(true, queue.IsEmpty())
|
||||
}
|
||||
105
datastructure/set/set.go
Normal file
105
datastructure/set/set.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package datastructure
|
||||
|
||||
// Set is a data container, like slice, but element of set is not duplicate
|
||||
type Set[T comparable] map[T]bool
|
||||
|
||||
// NewSet return a instance of set
|
||||
func NewSet[T comparable](values ...T) Set[T] {
|
||||
set := make(Set[T])
|
||||
set.Add(values...)
|
||||
return set
|
||||
}
|
||||
|
||||
// Add value to set
|
||||
func (s Set[T]) Add(values ...T) {
|
||||
for _, v := range values {
|
||||
s[v] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Contain checks if set contains value or not
|
||||
func (s Set[T]) Contain(value T) bool {
|
||||
_, ok := s[value]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Contain checks if set contains other set
|
||||
func (s Set[T]) ContainAll(other Set[T]) bool {
|
||||
for k := range other {
|
||||
_, ok := s[k]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Clone return a copy of set
|
||||
func (s Set[T]) Clone() Set[T] {
|
||||
set := NewSet[T]()
|
||||
set.Add(s.Values()...)
|
||||
return set
|
||||
}
|
||||
|
||||
// Delete value of set
|
||||
func (s Set[T]) Delete(values ...T) {
|
||||
for _, v := range values {
|
||||
delete(s, v)
|
||||
}
|
||||
}
|
||||
|
||||
// Equal checks if two set has same elements or not
|
||||
func (s Set[T]) Equal(other Set[T]) bool {
|
||||
if s.Size() != other.Size() {
|
||||
return false
|
||||
}
|
||||
|
||||
return s.ContainAll(other) && other.ContainAll(s)
|
||||
}
|
||||
|
||||
// Iterate call function by every element of set
|
||||
func (s Set[T]) Iterate(fn func(value T)) {
|
||||
for v := range s {
|
||||
fn(v)
|
||||
}
|
||||
}
|
||||
|
||||
// IsEmpty checks the set is empty or not
|
||||
func (s Set[T]) IsEmpty() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
// Size get the number of elements in set
|
||||
func (s Set[T]) Size() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// Values return all values of set
|
||||
func (s Set[T]) Values() []T {
|
||||
values := make([]T, 0, 0)
|
||||
|
||||
s.Iterate(func(value T) {
|
||||
values = append(values, value)
|
||||
})
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
// Union creates a new set contain all element of set s and other
|
||||
func (s Set[T]) Union(other Set[T]) Set[T] {
|
||||
set := s.Clone()
|
||||
set.Add(other.Values()...)
|
||||
return set
|
||||
}
|
||||
|
||||
// Intersection creates a new set whose element both be contained in set s and other
|
||||
func (s Set[T]) Intersection(other Set[T]) Set[T] {
|
||||
set := NewSet[T]()
|
||||
s.Iterate(func(value T) {
|
||||
if other.Contain(value) {
|
||||
set.Add(value)
|
||||
}
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
129
datastructure/set/set_test.go
Normal file
129
datastructure/set/set_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestSet_Add(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Add")
|
||||
|
||||
set := NewSet[int]()
|
||||
set.Add(1, 2, 3)
|
||||
|
||||
expected := NewSet(1, 2, 3)
|
||||
|
||||
assert.Equal(true, set.Equal(expected))
|
||||
}
|
||||
|
||||
func TestSet_Contain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Contain")
|
||||
|
||||
set := NewSet[int]()
|
||||
set.Add(1, 2, 3)
|
||||
|
||||
assert.Equal(true, set.Contain(1))
|
||||
assert.Equal(false, set.Contain(4))
|
||||
}
|
||||
|
||||
func TestSet_ContainAll(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_ContainAll")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(1, 2)
|
||||
set3 := NewSet(1, 2, 3, 4)
|
||||
|
||||
assert.Equal(true, set1.ContainAll(set2))
|
||||
assert.Equal(false, set1.ContainAll(set3))
|
||||
}
|
||||
|
||||
func TestSet_Clone(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Clone")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := set1.Clone()
|
||||
|
||||
assert.Equal(true, set1.Size() == set2.Size())
|
||||
assert.Equal(true, set1.ContainAll(set2))
|
||||
}
|
||||
|
||||
func TestSet_Delete(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Delete")
|
||||
|
||||
set := NewSet[int]()
|
||||
set.Add(1, 2, 3)
|
||||
set.Delete(3)
|
||||
|
||||
expected := NewSet(1, 2)
|
||||
|
||||
assert.Equal(true, set.Equal(expected))
|
||||
}
|
||||
|
||||
func TestSet_Equal(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Equal")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(1, 2, 3)
|
||||
set3 := NewSet(1, 2, 3, 4)
|
||||
|
||||
assert.Equal(true, set1.Equal(set2))
|
||||
assert.Equal(false, set1.Equal(set3))
|
||||
}
|
||||
|
||||
func TestSet_Iterate(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Iterate")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
arr := []int{}
|
||||
set.Iterate(func(value int) {
|
||||
arr = append(arr, value)
|
||||
})
|
||||
|
||||
assert.Equal(3, len(arr))
|
||||
}
|
||||
|
||||
func TestSet_IsEmpty(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_IsEmpty")
|
||||
|
||||
set := NewSet[int]()
|
||||
assert.Equal(true, set.IsEmpty())
|
||||
}
|
||||
|
||||
func TestSet_Size(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Size")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
assert.Equal(3, set.Size())
|
||||
}
|
||||
|
||||
func TestSet_Values(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Values")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
values := set.Values()
|
||||
|
||||
assert.Equal(3, len(values))
|
||||
}
|
||||
|
||||
func TestSet_Union(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Union")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
expected := NewSet(1, 2, 3, 4, 5)
|
||||
unionSet := set1.Union(set2)
|
||||
|
||||
assert.Equal(expected, unionSet)
|
||||
}
|
||||
|
||||
func TestSet_Intersection(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Intersection")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
expected := NewSet(2, 3)
|
||||
intersectionSet := set1.Intersection(set2)
|
||||
|
||||
assert.Equal(expected, intersectionSet)
|
||||
}
|
||||
62
datastructure/stack/arraystack.go
Normal file
62
datastructure/stack/arraystack.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package datastructure
|
||||
|
||||
import "errors"
|
||||
|
||||
// ArrayStack implements stack with slice
|
||||
type ArrayStack[T any] struct {
|
||||
data []T
|
||||
length int
|
||||
}
|
||||
|
||||
// NewArrayStack return a empty ArrayStack pointer
|
||||
func NewArrayStack[T any]() *ArrayStack[T] {
|
||||
return &ArrayStack[T]{data: []T{}, length: 0}
|
||||
}
|
||||
|
||||
// Data return stack data
|
||||
func (s *ArrayStack[T]) Data() []T {
|
||||
return s.data
|
||||
}
|
||||
|
||||
// Size return length of stack data
|
||||
func (s *ArrayStack[T]) Size() int {
|
||||
return s.length
|
||||
}
|
||||
|
||||
// IsEmpty checks if stack is empty or not
|
||||
func (s *ArrayStack[T]) IsEmpty() bool {
|
||||
return s.length == 0
|
||||
}
|
||||
|
||||
// Push element into stack
|
||||
func (s *ArrayStack[T]) Push(value T) {
|
||||
s.data = append([]T{value}, s.data...)
|
||||
s.length++
|
||||
}
|
||||
|
||||
// Pop delete the top element of stack then return it, if stack is empty, return nil and error
|
||||
func (s *ArrayStack[T]) Pop() (*T, error) {
|
||||
if s.IsEmpty() {
|
||||
return nil, errors.New("stack is empty")
|
||||
}
|
||||
|
||||
topItem := s.data[0]
|
||||
s.data = s.data[1:]
|
||||
s.length--
|
||||
|
||||
return &topItem, nil
|
||||
}
|
||||
|
||||
// Peak return the top element of stack then return it
|
||||
func (s *ArrayStack[T]) Peak() (*T, error) {
|
||||
if s.IsEmpty() {
|
||||
return nil, errors.New("stack is empty")
|
||||
}
|
||||
return &s.data[0], nil
|
||||
}
|
||||
|
||||
// Clear the stack data
|
||||
func (s *ArrayStack[T]) Clear() {
|
||||
s.data = []T{}
|
||||
s.length = 0
|
||||
}
|
||||
77
datastructure/stack/arraystack_test.go
Normal file
77
datastructure/stack/arraystack_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestArrayStack_Push(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Push")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
stack.Push(1)
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
values := stack.Data()
|
||||
length := stack.Size()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
assert.Equal(3, length)
|
||||
}
|
||||
|
||||
func TestArrayStack_Pop(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Pop")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
_, err := stack.Pop()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
stack.Push(1)
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
topItem, err := stack.Pop()
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{2, 1}
|
||||
assert.Equal(expected, stack.Data())
|
||||
}
|
||||
|
||||
func TestArrayStack_Peak(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Peak")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
_, err := stack.Peak()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
stack.Push(1)
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
topItem, err := stack.Peak()
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
assert.Equal(expected, stack.Data())
|
||||
}
|
||||
|
||||
func TestArrayStack_Clear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Clear")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
assert.Equal(true, stack.IsEmpty())
|
||||
assert.Equal(0, stack.Size())
|
||||
|
||||
stack.Push(1)
|
||||
assert.Equal(false, stack.IsEmpty())
|
||||
assert.Equal(1, stack.Size())
|
||||
|
||||
stack.Clear()
|
||||
assert.Equal(true, stack.IsEmpty())
|
||||
assert.Equal(0, stack.Size())
|
||||
}
|
||||
94
datastructure/stack/linkedstack.go
Normal file
94
datastructure/stack/linkedstack.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
)
|
||||
|
||||
// LinkedStack implements stack with link list
|
||||
type LinkedStack[T any] struct {
|
||||
top *datastructure.StackNode[T]
|
||||
length int
|
||||
}
|
||||
|
||||
// NewLinkedStack return a empty LinkedStack pointer
|
||||
func NewLinkedStack[T any]() *LinkedStack[T] {
|
||||
return &LinkedStack[T]{top: nil, length: 0}
|
||||
}
|
||||
|
||||
// Data return stack data
|
||||
func (s *LinkedStack[T]) Data() []T {
|
||||
res := []T{}
|
||||
current := s.top
|
||||
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Size return length of stack data
|
||||
func (s *LinkedStack[T]) Size() int {
|
||||
return s.length
|
||||
}
|
||||
|
||||
// IsEmpty checks if stack is empty or not
|
||||
func (s *LinkedStack[T]) IsEmpty() bool {
|
||||
return s.length == 0
|
||||
}
|
||||
|
||||
// Push element into stack
|
||||
func (s *LinkedStack[T]) Push(value T) {
|
||||
newNode := datastructure.NewStackNode(value)
|
||||
top := s.top
|
||||
if top == nil {
|
||||
s.top = newNode
|
||||
} else {
|
||||
newNode.Next = top
|
||||
s.top = newNode
|
||||
}
|
||||
|
||||
s.length++
|
||||
}
|
||||
|
||||
// Pop delete the top element of stack then return it, if stack is empty, return nil and error
|
||||
func (s *LinkedStack[T]) Pop() (*T, error) {
|
||||
if s.IsEmpty() {
|
||||
return nil, errors.New("stack is empty")
|
||||
}
|
||||
|
||||
top := s.top
|
||||
s.top = s.top.Next
|
||||
s.length--
|
||||
|
||||
return &top.Value, nil
|
||||
}
|
||||
|
||||
// Peak return the top element of stack then return it
|
||||
func (s *LinkedStack[T]) Peak() (*T, error) {
|
||||
if s.IsEmpty() {
|
||||
return nil, errors.New("stack is empty")
|
||||
}
|
||||
return &s.top.Value, nil
|
||||
}
|
||||
|
||||
// Clear clear the stack data
|
||||
func (s *LinkedStack[T]) Clear() {
|
||||
s.top = nil
|
||||
s.length = 0
|
||||
}
|
||||
|
||||
// Print all nodes info of stack link
|
||||
func (s *LinkedStack[T]) Print() {
|
||||
current := s.top
|
||||
info := "[ "
|
||||
for current != nil {
|
||||
info += fmt.Sprintf("%+v, ", current)
|
||||
current = current.Next
|
||||
}
|
||||
info += " ]"
|
||||
fmt.Println(info)
|
||||
}
|
||||
80
datastructure/stack/linkedstack_test.go
Normal file
80
datastructure/stack/linkedstack_test.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestLinkedStack_Push(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Push")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
stack.Push(1)
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
stack.Print()
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
values := stack.Data()
|
||||
size := stack.Size()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
assert.Equal(3, size)
|
||||
}
|
||||
|
||||
func TestLinkedStack_Pop(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
_, err := stack.Pop()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
stack.Push(1)
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
topItem, err := stack.Pop()
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{2, 1}
|
||||
stack.Print()
|
||||
assert.Equal(expected, stack.Data())
|
||||
}
|
||||
|
||||
func TestLinkedStack_Peak(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
_, err := stack.Peak()
|
||||
assert.IsNotNil(err)
|
||||
|
||||
stack.Push(1)
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
topItem, err := stack.Peak()
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
assert.Equal(expected, stack.Data())
|
||||
}
|
||||
|
||||
func TestLinkedStack_Empty(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
assert.Equal(true, stack.IsEmpty())
|
||||
assert.Equal(0, stack.Size())
|
||||
|
||||
stack.Push(1)
|
||||
assert.Equal(false, stack.IsEmpty())
|
||||
assert.Equal(1, stack.Size())
|
||||
|
||||
stack.Clear()
|
||||
assert.Equal(true, stack.IsEmpty())
|
||||
assert.Equal(0, stack.Size())
|
||||
}
|
||||
83
datastructure/tree/bstree.go
Normal file
83
datastructure/tree/bstree.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
// BSTree is a binary search tree data structure in which each node has at most two children,
|
||||
// which are referred to as the left child and the right child.
|
||||
// In BSTree: leftNode < rootNode < rightNode
|
||||
// type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
type BSTree[T any] struct {
|
||||
root *datastructure.TreeNode[T]
|
||||
}
|
||||
|
||||
// NewBSTree create a BSTree pointer
|
||||
func NewBSTree[T any](rootData T) *BSTree[T] {
|
||||
root := datastructure.NewTreeNode(rootData)
|
||||
return &BSTree[T]{root}
|
||||
}
|
||||
|
||||
// InsertNode insert data into BSTree
|
||||
func (t *BSTree[T]) InsertNode(data T, comparator lancetconstraints.Comparator) {
|
||||
root := t.root
|
||||
newNode := datastructure.NewTreeNode(data)
|
||||
if root == nil {
|
||||
t.root = newNode
|
||||
} else {
|
||||
insertTreeNode(root, newNode, comparator)
|
||||
}
|
||||
}
|
||||
|
||||
// DeletetNode delete data into BSTree
|
||||
func (t *BSTree[T]) DeletetNode(data T, comparator lancetconstraints.Comparator) {
|
||||
deleteTreeNode(t.root, data, comparator)
|
||||
}
|
||||
|
||||
// NodeLevel get node level in BSTree
|
||||
func (t *BSTree[T]) NodeLevel(node *datastructure.TreeNode[T]) int {
|
||||
if node == nil {
|
||||
return 0
|
||||
}
|
||||
left := float64(t.NodeLevel(node.Left))
|
||||
right := float64(t.NodeLevel(node.Right))
|
||||
|
||||
return int(math.Max(left, right)) + 1
|
||||
}
|
||||
|
||||
// PreOrderTraverse traverse tree node in pre order
|
||||
func (t *BSTree[T]) PreOrderTraverse() []T {
|
||||
return preOrderTraverse(t.root)
|
||||
}
|
||||
|
||||
// PostOrderTraverse traverse tree node in post order
|
||||
func (t *BSTree[T]) PostOrderTraverse() []T {
|
||||
return postOrderTraverse(t.root)
|
||||
}
|
||||
|
||||
// InOrderTraverse traverse tree node in mid order
|
||||
func (t *BSTree[T]) InOrderTraverse() []T {
|
||||
return inOrderTraverse(t.root)
|
||||
}
|
||||
|
||||
// LevelOrderTraverse traverse tree node in level order
|
||||
func (t *BSTree[T]) LevelOrderTraverse() []T {
|
||||
traversal := make([]T, 0)
|
||||
levelOrderTraverse(t.root, &traversal)
|
||||
return traversal
|
||||
}
|
||||
|
||||
// Depth returns the calculated depth of a binary saerch tree
|
||||
func (t *BSTree[T]) Depth() int {
|
||||
return calculateDepth(t.root, 0)
|
||||
}
|
||||
|
||||
// Print the bstree structure
|
||||
func (t *BSTree[T]) Print() {
|
||||
maxLevel := t.NodeLevel(t.root)
|
||||
nodes := []*datastructure.TreeNode[T]{t.root}
|
||||
printTreeNodes(nodes, 1, maxLevel)
|
||||
}
|
||||
142
datastructure/tree/bstree_test.go
Normal file
142
datastructure/tree/bstree_test.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestBSTree_InsertNode(t *testing.T) {
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
bstree.Print()
|
||||
}
|
||||
|
||||
func TestBSTree_PreOrderTraverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
acturl := bstree.PreOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_PostOrderTraverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
acturl := bstree.PostOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_InOrderTraverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
acturl := bstree.InOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
bstree.Print()
|
||||
|
||||
acturl := bstree.LevelOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_DeletetNode(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_DeletetNode")
|
||||
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
bstree.Print()
|
||||
|
||||
bstree.DeletetNode(4, comparator)
|
||||
bstree.Print()
|
||||
acturl1 := bstree.InOrderTraverse()
|
||||
t.Log(acturl1)
|
||||
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
||||
|
||||
//todo
|
||||
// bstree.DeletetNode(6, comparator)
|
||||
// bstree.Print()
|
||||
// acturl2 := bstree.InOrderTraverse()
|
||||
// t.Log(acturl2)
|
||||
// assert.Equal([]int{2, 5, 7}, acturl2)
|
||||
}
|
||||
|
||||
func TestBSTree_Depth(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBSTree_Depth")
|
||||
|
||||
bstree := NewBSTree(6)
|
||||
|
||||
comparator := &intComparator{}
|
||||
bstree.InsertNode(7, comparator)
|
||||
bstree.InsertNode(5, comparator)
|
||||
bstree.InsertNode(2, comparator)
|
||||
bstree.InsertNode(4, comparator)
|
||||
|
||||
bstree.Print()
|
||||
|
||||
assert.Equal(bstree.Depth(), 4)
|
||||
}
|
||||
224
datastructure/tree/tree_internal.go
Normal file
224
datastructure/tree/tree_internal.go
Normal file
@@ -0,0 +1,224 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
func preOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
|
||||
data := []T{}
|
||||
if node != nil {
|
||||
data = append(data, node.Data)
|
||||
data = append(data, preOrderTraverse(node.Left)...)
|
||||
data = append(data, preOrderTraverse(node.Right)...)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func postOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
|
||||
data := []T{}
|
||||
if node != nil {
|
||||
data = append(data, preOrderTraverse(node.Left)...)
|
||||
data = append(data, preOrderTraverse(node.Right)...)
|
||||
data = append(data, node.Data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func inOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
|
||||
data := []T{}
|
||||
if node != nil {
|
||||
data = append(data, inOrderTraverse(node.Left)...)
|
||||
data = append(data, node.Data)
|
||||
data = append(data, inOrderTraverse(node.Right)...)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func preOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%v, ", node.Data)
|
||||
preOrderPrint(node.Left)
|
||||
preOrderPrint(node.Right)
|
||||
}
|
||||
|
||||
func postOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
preOrderPrint(node.Left)
|
||||
preOrderPrint(node.Right)
|
||||
fmt.Printf("%v, ", node.Data)
|
||||
}
|
||||
|
||||
func inOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
inOrderPrint(node.Left)
|
||||
fmt.Printf("%v, ", node.Data)
|
||||
inOrderPrint(node.Right)
|
||||
}
|
||||
|
||||
func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T) {
|
||||
var q []*datastructure.TreeNode[T] // queue
|
||||
var n *datastructure.TreeNode[T] // temp node
|
||||
|
||||
q = append(q, root)
|
||||
|
||||
for len(q) != 0 {
|
||||
n, q = q[0], q[1:]
|
||||
*traversal = append(*traversal, n.Data)
|
||||
if n.Left != nil {
|
||||
q = append(q, n.Left)
|
||||
}
|
||||
if n.Right != nil {
|
||||
q = append(q, n.Right)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) {
|
||||
if comparator.Compare(newNode.Data, rootNode.Data) == -1 {
|
||||
if rootNode.Left == nil {
|
||||
rootNode.Left = newNode
|
||||
} else {
|
||||
insertTreeNode(rootNode.Left, newNode, comparator)
|
||||
}
|
||||
} else {
|
||||
if rootNode.Right == nil {
|
||||
rootNode.Right = newNode
|
||||
} else {
|
||||
insertTreeNode(rootNode.Right, newNode, comparator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo, delete root node failed
|
||||
func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator lancetconstraints.Comparator) *datastructure.TreeNode[T] {
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
if comparator.Compare(data, node.Data) == -1 {
|
||||
node.Left = deleteTreeNode(node.Left, data, comparator)
|
||||
} else if comparator.Compare(data, node.Data) == 1 {
|
||||
node.Right = deleteTreeNode(node.Right, data, comparator)
|
||||
} else {
|
||||
if node.Left == nil {
|
||||
node = node.Right
|
||||
} else if node.Right == nil {
|
||||
node = node.Left
|
||||
} else {
|
||||
l := node.Right
|
||||
d := inOrderSuccessor(l)
|
||||
d.Left = node.Left
|
||||
return node.Right
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func inOrderSuccessor[T any](root *datastructure.TreeNode[T]) *datastructure.TreeNode[T] {
|
||||
cur := root
|
||||
for cur.Left != nil {
|
||||
cur = cur.Left
|
||||
}
|
||||
return cur
|
||||
}
|
||||
|
||||
func printTreeNodes[T any](nodes []*datastructure.TreeNode[T], level, maxLevel int) {
|
||||
if len(nodes) == 0 || isAllNil(nodes) {
|
||||
return
|
||||
}
|
||||
|
||||
floor := maxLevel - level
|
||||
endgeLines := int(math.Pow(float64(2), (math.Max(float64(floor)-1, 0))))
|
||||
firstSpaces := int(math.Pow(float64(2), float64(floor))) - 1
|
||||
betweenSpaces := int(math.Pow(float64(2), float64(floor)+1)) - 1
|
||||
|
||||
printSpaces(firstSpaces)
|
||||
|
||||
newNodes := []*datastructure.TreeNode[T]{}
|
||||
for _, node := range nodes {
|
||||
if node != nil {
|
||||
fmt.Printf("%v", node.Data)
|
||||
newNodes = append(newNodes, node.Left)
|
||||
newNodes = append(newNodes, node.Right)
|
||||
} else {
|
||||
newNodes = append(newNodes, nil)
|
||||
newNodes = append(newNodes, nil)
|
||||
printSpaces(1)
|
||||
}
|
||||
|
||||
printSpaces(betweenSpaces)
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
|
||||
for i := 1; i <= endgeLines; i++ {
|
||||
for j := 0; j < len(nodes); j++ {
|
||||
printSpaces(firstSpaces - i)
|
||||
if nodes[j] == nil {
|
||||
printSpaces(endgeLines + endgeLines + i + 1)
|
||||
continue
|
||||
}
|
||||
|
||||
if nodes[j].Left != nil {
|
||||
fmt.Print("/")
|
||||
} else {
|
||||
printSpaces(1)
|
||||
}
|
||||
|
||||
printSpaces(i + i - 1)
|
||||
|
||||
if nodes[j].Right != nil {
|
||||
fmt.Print("\\")
|
||||
} else {
|
||||
printSpaces(1)
|
||||
}
|
||||
printSpaces(endgeLines + endgeLines - 1)
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
printTreeNodes(newNodes, level+1, maxLevel)
|
||||
}
|
||||
|
||||
// printSpaces
|
||||
func printSpaces(n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
}
|
||||
|
||||
func isAllNil[T any](nodes []*datastructure.TreeNode[T]) bool {
|
||||
for _, v := range nodes {
|
||||
if v != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func calculateDepth[T any](node *datastructure.TreeNode[T], depth int) int {
|
||||
if node == nil {
|
||||
return depth
|
||||
}
|
||||
return max(calculateDepth(node.Left, depth+1), calculateDepth(node.Right, depth+1))
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
60
datetime/conversion.go
Normal file
60
datetime/conversion.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license.
|
||||
|
||||
package datetime
|
||||
|
||||
import "time"
|
||||
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
|
||||
// NewUnixNow return unix timestamp of current time
|
||||
func NewUnixNow() *theTime {
|
||||
return &theTime{unix: time.Now().Unix()}
|
||||
}
|
||||
|
||||
// NewUnix return unix timestamp of specified time
|
||||
func NewUnix(unix int64) *theTime {
|
||||
return &theTime{unix: unix}
|
||||
}
|
||||
|
||||
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss"
|
||||
func NewFormat(t string) (*theTime, error) {
|
||||
timeLayout := "2006-01-02 15:04:05"
|
||||
loc := time.FixedZone("CST", 8*3600)
|
||||
tt, err := time.ParseInLocation(timeLayout, t, loc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &theTime{unix: tt.Unix()}, nil
|
||||
}
|
||||
|
||||
// NewISO8601 return unix timestamp of specified iso8601 time string
|
||||
func NewISO8601(iso8601 string) (*theTime, error) {
|
||||
t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &theTime{unix: t.Unix()}, nil
|
||||
}
|
||||
|
||||
// ToUnix return unix timestamp
|
||||
func (t *theTime) ToUnix() int64 {
|
||||
return t.unix
|
||||
}
|
||||
|
||||
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time
|
||||
func (t *theTime) ToFormat() string {
|
||||
return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// ToFormatForTpl return the time string which format is specified tpl
|
||||
func (t *theTime) ToFormatForTpl(tpl string) string {
|
||||
return time.Unix(t.unix, 0).Format(tpl)
|
||||
}
|
||||
|
||||
// ToFormatForTpl return iso8601 time string
|
||||
func (t *theTime) ToIso8601() string {
|
||||
return time.Unix(t.unix, 0).Format(time.RFC3339)
|
||||
}
|
||||
53
datetime/conversion_test.go
Normal file
53
datetime/conversion_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestToUnix(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToUnix")
|
||||
|
||||
tm1 := NewUnixNow()
|
||||
unixTimestamp := tm1.ToUnix()
|
||||
tm2 := NewUnix(unixTimestamp)
|
||||
|
||||
assert.Equal(tm1, tm2)
|
||||
}
|
||||
|
||||
func TestToFormat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToFormat")
|
||||
|
||||
_, err := NewFormat("2022/03/18 17:04:05")
|
||||
assert.IsNotNil(err)
|
||||
|
||||
tm, err := NewFormat("2022-03-18 17:04:05")
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log("ToFormat -> ", tm.ToFormat())
|
||||
}
|
||||
|
||||
func TestToFormatForTpl(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToFormatForTpl")
|
||||
|
||||
_, err := NewFormat("2022/03/18 17:04:05")
|
||||
assert.IsNotNil(err)
|
||||
|
||||
tm, err := NewFormat("2022-03-18 17:04:05")
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
|
||||
}
|
||||
|
||||
func TestToIso8601(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToIso8601")
|
||||
|
||||
_, err := NewISO8601("2022-03-18 17:04:05")
|
||||
assert.IsNotNil(err)
|
||||
|
||||
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log("ToIso8601 -> ", tm.ToIso8601())
|
||||
}
|
||||
@@ -110,3 +110,73 @@ func FormatStrToTime(str, format string) (time.Time, error) {
|
||||
|
||||
return time.Parse(v, str)
|
||||
}
|
||||
|
||||
// BeginOfMinute return beginning minute time of day
|
||||
func BeginOfMinute(t time.Time) time.Time {
|
||||
y, m, d := t.Date()
|
||||
return time.Date(y, m, d, t.Hour(), t.Minute(), 0, 0, t.Location())
|
||||
}
|
||||
|
||||
// EndOfMinute return end minute time of day
|
||||
func EndOfMinute(t time.Time) time.Time {
|
||||
y, m, d := t.Date()
|
||||
return time.Date(y, m, d, t.Hour(), t.Minute(), 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
}
|
||||
|
||||
// BeginOfHour return beginning hour time of day
|
||||
func BeginOfHour(t time.Time) time.Time {
|
||||
y, m, d := t.Date()
|
||||
return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location())
|
||||
}
|
||||
|
||||
// EndOfHour return end hour time of day
|
||||
func EndOfHour(t time.Time) time.Time {
|
||||
y, m, d := t.Date()
|
||||
return time.Date(y, m, d, t.Hour(), 59, 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
}
|
||||
|
||||
// BeginOfDay return beginning hour time of day
|
||||
func BeginOfDay(t time.Time) time.Time {
|
||||
y, m, d := t.Date()
|
||||
return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
|
||||
}
|
||||
|
||||
// EndOfDay return end time of day
|
||||
func EndOfDay(t time.Time) time.Time {
|
||||
y, m, d := t.Date()
|
||||
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
}
|
||||
|
||||
// BeginOfWeek return beginning week, week begin from Sunday
|
||||
func BeginOfWeek(t time.Time) time.Time {
|
||||
y, m, d := t.AddDate(0, 0, 0-int(BeginOfDay(t).Weekday())).Date()
|
||||
return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
|
||||
}
|
||||
|
||||
// EndOfWeek return end week time, week end with Saturday
|
||||
func EndOfWeek(t time.Time) time.Time {
|
||||
y, m, d := BeginOfWeek(t).AddDate(0, 0, 7).Add(-time.Nanosecond).Date()
|
||||
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
}
|
||||
|
||||
// BeginOfMonth return beginning of month
|
||||
func BeginOfMonth(t time.Time) time.Time {
|
||||
y, m, _ := t.Date()
|
||||
return time.Date(y, m, 1, 0, 0, 0, 0, t.Location())
|
||||
}
|
||||
|
||||
// EndOfMonth return end of month
|
||||
func EndOfMonth(t time.Time) time.Time {
|
||||
return BeginOfMonth(t).AddDate(0, 1, 0).Add(-time.Nanosecond)
|
||||
}
|
||||
|
||||
// BeginOfYear return beginning of year
|
||||
func BeginOfYear(t time.Time) time.Time {
|
||||
y, _, _ := t.Date()
|
||||
return time.Date(y, time.January, 1, 0, 0, 0, 0, t.Location())
|
||||
}
|
||||
|
||||
// EndOfYear return end of year
|
||||
func EndOfYear(t time.Time) time.Time {
|
||||
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
|
||||
}
|
||||
|
||||
@@ -1,103 +1,72 @@
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestAddDay(t *testing.T) {
|
||||
now := time.Now()
|
||||
assert := internal.NewAssert(t, "TestAddDay")
|
||||
|
||||
now := time.Now()
|
||||
after2Days := AddDay(now, 2)
|
||||
diff1 := after2Days.Sub(now)
|
||||
if diff1.Hours() != 48 {
|
||||
utils.LogFailedTestInfo(t, "AddDay", now, 48, diff1.Hours())
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(float64(48), diff1.Hours())
|
||||
|
||||
before2Days := AddDay(now, -2)
|
||||
diff2 := before2Days.Sub(now)
|
||||
if diff2.Hours() != -48 {
|
||||
utils.LogFailedTestInfo(t, "AddDay", now, -48, diff2.Hours())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(float64(-48), diff2.Hours())
|
||||
}
|
||||
func TestAddHour(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
func TestAddHour(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAddHour")
|
||||
|
||||
now := time.Now()
|
||||
after2Hours := AddHour(now, 2)
|
||||
diff1 := after2Hours.Sub(now)
|
||||
if diff1.Hours() != 2 {
|
||||
utils.LogFailedTestInfo(t, "AddHour", now, 2, diff1.Hours())
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(float64(2), diff1.Hours())
|
||||
|
||||
before2Hours := AddHour(now, -2)
|
||||
diff2 := before2Hours.Sub(now)
|
||||
if diff2.Hours() != -2 {
|
||||
utils.LogFailedTestInfo(t, "AddHour", now, -2, diff2.Hours())
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(float64(-2), diff2.Hours())
|
||||
}
|
||||
|
||||
func TestAddMinute(t *testing.T) {
|
||||
now := time.Now()
|
||||
assert := internal.NewAssert(t, "TestAddMinute")
|
||||
|
||||
now := time.Now()
|
||||
after2Minutes := AddMinute(now, 2)
|
||||
diff1 := after2Minutes.Sub(now)
|
||||
if diff1.Minutes() != 2 {
|
||||
utils.LogFailedTestInfo(t, "AddMinute", now, 2, diff1.Minutes())
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(float64(2), diff1.Minutes())
|
||||
|
||||
before2Minutes := AddMinute(now, -2)
|
||||
diff2 := before2Minutes.Sub(now)
|
||||
if diff2.Minutes() != -2 {
|
||||
utils.LogFailedTestInfo(t, "AddMinute", now, -2, diff2.Minutes())
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(float64(-2), diff2.Minutes())
|
||||
}
|
||||
|
||||
func TestGetNowDate(t *testing.T) {
|
||||
date := GetNowDate()
|
||||
assert := internal.NewAssert(t, "TestGetNowDate")
|
||||
expected := time.Now().Format("2006-01-02")
|
||||
if date != expected {
|
||||
utils.LogFailedTestInfo(t, "GetNowDate", "", expected, date)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(expected, GetNowDate())
|
||||
}
|
||||
|
||||
func TestGetNotTime(t *testing.T) {
|
||||
ts := GetNowTime()
|
||||
assert := internal.NewAssert(t, "TestGetNotTime")
|
||||
expected := time.Now().Format("15:04:05")
|
||||
if ts != expected {
|
||||
utils.LogFailedTestInfo(t, "GetNowTime", "", expected, ts)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(expected, GetNowTime())
|
||||
}
|
||||
|
||||
func TestGetNowDateTime(t *testing.T) {
|
||||
ts := GetNowDateTime()
|
||||
assert := internal.NewAssert(t, "TestGetNowDateTime")
|
||||
expected := time.Now().Format("2006-01-02 15:04:05")
|
||||
if ts != expected {
|
||||
utils.LogFailedTestInfo(t, "GetNowDateTime", "", expected, ts)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(expected, GetNowDateTime())
|
||||
}
|
||||
|
||||
//todo
|
||||
//func TestGetZeroHourTimestamp(t *testing.T) {
|
||||
// ts := GetZeroHourTimestamp()
|
||||
// expected := time.Now().UTC().Unix() - 8*3600
|
||||
// if ts != expected {
|
||||
// utils.LogFailedTestInfo(t, "GetZeroHourTimestamp", "", expected, ts)
|
||||
// t.FailNow()
|
||||
// }
|
||||
//}
|
||||
|
||||
func TestFormatTimeToStr(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFormatTimeToStr")
|
||||
|
||||
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
|
||||
cases := []string{
|
||||
"yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd",
|
||||
@@ -110,16 +79,15 @@ func TestFormatTimeToStr(t *testing.T) {
|
||||
"16:04:08", "2021/01"}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res := FormatTimeToStr(datetime, cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
actual := FormatTimeToStr(datetime, cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatStrToTime(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFormatStrToTime")
|
||||
|
||||
formats := []string{
|
||||
"2006-01-02 15:04:05", "2006-01-02",
|
||||
"02-01-06 15:04:05", "2006/01/02 15:04:05",
|
||||
@@ -135,14 +103,131 @@ func TestFormatStrToTime(t *testing.T) {
|
||||
"2021/01"}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res, err := FormatStrToTime(datetimeStr[i], cases[i])
|
||||
actual, err := FormatStrToTime(datetimeStr[i], cases[i])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected, _ := time.Parse(formats[i], datetimeStr[i])
|
||||
if res != expected {
|
||||
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeginOfMinute(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBeginOfMinute")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 48, 0, 0, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := BeginOfMinute(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestEndOfMinute(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfMinute")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 48, 59, 999999999, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := EndOfMinute(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBeginOfHour(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBeginOfHour")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 0, 0, 0, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := BeginOfHour(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestEndOfHour(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfHour")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 59, 59, 999999999, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := EndOfHour(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBeginOfDay(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBeginOfDay")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 0, 0, 0, 0, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := BeginOfDay(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestEndOfDay(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfDay")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 23, 59, 59, 999999999, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := EndOfDay(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBeginOfWeek(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBeginOfWeek")
|
||||
|
||||
expected := time.Date(2022, 2, 13, 0, 0, 0, 0, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := BeginOfWeek(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestEndOfWeek(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfWeek")
|
||||
|
||||
expected := time.Date(2022, 2, 19, 23, 59, 59, 999999999, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := EndOfWeek(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBeginOfMonth(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBeginOfMonth")
|
||||
|
||||
expected := time.Date(2022, 2, 1, 0, 0, 0, 0, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := BeginOfMonth(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestEndOfMonth(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfMonth")
|
||||
|
||||
expected := time.Date(2022, 2, 28, 23, 59, 59, 999999999, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := EndOfMonth(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBeginOfYear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBeginOfYear")
|
||||
|
||||
expected := time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := BeginOfYear(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestEndOfYear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfYear")
|
||||
|
||||
expected := time.Date(2022, 12, 31, 23, 59, 59, 999999999, time.Local)
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
actual := EndOfYear(td)
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
593
docs/algorithm.md
Normal file
593
docs/algorithm.md
Normal file
@@ -0,0 +1,593 @@
|
||||
# Algorithm
|
||||
Package algorithm implements some basic algorithm. eg. sort, search.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [BubbleSort](#BubbleSort)
|
||||
- [CountSort](#CountSort)
|
||||
- [HeapSort](#HeapSort)
|
||||
- [InsertionSort](#InsertionSort)
|
||||
- [MergeSort](#MergeSort)
|
||||
- [QuickSort](#QuickSort)
|
||||
- [SelectionSort](#SelectionSort)
|
||||
- [ShellSort](#ShellSort)
|
||||
- [BinarySearch](#BinarySearch)
|
||||
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
||||
- [LinearSearch](#LinearSearch)
|
||||
- [LRUCache](#LRUCache)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="BubbleSort">BubbleSort</span>
|
||||
<p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.BubbleSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="InsertionSort">InsertionSort</span>
|
||||
<p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type people struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
// PeopleAageComparator sort people slice by age field
|
||||
type peopleAgeComparator struct{}
|
||||
|
||||
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
|
||||
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
p1, _ := v1.(people)
|
||||
p2, _ := v2.(people)
|
||||
|
||||
//ascending order
|
||||
if p1.Age < p2.Age {
|
||||
return -1
|
||||
} else if p1.Age > p2.Age {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
|
||||
//decending order
|
||||
// if p1.Age > p2.Age {
|
||||
// return -1
|
||||
// } else if p1.Age < p2.Age {
|
||||
// return 1
|
||||
// }
|
||||
}
|
||||
|
||||
var peoples = []people{
|
||||
{Name: "a", Age: 20},
|
||||
{Name: "b", Age: 10},
|
||||
{Name: "c", Age: 17},
|
||||
{Name: "d", Age: 8},
|
||||
{Name: "e", Age: 28},
|
||||
}
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeople := algorithm.InsertionSort(peoples, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="SelectionSort">SelectionSort</span>
|
||||
<p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.SelectionSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ShellSort">ShellSort</span>
|
||||
<p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.ShellSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="QuickSort">QuickSort</span>
|
||||
<p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="HeapSort">HeapSort</span>
|
||||
<p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.HeapSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="MergeSort">MergeSort</span>
|
||||
<p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.MergeSort(intSlice, 0, len(intSlice)-1, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CountSort">CountSort</span>
|
||||
<p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.CountSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BinarySearch">BinarySearch</span>
|
||||
<p>BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
comparator := &intComparator{}
|
||||
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(foundIndex) //4
|
||||
|
||||
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(notFoundIndex) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
|
||||
<p>BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
comparator := &intComparator{}
|
||||
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(foundIndex) //4
|
||||
|
||||
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(notFoundIndex) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinearSearch">LinearSearch</span>
|
||||
<p>LinearSearch Simple linear search algorithm that iterates over all elements of an slice. If a target is found, the index of the target is returned. Else the function return -1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
|
||||
fmt.Println(foundIndex) //2
|
||||
|
||||
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
|
||||
fmt.Println(notFoundIndex) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LRUCache">LRUCache</span>
|
||||
<p>LRUCache implements mem cache with lru.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
|
||||
func (l *LRUCache[K, V]) Get(key K) (V, bool)
|
||||
func (l *LRUCache[K, V]) Put(key K, value V)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cache := algorithm.NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0) // ok -> false
|
||||
|
||||
v, ok := cache.Get(1) // v->1, ok->true
|
||||
|
||||
}
|
||||
```
|
||||
593
docs/algorithm_zh-CN.md
Normal file
593
docs/algorithm_zh-CN.md
Normal file
@@ -0,0 +1,593 @@
|
||||
# Algorithm
|
||||
algorithm算法包实现一些基本算法,sort,search,lrucache。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [BubbleSort](#BubbleSort)
|
||||
- [CountSort](#CountSort)
|
||||
- [HeapSort](#HeapSort)
|
||||
- [InsertionSort](#InsertionSort)
|
||||
- [MergeSort](#MergeSort)
|
||||
- [QuickSort](#QuickSort)
|
||||
- [SelectionSort](#SelectionSort)
|
||||
- [ShellSort](#ShellSort)
|
||||
- [BinarySearch](#BinarySearch)
|
||||
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
||||
- [LinearSearch](#LinearSearch)
|
||||
- [LRUCache](#LRUCache)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="BubbleSort">BubbleSort</span>
|
||||
<p>冒泡排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.BubbleSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="InsertionSort">InsertionSort</span>
|
||||
<p>插入排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type people struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
// PeopleAageComparator sort people slice by age field
|
||||
type peopleAgeComparator struct{}
|
||||
|
||||
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
|
||||
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
p1, _ := v1.(people)
|
||||
p2, _ := v2.(people)
|
||||
|
||||
//ascending order
|
||||
if p1.Age < p2.Age {
|
||||
return -1
|
||||
} else if p1.Age > p2.Age {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
|
||||
//decending order
|
||||
// if p1.Age > p2.Age {
|
||||
// return -1
|
||||
// } else if p1.Age < p2.Age {
|
||||
// return 1
|
||||
// }
|
||||
}
|
||||
|
||||
var peoples = []people{
|
||||
{Name: "a", Age: 20},
|
||||
{Name: "b", Age: 10},
|
||||
{Name: "c", Age: 17},
|
||||
{Name: "d", Age: 8},
|
||||
{Name: "e", Age: 28},
|
||||
}
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeople := algorithm.InsertionSort(peoples, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="SelectionSort">SelectionSort</span>
|
||||
<p>选择排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.SelectionSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ShellSort">ShellSort</span>
|
||||
<p>希尔排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.ShellSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="QuickSort">QuickSort</span>
|
||||
<p>快速排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="HeapSort">HeapSort</span>
|
||||
<p>堆排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.HeapSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="MergeSort">MergeSort</span>
|
||||
<p>归并排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.MergeSort(intSlice, 0, len(intSlice)-1, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CountSort">CountSort</span>
|
||||
<p>计数排序,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
sortedSlice := algorithm.CountSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BinarySearch">BinarySearch</span>
|
||||
<p>二分递归查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
comparator := &intComparator{}
|
||||
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(foundIndex) //4
|
||||
|
||||
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(notFoundIndex) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
|
||||
<p>二分迭代查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
comparator := &intComparator{}
|
||||
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(foundIndex) //4
|
||||
|
||||
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
|
||||
fmt.Println(notFoundIndex) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LinearSearch">LinearSearch</span>
|
||||
<p>线性查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
//ascending order
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
|
||||
fmt.Println(foundIndex) //2
|
||||
|
||||
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
|
||||
fmt.Println(notFoundIndex) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LRUCache">LRUCache</span>
|
||||
<p>lru实现缓存</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
|
||||
func (l *LRUCache[K, V]) Get(key K) (V, bool)
|
||||
func (l *LRUCache[K, V]) Put(key K, value V)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/algorithm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cache := algorithm.NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0) // ok -> false
|
||||
|
||||
v, ok := cache.Get(1) // v->1, ok->true
|
||||
|
||||
}
|
||||
```
|
||||
349
docs/convertor.md
Normal file
349
docs/convertor.md
Normal file
@@ -0,0 +1,349 @@
|
||||
# Convertor
|
||||
Package convertor contains some functions for data type convertion.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [ColorHexToRGB](#ColorHexToRGB)
|
||||
- [ColorRGBToHex](#ColorRGBToHex)
|
||||
- [ToBool](#ToBool)
|
||||
- [ToBytes](#ToBytes)
|
||||
- [ToChar](#ToChar)
|
||||
- [ToInt](#ToInt)
|
||||
- [ToJson](#ToJson)
|
||||
- [ToString](#ToString)
|
||||
- [StructToMap](#StructToMap)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="ColorHexToRGB">ColorHexToRGB</span>
|
||||
<p>Convert color hex to color rgb.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
colorHex := "#003366"
|
||||
r, g, b := convertor.ColorHexToRGB(colorHex)
|
||||
fmt.Println(r, g, b) //0,51,102
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ColorRGBToHex">ColorRGBToHex</span>
|
||||
|
||||
<p>Convert color rgb to color hex.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ColorRGBToHex(red, green, blue int) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := 0
|
||||
g := 51
|
||||
b := 102
|
||||
colorHex := convertor.ColorRGBToHex(r, g, b)
|
||||
|
||||
fmt.Println(colorHex) //#003366
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToBool">ToBool</span>
|
||||
|
||||
<p>Convert string to a boolean value. Use strconv.ParseBool</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToBool(s string) (bool, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v1, _ := convertor.ToBool("1")
|
||||
fmt.Println(v1) //true
|
||||
|
||||
v2, _ := convertor.ToBool("true")
|
||||
fmt.Println(v2) //true
|
||||
|
||||
v3, _ := convertor.ToBool("True")
|
||||
fmt.Println(v3) //true
|
||||
|
||||
v4, _ := convertor.ToBool("123")
|
||||
fmt.Println(v4) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToBytes">ToBytes</span>
|
||||
|
||||
<p>Convert interface to byte slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToBytes(data any) ([]byte, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
bytesData, err := convertor.ToBytes("0")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(bytesData) //[]bytes{3, 4, 0, 0}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToChar">ToChar</span>
|
||||
|
||||
<p>Convert string to char slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToChar(s string) []string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
chars := convertor.ToChar("")
|
||||
fmt.Println(chars) //[]string{""}
|
||||
|
||||
chars = convertor.ToChar("abc")
|
||||
fmt.Println(chars) //[]string{"a", "b", "c"}
|
||||
|
||||
chars = convertor.ToChar("1 2#3")
|
||||
fmt.Println(chars) //[]string{"1", " ", "2", "#", "3"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFloat">ToFloat</span>
|
||||
|
||||
<p>Convert interface to a float64 value. If param is a invalid floatable, will return 0 and error. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToFloat(value any) (float64, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, err := convertor.ToFloat("")
|
||||
if err != nil {
|
||||
fmt.Println(err) //strconv.ParseFloat: parsing "": invalid syntax
|
||||
}
|
||||
fmt.Println(v) //0
|
||||
|
||||
v, _ = convertor.ToFloat("-.11")
|
||||
fmt.Println(v) //-0.11
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToInt">ToInt</span>
|
||||
|
||||
<p>Convert interface to a int64 value. If param is a invalid intable, will return 0 and error. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToInt(value any) (int64, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, err := convertor.ToInt("")
|
||||
if err != nil {
|
||||
fmt.Println(err) //strconv.ParseInt: parsing "": invalid syntax
|
||||
}
|
||||
fmt.Println(v) //0
|
||||
|
||||
v, _ = convertor.ToFloat(1.12)
|
||||
fmt.Println(v) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToJson">ToJson</span>
|
||||
|
||||
<p>Convert interface to json string. If param can't be converted, will return "" and error. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToJson(value any) (string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
jsonStr, _ := convertor.ToJson(aMap)
|
||||
fmt.Printf("%q", jsonStr) //"{\"a\":1,\"b\":2,\"c\":3}"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToString">ToString</span>
|
||||
|
||||
<p>Convert interface to string. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToString(value any) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("%q", convertor.ToString(1)) //"1"
|
||||
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
|
||||
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="StructToMap">StructToMap</span>
|
||||
|
||||
<p>Convert struct to map, only convert exported field, struct field tag `json` should be set.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func StructToMap(value any) (map[string]any, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
age int
|
||||
}
|
||||
p := People{
|
||||
"test",
|
||||
100,
|
||||
}
|
||||
pm, _ := convertor.StructToMap(p)
|
||||
|
||||
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
|
||||
}
|
||||
```
|
||||
351
docs/convertor_zh-CN.md
Normal file
351
docs/convertor_zh-CN.md
Normal file
@@ -0,0 +1,351 @@
|
||||
# Convertor
|
||||
convertor转换器包支持一些常见的数据类型转换
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [ColorHexToRGB](#ColorHexToRGB)
|
||||
- [ColorRGBToHex](#ColorRGBToHex)
|
||||
- [ToBool](#ToBool)
|
||||
- [ToBytes](#ToBytes)
|
||||
- [ToChar](#ToChar)
|
||||
- [ToInt](#ToInt)
|
||||
- [ToJson](#ToJson)
|
||||
- [ToString](#ToString)
|
||||
- [StructToMap](#StructToMap)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="ColorHexToRGB">ColorHexToRGB</span>
|
||||
<p>颜色值十六进制转rgb</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
colorHex := "#003366"
|
||||
r, g, b := convertor.ColorHexToRGB(colorHex)
|
||||
fmt.Println(r, g, b) //0,51,102
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ColorRGBToHex">ColorRGBToHex</span>
|
||||
|
||||
<p>颜色值rgb转十六进制</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ColorRGBToHex(red, green, blue int) string
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := 0
|
||||
g := 51
|
||||
b := 102
|
||||
colorHex := convertor.ColorRGBToHex(r, g, b)
|
||||
|
||||
fmt.Println(colorHex) //#003366
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToBool">ToBool</span>
|
||||
|
||||
<p>字符串转布尔类型,使用strconv.ParseBool</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToBool(s string) (bool, error)
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v1, _ := convertor.ToBool("1")
|
||||
fmt.Println(v1) //true
|
||||
|
||||
v2, _ := convertor.ToBool("true")
|
||||
fmt.Println(v2) //true
|
||||
|
||||
v3, _ := convertor.ToBool("True")
|
||||
fmt.Println(v3) //true
|
||||
|
||||
v4, _ := convertor.ToBool("123")
|
||||
fmt.Println(v4) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToBytes">ToBytes</span>
|
||||
|
||||
<p>interface转字节切片.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToBytes(data any) ([]byte, error)
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
bytesData, err := convertor.ToBytes("0")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(bytesData) //[]bytes{3, 4, 0, 0}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToChar">ToChar</span>
|
||||
|
||||
<p>字符串转字符切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToChar(s string) []string
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
chars := convertor.ToChar("")
|
||||
fmt.Println(chars) //[]string{""}
|
||||
|
||||
chars = convertor.ToChar("abc")
|
||||
fmt.Println(chars) //[]string{"a", "b", "c"}
|
||||
|
||||
chars = convertor.ToChar("1 2#3")
|
||||
fmt.Println(chars) //[]string{"1", " ", "2", "#", "3"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFloat">ToFloat</span>
|
||||
|
||||
<p>将interface转成float64类型,如果参数无法转换,会返回0和error</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToFloat(value any) (float64, error)
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, err := convertor.ToFloat("")
|
||||
if err != nil {
|
||||
fmt.Println(err) //strconv.ParseFloat: parsing "": invalid syntax
|
||||
}
|
||||
fmt.Println(v) //0
|
||||
|
||||
v, _ = convertor.ToFloat("-.11")
|
||||
fmt.Println(v) //-0.11
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToInt">ToInt</span>
|
||||
|
||||
<p>将interface转成intt64类型,如果参数无法转换,会返回0和error</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToInt(value any) (int64, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, err := convertor.ToInt("")
|
||||
if err != nil {
|
||||
fmt.Println(err) //strconv.ParseInt: parsing "": invalid syntax
|
||||
}
|
||||
fmt.Println(v) //0
|
||||
|
||||
v, _ = convertor.ToFloat(1.12)
|
||||
fmt.Println(v) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToJson">ToJson</span>
|
||||
|
||||
<p>将interface转成json字符串,如果参数无法转换,会返回""和error</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToJson(value any) (string, error)
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
jsonStr, _ := convertor.ToJson(aMap)
|
||||
fmt.Printf("%q", jsonStr) //"{\"a\":1,\"b\":2,\"c\":3}"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToString">ToString</span>
|
||||
|
||||
<p>将interface转成字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToString(value any) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("%q", convertor.ToString(1)) //"1"
|
||||
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
|
||||
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="StructToMap">StructToMap</span>
|
||||
|
||||
<p>将struct转成map,只会转换struct中可导出的字段。struct中导出字段需要设置json tag标记</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func StructToMap(value any) (map[string]any, error)
|
||||
```
|
||||
<b>列子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
age int
|
||||
}
|
||||
p := People{
|
||||
"test",
|
||||
100,
|
||||
}
|
||||
pm, _ := convertor.StructToMap(p)
|
||||
|
||||
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
|
||||
}
|
||||
```
|
||||
1033
docs/cryptor.md
Normal file
1033
docs/cryptor.md
Normal file
File diff suppressed because it is too large
Load Diff
1028
docs/cryptor_zh-CN.md
Normal file
1028
docs/cryptor_zh-CN.md
Normal file
File diff suppressed because it is too large
Load Diff
897
docs/datetime.md
Normal file
897
docs/datetime.md
Normal file
@@ -0,0 +1,897 @@
|
||||
# Datetime
|
||||
Package datetime supports date and time format and compare.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/datetime/conversion.go](https://github.com/duke-git/lancet/blob/main/datetime/conversion.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [AddDay](#AddDay)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
- [BeginOfWeek](#BeginOfWeek)
|
||||
- [BeginOfMonth](#BeginOfMonth)
|
||||
- [BeginOfYear](#BeginOfYear)
|
||||
- [EndOfMinute](#EndOfMinute)
|
||||
- [EndOfHour](#EndOfHour)
|
||||
- [EndOfDay](#EndOfDay)
|
||||
- [EndOfWeek](#EndOfWeek)
|
||||
- [EndOfMonth](#EndOfMonth)
|
||||
- [EndOfYear](#EndOfYear)
|
||||
- [GetNowDate](#GetNowDate)
|
||||
- [GetNowTime](#GetNowTime)
|
||||
- [GetNowDateTime](#GetNowDateTime)
|
||||
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
|
||||
- [GetNightTimestamp](#GetNightTimestamp)
|
||||
- [FormatTimeToStr](#FormatTimeToStr)
|
||||
- [FormatStrToTime](#FormatStrToTime)
|
||||
|
||||
- [NewUnixNow](#NewUnixNow)
|
||||
- [NewUnix](#NewUnix)
|
||||
- [NewFormat](#NewFormat)
|
||||
- [NewISO8601](#NewISO8601)
|
||||
- [ToUnix](#ToUnix)
|
||||
- [ToFormat](#ToFormat)
|
||||
- [ToFormatForTpl](#ToFormatForTpl)
|
||||
- [ToIso8601](#ToIso8601)
|
||||
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
## Note:
|
||||
1. 'format' string param in func FormatTimeToStr and FormatStrToTime function should be one of flows:
|
||||
- yyyy-mm-dd hh:mm:ss
|
||||
- yyyy-mm-dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy-mm-dd
|
||||
- yyyy-mm
|
||||
- mm-dd
|
||||
- dd-mm-yy hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy/mm/dd
|
||||
- yyyy/mm
|
||||
- mm/dd
|
||||
- dd/mm/yy hh:mm:ss
|
||||
- yyyy
|
||||
- mm
|
||||
- hh:mm:ss
|
||||
- mm:ss
|
||||
|
||||
|
||||
### <span id="AddDay">AddDay</span>
|
||||
<p>Add or sub days to time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
after2Days := datetime.AddDay(now, 2)
|
||||
before2Days := datetime.AddDay(now, -2)
|
||||
|
||||
fmt.Println(after2Days, before2Days)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="AddHour">AddHour</span>
|
||||
<p>Add or sub hours to time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddHour(t time.Time, hour int64) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
after2Hours := datetime.AddHour(now, 2)
|
||||
before2Hours := datetime.AddHour(now, -2)
|
||||
|
||||
fmt.Println(after2Hours, after2Hours)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddMinute">AddMinute</span>
|
||||
<p>Add or sub minutes to time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddMinute(t time.Time, minute int64) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
after2Minute := datetime.AddMinute(now, 2)
|
||||
before2Minute := datetime.AddMinute(now, -2)
|
||||
|
||||
fmt.Println(after2Minute, before2Minute)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfMinute">BeginOfMinute</span>
|
||||
<p>Return beginning minute time of day.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfMinute(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfMinute(td)
|
||||
fmt.Println(bm) //2022-02-15 15:48:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfHour">BeginOfHour</span>
|
||||
<p>Return zero time of day.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfHour(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfHour(td)
|
||||
fmt.Println(bm) //2022-02-15 15:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfDay">BeginOfDay</span>
|
||||
<p>Return begin time of day.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfDay(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfDay(td)
|
||||
fmt.Println(bm) //2022-02-15 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="BeginOfWeek">BeginOfWeek</span>
|
||||
<p>Return beginning time of week, week begin from Sunday.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfWeek(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfWeek(td)
|
||||
fmt.Println(bm) //2022-02-13 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="BeginOfMonth">BeginOfMonth</span>
|
||||
<p>Return beginning time of month</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfMonth(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfMonth(td)
|
||||
fmt.Println(bm) //2022-02-01 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="BeginOfYear">BeginOfYear</span>
|
||||
<p>Return beginning time of year.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfYear(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfYear(td)
|
||||
fmt.Println(bm) //2022-01-01 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EndOfMinute">EndOfMinute</span>
|
||||
<p>Return end time minute of day.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfMinute(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfMinute(td)
|
||||
fmt.Println(bm) //2022-02-15 15:48:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EndOfHour">EndOfHour</span>
|
||||
<p>Return end time hour of day.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfHour(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfHour(td)
|
||||
fmt.Println(bm) //2022-02-15 15:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EndOfDay">EndOfDay</span>
|
||||
<p>Return end time hour of day.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfDay(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfDay(td)
|
||||
fmt.Println(bm) //2022-02-15 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EndOfWeek">EndOfWeek</span>
|
||||
<p>Return end time of week, week end with Saturday.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfWeek(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfWeek(td)
|
||||
fmt.Println(bm) //2022-02-19 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EndOfMonth">EndOfMonth</span>
|
||||
<p>Return end time of month</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfMonth(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfMonth(td)
|
||||
fmt.Println(bm) //2022-02-28 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="EndOfYear">EndOfYear</span>
|
||||
<p>Return beginning time of year.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfYear(t time.Time) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfYear(td)
|
||||
fmt.Println(bm) //2022-12-31 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNowDate">GetNowDate</span>
|
||||
<p>Get current date string, format is yyyy-mm-dd.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetNowDate() string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
currentDate := datetime.GetNowDate()
|
||||
fmt.Println(currentDate) // 2022-01-28
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNowTime">GetNowTime</span>
|
||||
<p>Get current time string, format is hh:mm:ss.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetNowTime() string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
currentTime := datetime.GetNowTime()
|
||||
fmt.Println(currentDate) // 15:57:33
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNowDateTime">GetNowDateTime</span>
|
||||
<p>Get current date time string, format is yyyy-mm-dd hh:mm:ss.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetNowDateTime() string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
current := datetime.GetNowDateTime()
|
||||
fmt.Println(current) // 2022-01-28 15:59:33
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
|
||||
<p>Return timestamp of zero hour (timestamp of 00:00).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetZeroHourTimestamp() int64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
zeroTime := datetime.GetZeroHourTimestamp()
|
||||
fmt.Println(zeroTime) // 1643299200
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNightTimestamp">GetNightTimestamp</span>
|
||||
<p>Return timestamp of zero hour (timestamp of 23:59).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetNightTimestamp() int64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
nightTime := datetime.GetNightTimestamp()
|
||||
fmt.Println(nightTime) // 1643385599
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FormatTimeToStr">FormatTimeToStr</span>
|
||||
<p>Format time to string, `format` param specification see note 1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FormatTimeToStr(t time.Time, format string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
timeStr := datetime.FormatTimeToStr(now, "yyyy/mm/dd hh:mm:ss")
|
||||
fmt.Println(timeStr) //2022/01/28 16:07:44
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="FormatStrToTime">FormatStrToTime</span>
|
||||
<p>Format string to time, `format` param specification see note 1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FormatStrToTime(str, format string) (time.Time, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
time := datetime.FormatStrToTime("2006-01-02 15:04:05", "yyyy/mm/dd hh:mm:ss")
|
||||
fmt.Println(time)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="NewUnixNow">NewUnixNow</span>
|
||||
<p>Return unix timestamp of current time</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewUnixNow() *theTime
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm) //&{1647597438}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="NewUnix">NewUnix</span>
|
||||
<p>Return unix timestamp of specified int64 value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnix(1647597438)
|
||||
fmt.Println(tm) //&{1647597438}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="NewFormat">NewFormat</span>
|
||||
<p>Return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm) //&{1647594245}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="NewISO8601">NewISO8601</span>
|
||||
<p>Return unix timestamp of specified iso8601 time string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
fmt.Println(tm) //&{1136214245}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToUnix">ToUnix</span>
|
||||
<p>Return unix timestamp.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToUnix() int64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm.ToUnix()) //1647597438
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFormat">ToFormat</span>
|
||||
<p>Return time string 'yyyy-mm-dd hh:mm:ss'.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToFormat() string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFormatForTpl">ToFormatForTpl</span>
|
||||
<p>Return the time string which format is specified tpl.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToFormatForTpl(tpl string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
|
||||
fmt.Println(ts) //"2022/03/18 17:04:05"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="ToIso8601">ToIso8601</span>
|
||||
<p>Return iso8601 time string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToIso8601() string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
ts := tm.ToIso8601()
|
||||
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
|
||||
}
|
||||
```
|
||||
893
docs/datetime_zh-CN.md
Normal file
893
docs/datetime_zh-CN.md
Normal file
@@ -0,0 +1,893 @@
|
||||
# Datetime
|
||||
datetime日期时间处理包,格式化日期,比较日期。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [AddDay](#AddDay)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
- [BeginOfWeek](#BeginOfWeek)
|
||||
- [BeginOfMonth](#BeginOfMonth)
|
||||
- [BeginOfYear](#BeginOfYear)
|
||||
- [EndOfMinute](#EndOfMinute)
|
||||
- [EndOfHour](#EndOfHour)
|
||||
- [EndOfDay](#EndOfDay)
|
||||
- [EndOfWeek](#EndOfWeek)
|
||||
- [EndOfMonth](#EndOfMonth)
|
||||
- [EndOfYear](#EndOfYear)
|
||||
- [GetNowDate](#GetNowDate)
|
||||
- [GetNowTime](#GetNowTime)
|
||||
- [GetNowDateTime](#GetNowDateTime)
|
||||
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
|
||||
- [GetNightTimestamp](#GetNightTimestamp)
|
||||
- [FormatTimeToStr](#FormatTimeToStr)
|
||||
- [FormatStrToTime](#FormatStrToTime)
|
||||
|
||||
- [NewUnixNow](#NewUnixNow)
|
||||
- [NewUnix](#NewUnix)
|
||||
- [NewFormat](#NewFormat)
|
||||
- [NewISO8601](#NewISO8601)
|
||||
- [ToUnix](#ToUnix)
|
||||
- [ToFormat](#ToFormat)
|
||||
- [ToFormatForTpl](#ToFormatForTpl)
|
||||
- [ToIso8601](#ToIso8601)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
## 注:
|
||||
1. 方法FormatTimeToStr和FormatStrToTime中的format参数值需要传以下类型之一:
|
||||
- yyyy-mm-dd hh:mm:ss
|
||||
- yyyy-mm-dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy-mm-dd
|
||||
- yyyy-mm
|
||||
- mm-dd
|
||||
- dd-mm-yy hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy/mm/dd
|
||||
- yyyy/mm
|
||||
- mm/dd
|
||||
- dd/mm/yy hh:mm:ss
|
||||
- yyyy
|
||||
- mm
|
||||
- hh:mm:ss
|
||||
- mm:ss
|
||||
|
||||
|
||||
### <span id="AddDay">AddDay</span>
|
||||
<p>将日期加/减天数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
after2Days := datetime.AddDay(now, 2)
|
||||
before2Days := datetime.AddDay(now, -2)
|
||||
|
||||
fmt.Println(after2Days, before2Days)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="AddHour">AddHour</span>
|
||||
<p>将日期加/减小时数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddHour(t time.Time, hour int64) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
after2Hours := datetime.AddHour(now, 2)
|
||||
before2Hours := datetime.AddHour(now, -2)
|
||||
|
||||
fmt.Println(after2Hours, after2Hours)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddMinute">AddMinute</span>
|
||||
<p>将日期加/减分钟数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddMinute(t time.Time, minute int64) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
after2Minute := datetime.AddMinute(now, 2)
|
||||
before2Minute := datetime.AddMinute(now, -2)
|
||||
|
||||
fmt.Println(after2Minute, before2Minute)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfMinute">BeginOfMinute</span>
|
||||
<p>返回指定时间的分钟开始时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfMinute(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfMinute(td)
|
||||
fmt.Println(bm) //2022-02-15 15:48:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfHour">BeginOfHour</span>
|
||||
<p>返回指定时间的小时开始时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfHour(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfHour(td)
|
||||
fmt.Println(bm) //2022-02-15 15:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfDay">BeginOfDay</span>
|
||||
<p>返回指定时间的当天开始时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfDay(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfDay(td)
|
||||
fmt.Println(bm) //2022-02-15 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="BeginOfWeek">BeginOfWeek</span>
|
||||
<p>返回指定时间的星期开始时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfWeek(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfWeek(td)
|
||||
fmt.Println(bm) //2022-02-13 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="BeginOfMonth">BeginOfMonth</span>
|
||||
<p>返回指定时间的当月开始时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfMonth(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfMonth(td)
|
||||
fmt.Println(bm) //2022-02-01 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="BeginOfYear">BeginOfYear</span>
|
||||
<p>返回指定时间的当年开始时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfYear(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.BeginOfYear(td)
|
||||
fmt.Println(bm) //2022-01-01 00:00:00 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EndOfMinute">EndOfMinute</span>
|
||||
<p>返回指定时间的分钟结束时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfMinute(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfMinute(td)
|
||||
fmt.Println(bm) //2022-02-15 15:48:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EndOfHour">EndOfHour</span>
|
||||
<p>返回指定时间的小时结束时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfHour(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfHour(td)
|
||||
fmt.Println(bm) //2022-02-15 15:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EndOfDay">EndOfDay</span>
|
||||
<p>返回指定时间的当天结束时间.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfDay(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfDay(td)
|
||||
fmt.Println(bm) //2022-02-15 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EndOfWeek">EndOfWeek</span>
|
||||
<p>返回指定时间的星期结束时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfWeek(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfWeek(td)
|
||||
fmt.Println(bm) //2022-02-19 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EndOfMonth">EndOfMonth</span>
|
||||
<p>返回指定时间的月份结束时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfMonth(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfMonth(td)
|
||||
fmt.Println(bm) //2022-02-28 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="EndOfYear">EndOfYear</span>
|
||||
<p>返回指定时间的年份结束时间</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfYear(t time.Time) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
|
||||
bm := datetime.EndOfYear(td)
|
||||
fmt.Println(bm) //2022-12-31 23:59:59.999999999 +0800 CST
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNowDate">GetNowDate</span>
|
||||
<p>获取当天日期,返回格式:yyyy-mm-dd</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNowDate() string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
currentDate := datetime.GetNowDate()
|
||||
fmt.Println(currentDate) // 2022-01-28
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNowTime">GetNowTime</span>
|
||||
<p>获取当时时间,返回格式:hh:mm:ss</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNowTime() string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
currentTime := datetime.GetNowTime()
|
||||
fmt.Println(currentDate) // 15:57:33
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNowDateTime">GetNowDateTime</span>
|
||||
<p>获取当时日期和时间,返回格式:yyyy-mm-dd hh:mm:ss.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNowDateTime() string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
current := datetime.GetNowDateTime()
|
||||
fmt.Println(current) // 2022-01-28 15:59:33
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
|
||||
<p>获取零时时间戳(timestamp of 00:00).</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetZeroHourTimestamp() int64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
zeroTime := datetime.GetZeroHourTimestamp()
|
||||
fmt.Println(zeroTime) // 1643299200
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetNightTimestamp">GetNightTimestamp</span>
|
||||
<p>获取午夜时间戳(timestamp of 23:59).</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNightTimestamp() int64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
nightTime := datetime.GetNightTimestamp()
|
||||
fmt.Println(nightTime) // 1643385599
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FormatTimeToStr">FormatTimeToStr</span>
|
||||
<p>将日期格式化成字符串,`format` 参数格式参考注<sup>1</sup></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FormatTimeToStr(t time.Time, format string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
timeStr := datetime.FormatTimeToStr(now, "yyyy/mm/dd hh:mm:ss")
|
||||
fmt.Println(timeStr) //2022/01/28 16:07:44
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="FormatStrToTime">FormatStrToTime</span>
|
||||
<p>将字符串格式化成时间,`format` 参数格式参考注<sup>1</sup></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FormatStrToTime(str, format string) (time.Time, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
time := datetime.FormatStrToTime("2006-01-02 15:04:05", "yyyy/mm/dd hh:mm:ss")
|
||||
fmt.Println(time)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="NewUnixNow">NewUnixNow</span>
|
||||
<p>创建一个当前时间的unix时间戳</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewUnixNow() *theTime
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm) //&{1647597438}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="NewUnix">NewUnix</span>
|
||||
<p>创建一个unix时间戳</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnix(1647597438)
|
||||
fmt.Println(tm) //&{1647597438}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="NewFormat">NewFormat</span>
|
||||
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm) //&{1647594245}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="NewISO8601">NewISO8601</span>
|
||||
<p>创建一个iso8601格式时间字符串的unix时间戳</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
}
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
fmt.Println(tm) //&{1136214245}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToUnix">ToUnix</span>
|
||||
<p>返回unix时间戳</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToUnix() int64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm.ToUnix()) //1647597438
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFormat">ToFormat</span>
|
||||
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToFormat() string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFormatForTpl">ToFormatForTpl</span>
|
||||
<p>返回tpl格式指定的日期字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToFormatForTpl(tpl string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
|
||||
fmt.Println(ts) //"2022/03/18 17:04:05"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="ToIso8601">ToIso8601</span>
|
||||
<p>返回iso8601日期字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToIso8601() string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
ts := tm.ToIso8601()
|
||||
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
|
||||
}
|
||||
```
|
||||
444
docs/fileutil.md
Normal file
444
docs/fileutil.md
Normal file
@@ -0,0 +1,444 @@
|
||||
# Fileutil
|
||||
Package fileutil implements some basic functions for file operations.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
- [IsExist](#IsExist)
|
||||
- [IsLink](#IsLink)
|
||||
- [IsDir](#IsDir)
|
||||
- [ListFileNames](#ListFileNames)
|
||||
- [RemoveFile](#RemoveFile)
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
|
||||
- [UnZip](#UnZip)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="ClearFile">ClearFile</span>
|
||||
<p>Clear the file content, write empty string to the file.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ClearFile(path string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ClearFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CreateFile">CreateFile</span>
|
||||
<p>Create file in path. return true if create succeed.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CreateFile(path string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isCreatedSucceed := fileutil.CreateFile("./test.txt")
|
||||
fmt.Println(isCreatedSucceed)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
<p>Copy src file to dest file. If dest file exist will overwrite it.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CopyFile(srcFilePath string, dstFilePath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="FileMode">FileMode</span>
|
||||
<p>Return file mode infomation.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FileMode(path string) (fs.FileMode, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="MiMeType">MiMeType</span>
|
||||
<p>Get file mime type, 'file' param's type should be string or *os.File.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MiMeType(file any) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type1 := fileutil.MiMeType("./test.txt")
|
||||
fmt.Println(type1) //text/plain; charset=utf-8
|
||||
|
||||
f, _ := os.Open("./file.go")
|
||||
type2 := fileutil.MiMeType(f)
|
||||
fmt.Println(type2) //text/plain; charset=utf-8
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsExist">IsExist</span>
|
||||
<p>Checks if a file or directory exists.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsExist(path string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileutil.CreateFile("./test.txt")
|
||||
isFileExist := fileutil.IsExist("./test.txt")
|
||||
fmt.Println(isFileExist) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsLink">IsLink</span>
|
||||
<p>Checks if a file is symbol link or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsLink(path string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isLinkFile := fileutil.IsLink("./test.txt")
|
||||
fmt.Println(isLinkFile) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsDir">IsDir</span>
|
||||
<p>Checks if the path is directy or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsDir(path string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isDir := fileutil.IsDir("./")
|
||||
fmt.Println(isDir) //true
|
||||
|
||||
isDir = fileutil.IsDir("./test.txt")
|
||||
fmt.Println(isDir) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ListFileNames">ListFileNames</span>
|
||||
<p>List all file names in given path.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ListFileNames(path string) ([]string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileNames, _ := fileutil.ListFileNames("./")
|
||||
fmt.Println(fileNames)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RemoveFile">RemoveFile</span>
|
||||
<p>Remove the file of path.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RemoveFile(path string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="ReadFileToString">ReadFileToString</span>
|
||||
<p>Return string of file content.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReadFileToString(path string) (string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ReadFileByLine">ReadFileByLine</span>
|
||||
<p>Read file line by line, and return slice of lines</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReadFileByLine(path string)([]string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Zip">Zip</span>
|
||||
<p>Create a zip file of fpath, fpath could be a file or a directory.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Zip(fpath string, destPath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="UnZip">UnZip</span>
|
||||
<p>Unzip the file and save it to dest path.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UnZip(zipFile string, destPath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
444
docs/fileutil_zh-CN.md
Normal file
444
docs/fileutil_zh-CN.md
Normal file
@@ -0,0 +1,444 @@
|
||||
# Fileutil
|
||||
fileutil包支持文件基本操作。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
- [IsExist](#IsExist)
|
||||
- [IsLink](#IsLink)
|
||||
- [IsDir](#IsDir)
|
||||
|
||||
- [ListFileNames](#ListFileNames)
|
||||
- [RemoveFile](#RemoveFile)
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
- [UnZip](#UnZip)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="ClearFile">ClearFile</span>
|
||||
<p>清空文件内容</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ClearFile(path string) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ClearFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CreateFile">CreateFile</span>
|
||||
<p>创建文件,创建成功返回true, 否则返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CreateFile(path string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isCreatedSucceed := fileutil.CreateFile("./test.txt")
|
||||
fmt.Println(isCreatedSucceed)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
<p>拷贝文件,会覆盖原有的拷贝文件</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CopyFile(srcFilePath string, dstFilePath string) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="FileMode">FileMode</span>
|
||||
<p>获取文件mode信息</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FileMode(path string) (fs.FileMode, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="MiMeType">MiMeType</span>
|
||||
<p>获取文件mime类型, 'file'参数的类型必须是string或者*os.File</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MiMeType(file any) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type1 := fileutil.MiMeType("./test.txt")
|
||||
fmt.Println(type1) //text/plain; charset=utf-8
|
||||
|
||||
f, _ := os.Open("./file.go")
|
||||
type2 := fileutil.MiMeType(f)
|
||||
fmt.Println(type2) //text/plain; charset=utf-8
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsExist">IsExist</span>
|
||||
<p>判断文件或目录是否存在</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsExist(path string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileutil.CreateFile("./test.txt")
|
||||
isFileExist := fileutil.IsExist("./test.txt")
|
||||
fmt.Println(isFileExist) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsLink">IsLink</span>
|
||||
<p>判断文件是否是符号链接</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsLink(path string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isLinkFile := fileutil.IsLink("./test.txt")
|
||||
fmt.Println(isLinkFile) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsDir">IsDir</span>
|
||||
<p>判断目录是否存在</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsDir(path string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isDir := fileutil.IsDir("./")
|
||||
fmt.Println(isDir) //true
|
||||
|
||||
isDir = fileutil.IsDir("./test.txt")
|
||||
fmt.Println(isDir) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ListFileNames">ListFileNames</span>
|
||||
<p>返回目录下所有文件名</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ListFileNames(path string) ([]string, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileNames, _ := fileutil.ListFileNames("./")
|
||||
fmt.Println(fileNames)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RemoveFile">RemoveFile</span>
|
||||
<p>删除文件</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RemoveFile(path string) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="ReadFileToString">ReadFileToString</span>
|
||||
<p>读取文件内容并返回字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadFileToString(path string) (string, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ReadFileByLine">ReadFileByLine</span>
|
||||
<p>按行读取文件内容,返回字符串切片包含每一行</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadFileByLine(path string)([]string, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Zip">Zip</span>
|
||||
<p>zip压缩文件, fpath参数可以是文件或目录</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Zip(fpath string, destPath string) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="UnZip">UnZip</span>
|
||||
<p>zip解压缩文件并保存在目录中</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UnZip(zipFile string, destPath string) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
53
docs/formatter.md
Normal file
53
docs/formatter.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Formatter
|
||||
formatter contains some functions for data formatting.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Comma](#Comma)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="Comma">Comma</span>
|
||||
<p>Add comma to number by every 3 numbers from right. ahead by symbol char.
|
||||
Param should be number or numberic string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Comma(v any, symbol string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(formatter.Comma("12345", "")) // "12,345"
|
||||
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
||||
}
|
||||
```
|
||||
52
docs/formatter_zh-CN.md
Normal file
52
docs/formatter_zh-CN.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Formatter
|
||||
formatter格式化器包含一些数据格式化处理方法。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Comma](#Comma)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="Comma">Comma</span>
|
||||
<p>用逗号每隔3位分割数字/字符串,签名添加符号。参数必须是数字或者可以转为数字的字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Comma(v any, symbol string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(formatter.Comma("12345", "")) // "12,345"
|
||||
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
||||
}
|
||||
```
|
||||
364
docs/function.md
Normal file
364
docs/function.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# Function
|
||||
Package function can control the flow of function execution and support part of functional programming.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [After](#After)
|
||||
- [Before](#Before)
|
||||
- [Curry](#Curry)
|
||||
- [Compose](#Compose)
|
||||
- [Debounced](#Debounced)
|
||||
- [Delay](#Delay)
|
||||
- [Watcher](#Watcher)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="After">After</span>
|
||||
<p>Creates a function that invokes given func once it's called n or more times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func After(n int, fn any) func(args ...any) []reflect.Value
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arr := []string{"a", "b"}
|
||||
f := function.After(len(arr), func(i int) int {
|
||||
fmt.Println("last print")
|
||||
return i
|
||||
})
|
||||
|
||||
type cb func(args ...any) []reflect.Value
|
||||
print := func(i int, s string, fn cb) {
|
||||
fmt.Printf("arr[%d] is %s \n", i, s)
|
||||
fn(i)
|
||||
}
|
||||
|
||||
fmt.Println("arr is", arr)
|
||||
for i := 0; i < len(arr); i++ {
|
||||
print(i, arr[i], f)
|
||||
}
|
||||
|
||||
//output:
|
||||
// arr is [a b]
|
||||
// arr[0] is a
|
||||
// arr[1] is b
|
||||
// last print
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Before">Before</span>
|
||||
|
||||
<p>creates a function that invokes func once it's called less than n times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Before(n int, fn any) func(args ...any) []reflect.Value
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := function.Before(3, func(i int) int {
|
||||
return i
|
||||
})
|
||||
|
||||
var res []int64
|
||||
type cb func(args ...any) []reflect.Value
|
||||
appendStr := func(i int, s string, fn cb) {
|
||||
v := fn(i)
|
||||
res = append(res, v[0].Int())
|
||||
}
|
||||
|
||||
for i := 0; i < len(arr); i++ {
|
||||
appendStr(i, arr[i], f)
|
||||
}
|
||||
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Curry">Curry</span>
|
||||
|
||||
<p>Make a curry function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type Fn func(...any) any
|
||||
func (f Fn) Curry(i any) func(...any) any
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
add := func(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
var addCurry function.Fn = func(values ...any) any {
|
||||
return add(values[0].(int), values[1].(int))
|
||||
}
|
||||
add1 := addCurry.Curry(1)
|
||||
result := add1(2)
|
||||
fmt.Println(result) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Compose">Compose</span>
|
||||
|
||||
<p>Compose the function list from right to left, then return the composed function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Compose(fnList ...func(...any) any) func(...any) any
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
add1 := func(v ...any) any {
|
||||
return v[0].(int) + 1
|
||||
}
|
||||
add2 := func(v ...any) any {
|
||||
return v[0].(int) + 2
|
||||
}
|
||||
|
||||
add3 := function.Compose(add1, add2)
|
||||
result := add3(1)
|
||||
|
||||
fmt.Println(result) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Debounced">Debounced</span>
|
||||
|
||||
<p>Creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Debounced(fn func(), duration time.Duration) func()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
count := 0
|
||||
add := func() {
|
||||
count++
|
||||
}
|
||||
|
||||
debouncedAdd := function.Debounced(add, 50*time.Microsecond)
|
||||
function.debouncedAdd()
|
||||
function.debouncedAdd()
|
||||
function.debouncedAdd()
|
||||
function.debouncedAdd()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fmt.Println(count) //1
|
||||
|
||||
function.debouncedAdd()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fmt.Println(count) //2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Delay">Delay</span>
|
||||
|
||||
<p>Invoke function after delayed time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Delay(delay time.Duration, fn any, args ...any)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var print = func(s string) {
|
||||
fmt.Println(count) //test delay
|
||||
}
|
||||
function.Delay(2*time.Second, print, "test delay")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Schedule">Schedule</span>
|
||||
|
||||
<p>Invoke function every duration time, until close the returned bool chan.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Schedule(d time.Duration, fn any, args ...any) chan bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var res []string
|
||||
appendStr := func(s string) {
|
||||
res = append(res, s)
|
||||
}
|
||||
|
||||
stop := function.Schedule(1*time.Second, appendStr, "*")
|
||||
time.Sleep(5 * time.Second)
|
||||
close(stop)
|
||||
|
||||
fmt.Println(res) //[* * * * *]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Watcher">Watcher</span>
|
||||
|
||||
<p>Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type Watcher struct {
|
||||
startTime int64
|
||||
stopTime int64
|
||||
excuting bool
|
||||
}
|
||||
func (w *Watcher) Start() //start the watcher
|
||||
func (w *Watcher) Stop() //stop the watcher
|
||||
func (w *Watcher) Reset() //reset the watcher
|
||||
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
w := &function.Watcher{}
|
||||
w.Start()
|
||||
|
||||
longRunningTask()
|
||||
|
||||
fmt.Println(w.excuting) //true
|
||||
|
||||
w.Stop()
|
||||
|
||||
eapsedTime := w.GetElapsedTime().Milliseconds()
|
||||
fmt.Println(eapsedTime)
|
||||
|
||||
w.Reset()
|
||||
|
||||
fmt.Println(w.excuting) //false
|
||||
|
||||
fmt.Println(w.startTime) //0
|
||||
fmt.Println(w.stopTime) //0
|
||||
}
|
||||
|
||||
func longRunningTask() {
|
||||
var slice []int64
|
||||
for i := 0; i < 10000000; i++ {
|
||||
slice = append(slice, int64(i))
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
364
docs/function_zh-CN.md
Normal file
364
docs/function_zh-CN.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# Function
|
||||
function函数包控制函数执行流程,包含部分函数式编程。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [After](#After)
|
||||
- [Before](#Before)
|
||||
- [Curry](#Curry)
|
||||
- [Compose](#Compose)
|
||||
- [Debounced](#Debounced)
|
||||
- [Delay](#Delay)
|
||||
- [Watcher](#Watcher)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="After">After</span>
|
||||
<p>创建一个函数,当他被调用n或更多次之后将马上触发fn</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func After(n int, fn any) func(args ...any) []reflect.Value
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arr := []string{"a", "b"}
|
||||
f := function.After(len(arr), func(i int) int {
|
||||
fmt.Println("last print")
|
||||
return i
|
||||
})
|
||||
|
||||
type cb func(args ...any) []reflect.Value
|
||||
print := func(i int, s string, fn cb) {
|
||||
fmt.Printf("arr[%d] is %s \n", i, s)
|
||||
fn(i)
|
||||
}
|
||||
|
||||
fmt.Println("arr is", arr)
|
||||
for i := 0; i < len(arr); i++ {
|
||||
print(i, arr[i], f)
|
||||
}
|
||||
|
||||
//output:
|
||||
// arr is [a b]
|
||||
// arr[0] is a
|
||||
// arr[1] is b
|
||||
// last print
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Before">Before</span>
|
||||
|
||||
<p>创建一个函数,调用次数不超过n次,之后再调用这个函数,将返回一次最后调用fn的结果</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Before(n int, fn any) func(args ...any) []reflect.Value
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := function.Before(3, func(i int) int {
|
||||
return i
|
||||
})
|
||||
|
||||
var res []int64
|
||||
type cb func(args ...any) []reflect.Value
|
||||
appendStr := func(i int, s string, fn cb) {
|
||||
v := fn(i)
|
||||
res = append(res, v[0].Int())
|
||||
}
|
||||
|
||||
for i := 0; i < len(arr); i++ {
|
||||
appendStr(i, arr[i], f)
|
||||
}
|
||||
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Curry">Curry</span>
|
||||
|
||||
<p>创建一个柯里化的函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type Fn func(...any) any
|
||||
func (f Fn) Curry(i any) func(...any) any
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
add := func(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
var addCurry function.Fn = func(values ...any) any {
|
||||
return add(values[0].(int), values[1].(int))
|
||||
}
|
||||
add1 := addCurry.Curry(1)
|
||||
result := add1(2)
|
||||
fmt.Println(result) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Compose">Compose</span>
|
||||
|
||||
<p>从右至左组合函数列表fnList, 返回组合后的函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Compose(fnList ...func(...any) any) func(...any) any
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
add1 := func(v ...any) any {
|
||||
return v[0].(int) + 1
|
||||
}
|
||||
add2 := func(v ...any) any {
|
||||
return v[0].(int) + 2
|
||||
}
|
||||
|
||||
add3 := function.Compose(add1, add2)
|
||||
result := add3(1)
|
||||
|
||||
fmt.Println(result) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Debounced">Debounced</span>
|
||||
|
||||
<p>创建一个 debounced 函数,该函数延迟调用 fn 直到自上次调用 debounced 函数后等待持续时间过去。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Debounced(fn func(), duration time.Duration) func()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
count := 0
|
||||
add := func() {
|
||||
count++
|
||||
}
|
||||
|
||||
debouncedAdd := function.Debounced(add, 50*time.Microsecond)
|
||||
function.debouncedAdd()
|
||||
function.debouncedAdd()
|
||||
function.debouncedAdd()
|
||||
function.debouncedAdd()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fmt.Println(count) //1
|
||||
|
||||
function.debouncedAdd()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fmt.Println(count) //2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Delay">Delay</span>
|
||||
|
||||
<p>延迟delay时间后调用函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Delay(delay time.Duration, fn any, args ...any)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var print = func(s string) {
|
||||
fmt.Println(count) //test delay
|
||||
}
|
||||
function.Delay(2*time.Second, print, "test delay")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Schedule">Schedule</span>
|
||||
|
||||
<p>每次持续时间调用函数,直到关闭返回的 bool chan</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Schedule(d time.Duration, fn any, args ...any) chan bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var res []string
|
||||
appendStr := func(s string) {
|
||||
res = append(res, s)
|
||||
}
|
||||
|
||||
stop := function.Schedule(1*time.Second, appendStr, "*")
|
||||
time.Sleep(5 * time.Second)
|
||||
close(stop)
|
||||
|
||||
fmt.Println(res) //[* * * * *]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Watcher">Watcher</span>
|
||||
|
||||
<p>Watcher 用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。 </p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type Watcher struct {
|
||||
startTime int64
|
||||
stopTime int64
|
||||
excuting bool
|
||||
}
|
||||
func (w *Watcher) Start() //start the watcher
|
||||
func (w *Watcher) Stop() //stop the watcher
|
||||
func (w *Watcher) Reset() //reset the watcher
|
||||
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
w := &function.Watcher{}
|
||||
w.Start()
|
||||
|
||||
longRunningTask()
|
||||
|
||||
fmt.Println(w.excuting) //true
|
||||
|
||||
w.Stop()
|
||||
|
||||
eapsedTime := w.GetElapsedTime().Milliseconds()
|
||||
fmt.Println(eapsedTime)
|
||||
|
||||
w.Reset()
|
||||
|
||||
fmt.Println(w.excuting) //false
|
||||
|
||||
fmt.Println(w.startTime) //0
|
||||
fmt.Println(w.stopTime) //0
|
||||
}
|
||||
|
||||
func longRunningTask() {
|
||||
var slice []int64
|
||||
for i := 0; i < 10000000; i++ {
|
||||
slice = append(slice, int64(i))
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
320
docs/mathutil.md
Normal file
320
docs/mathutil.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# Mathutil
|
||||
Package mathutil implements some functions for math calculation.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Example:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Average](#Average)
|
||||
- [Exponent](#Exponent)
|
||||
- [Fibonacci](#Fibonacci)
|
||||
- [Factorial](#Factorial)
|
||||
- [Max](#Max)
|
||||
- [Min](#Min)
|
||||
|
||||
- [Percent](#Percent)
|
||||
- [RoundToFloat](#RoundToFloat)
|
||||
- [RoundToString](#RoundToString)
|
||||
- [TruncRound](#TruncRound)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="Average">Average</span>
|
||||
<p>Return average value of numbers. Maybe call RoundToFloat to round result.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Average[T lancetconstraints.Number](numbers ...T) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Average(0, 0)) //0
|
||||
fmt.Println(mathutil.Average(1, 1)) //1
|
||||
avg := mathutil.Average(1.2, 1.4) //1.2999999998
|
||||
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Exponent">Exponent</span>
|
||||
<p>Calculate x to the nth power.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Exponent(x, n int64) int64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Exponent(10, 0)) //1
|
||||
fmt.Println(mathutil.Exponent(10, 1)) //10
|
||||
fmt.Println(mathutil.Exponent(10, 2)) //100
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Fibonacci">Fibonacci</span>
|
||||
<p>Calculate the nth number of fibonacci sequence.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Fibonacci(first, second, n int) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Factorial">Factorial</span>
|
||||
<p>Calculate the factorial of x.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Factorial(x uint) uint
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Factorial(0)) //1
|
||||
fmt.Println(mathutil.Factorial(1)) //1
|
||||
fmt.Println(mathutil.Factorial(2)) //2
|
||||
fmt.Println(mathutil.Factorial(3)) //6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
<p>Return max value of numbers.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Max[T lancetconstraints.Number](numbers ...T) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Max(0, 0)) //0
|
||||
fmt.Println(mathutil.Max(1, 2, 3)) //3
|
||||
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Min">Min</span>
|
||||
<p>Return min value of numbers.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Min[T lancetconstraints.Number](numbers ...T) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Min(0, 0)) //0
|
||||
fmt.Println(mathutil.Min(1, 2, 3)) //1
|
||||
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Percent">Percent</span>
|
||||
<p>calculate the percentage of val to total, retain n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Percent(val, total float64, n int) float64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Percent(1, 2, 2)) //1
|
||||
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RoundToFloat">RoundToFloat</span>
|
||||
<p>Round float up to n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RoundToFloat(x float64, n int) float64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.RoundToFloat(0, 0)) //0
|
||||
fmt.Println(mathutil.RoundToFloat(0, 1)) //0
|
||||
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12
|
||||
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
|
||||
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RoundToString">RoundToString</span>
|
||||
<p>Round float up to n decimal places. will return string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RoundToString(x float64, n int) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.RoundToString(0, 0)) //"0"
|
||||
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0:
|
||||
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12"
|
||||
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
|
||||
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="TruncRound">TruncRound</span>
|
||||
<p>Round float off n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TruncRound(x float64, n int) float64
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.TruncRound(0, 0)) //0
|
||||
fmt.Println(mathutil.TruncRound(0, 1)) //0
|
||||
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12
|
||||
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
|
||||
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
317
docs/mathutil_zh-CN.md
Normal file
317
docs/mathutil_zh-CN.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# Mathutil
|
||||
mathutil包实现了一些数学计算的函数.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Average](#Average)
|
||||
- [Exponent](#Exponent)
|
||||
- [Fibonacci](#Fibonacci)
|
||||
- [Factorial](#Factorial)
|
||||
- [Max](#Max)
|
||||
- [Min](#Min)
|
||||
|
||||
- [Percent](#Percent)
|
||||
- [RoundToFloat](#RoundToFloat)
|
||||
- [RoundToString](#RoundToString)
|
||||
- [TruncRound](#TruncRound)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="Average">Average</span>
|
||||
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Average[T lancetconstraints.Number](numbers ...T) T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Average(0, 0)) //0
|
||||
fmt.Println(mathutil.Average(1, 1)) //1
|
||||
avg := mathutil.Average(1.2, 1.4) //1.2999999998
|
||||
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Exponent">Exponent</span>
|
||||
<p>指数计算(x的n次方)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Exponent(x, n int64) int64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Exponent(10, 0)) //1
|
||||
fmt.Println(mathutil.Exponent(10, 1)) //10
|
||||
fmt.Println(mathutil.Exponent(10, 2)) //100
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Fibonacci">Fibonacci</span>
|
||||
<p>计算斐波那契数列的第n个数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Fibonacci(first, second, n int) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
|
||||
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Factorial">Factorial</span>
|
||||
<p>计算阶乘</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Factorial(x uint) uint
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Factorial(0)) //1
|
||||
fmt.Println(mathutil.Factorial(1)) //1
|
||||
fmt.Println(mathutil.Factorial(2)) //2
|
||||
fmt.Println(mathutil.Factorial(3)) //6
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
<p>返回参数中的最大数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Max[T lancetconstraints.Number](numbers ...T) T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Max(0, 0)) //0
|
||||
fmt.Println(mathutil.Max(1, 2, 3)) //3
|
||||
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Min">Min</span>
|
||||
<p>返回参数中的最小数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Min[T lancetconstraints.Number](numbers ...T) T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Min(0, 0)) //0
|
||||
fmt.Println(mathutil.Min(1, 2, 3)) //1
|
||||
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Percent">Percent</span>
|
||||
<p>计算百分比,保留n位小数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Percent(val, total float64, n int) float64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.Percent(1, 2, 2)) //1
|
||||
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RoundToFloat">RoundToFloat</span>
|
||||
<p>四舍五入,保留n位小数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RoundToFloat(x float64, n int) float64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.RoundToFloat(0, 0)) //0
|
||||
fmt.Println(mathutil.RoundToFloat(0, 1)) //0
|
||||
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12
|
||||
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
|
||||
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RoundToString">RoundToString</span>
|
||||
<p>四舍五入,保留n位小数,返回字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RoundToString(x float64, n int) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.RoundToString(0, 0)) //"0"
|
||||
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0:
|
||||
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12"
|
||||
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
|
||||
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="TruncRound">TruncRound</span>
|
||||
<p>截短n位小数(不进行四舍五入)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TruncRound(x float64, n int) float64
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(mathutil.TruncRound(0, 0)) //0
|
||||
fmt.Println(mathutil.TruncRound(0, 1)) //0
|
||||
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12
|
||||
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
|
||||
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
511
docs/netutil.md
Normal file
511
docs/netutil.md
Normal file
@@ -0,0 +1,511 @@
|
||||
# Netutil
|
||||
Package netutil contains functions to get net information and send http request.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||
- [GetInternalIp](#GetInternalIp)
|
||||
- [GetIps](#GetIps)
|
||||
- [GetMacAddrs](#GetMacAddrs)
|
||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [HttpGet](#HttpGet)
|
||||
- [HttpDelete](#HttpDelete)
|
||||
- [HttpPost](#HttpPost)
|
||||
- [HttpPut](#HttpPut)
|
||||
|
||||
- [HttpPatch](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
|
||||
<p>Convert map to url query string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ConvertMapToQueryString(param map[string]any) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var m = map[string]any{
|
||||
"c": 3,
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
qs := netutil.ConvertMapToQueryString(m)
|
||||
|
||||
fmt.Println(qs) //a=1&b=2&c=3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetInternalIp">GetInternalIp</span>
|
||||
<p>Get internal ip information.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetInternalIp() string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
internalIp := netutil.GetInternalIp()
|
||||
ip := net.ParseIP(internalIp)
|
||||
|
||||
fmt.Println(ip) //192.168.1.9
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetIps">GetIps</span>
|
||||
<p>Get all ipv4 list.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetIps() []string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ips := netutil.GetIps()
|
||||
fmt.Println(ips) //[192.168.1.9]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetMacAddrs">GetMacAddrs</span>
|
||||
<p>Get all mac addresses list.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetMacAddrs() []string {
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addrs := netutil.GetMacAddrs()
|
||||
fmt.Println(addrs)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetPublicIpInfo">GetPublicIpInfo</span>
|
||||
<p>Get public ip information.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetPublicIpInfo() (*PublicIpInfo, error)
|
||||
type PublicIpInfo struct {
|
||||
Status string `json:"status"`
|
||||
Country string `json:"country"`
|
||||
CountryCode string `json:"countryCode"`
|
||||
Region string `json:"region"`
|
||||
RegionName string `json:"regionName"`
|
||||
City string `json:"city"`
|
||||
Lat float64 `json:"lat"`
|
||||
Lon float64 `json:"lon"`
|
||||
Isp string `json:"isp"`
|
||||
Org string `json:"org"`
|
||||
As string `json:"as"`
|
||||
Ip string `json:"query"`
|
||||
}
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
publicIpInfo, err := netutil.GetPublicIpInfo()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(publicIpInfo)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsPublicIP">IsPublicIP</span>
|
||||
<p>Checks if a ip is public or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsPublicIP(IP net.IP) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip1 := net.ParseIP("192.168.0.1")
|
||||
ip2 := net.ParseIP("36.112.24.10")
|
||||
|
||||
fmt.Println(netutil.IsPublicIP(ip1)) //false
|
||||
fmt.Println(netutil.IsPublicIP(ip2)) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
<p>Send http get request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpGet(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
resp, err := netutil.HttpGet(url, header)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
<p>Send http post request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPost(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, "TestAddToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
<p>Send http put request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPut(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
type Todo struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, 1, "TestPutToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPut(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
<p>Send http delete request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
resp, err := netutil.HttpDelete(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
<p>Send http patch request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
type Todo struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, 1, "TestPatchToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPatch(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ParseHttpResponse">ParseHttpResponse</span>
|
||||
<p>Decode http response to specified interface.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ParseHttpResponse(resp *http.Response, obj any) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
resp, err := netutil.HttpGet(url, header)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
toDoResp := &Todo{}
|
||||
err = netutil.ParseHttpResponse(resp, toDoResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(toDoResp)
|
||||
}
|
||||
```
|
||||
|
||||
509
docs/netutil_zh-CN.md
Normal file
509
docs/netutil_zh-CN.md
Normal file
@@ -0,0 +1,509 @@
|
||||
# Netutil
|
||||
netutil网络包支持获取ip地址,发送http请求。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||
- [GetInternalIp](#GetInternalIp)
|
||||
- [GetIps](#GetIps)
|
||||
- [GetMacAddrs](#GetMacAddrs)
|
||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [HttpGet](#HttpGet)
|
||||
- [HttpDelete](#HttpDelete)
|
||||
- [HttpPost](#HttpPost)
|
||||
- [HttpPut](#HttpPut)
|
||||
|
||||
- [HttpPatch](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
|
||||
<p>将map转换成http查询字符串.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ConvertMapToQueryString(param map[string]any) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var m = map[string]any{
|
||||
"c": 3,
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
qs := netutil.ConvertMapToQueryString(m)
|
||||
|
||||
fmt.Println(qs) //a=1&b=2&c=3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetInternalIp">GetInternalIp</span>
|
||||
<p>获取内部ip</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetInternalIp() string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
internalIp := netutil.GetInternalIp()
|
||||
ip := net.ParseIP(internalIp)
|
||||
|
||||
fmt.Println(ip) //192.168.1.9
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="GetIps">GetIps</span>
|
||||
<p>获取ipv4地址列表</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetIps() []string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ips := netutil.GetIps()
|
||||
fmt.Println(ips) //[192.168.1.9]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetMacAddrs">GetMacAddrs</span>
|
||||
<p>获取mac地址列</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetMacAddrs() []string {
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addrs := netutil.GetMacAddrs()
|
||||
fmt.Println(addrs)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetPublicIpInfo">GetPublicIpInfo</span>
|
||||
<p>获取公网ip信息</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetPublicIpInfo() (*PublicIpInfo, error)
|
||||
type PublicIpInfo struct {
|
||||
Status string `json:"status"`
|
||||
Country string `json:"country"`
|
||||
CountryCode string `json:"countryCode"`
|
||||
Region string `json:"region"`
|
||||
RegionName string `json:"regionName"`
|
||||
City string `json:"city"`
|
||||
Lat float64 `json:"lat"`
|
||||
Lon float64 `json:"lon"`
|
||||
Isp string `json:"isp"`
|
||||
Org string `json:"org"`
|
||||
As string `json:"as"`
|
||||
Ip string `json:"query"`
|
||||
}
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
publicIpInfo, err := netutil.GetPublicIpInfo()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(publicIpInfo)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsPublicIP">IsPublicIP</span>
|
||||
<p>判断ip是否是公共ip</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsPublicIP(IP net.IP) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip1 := net.ParseIP("192.168.0.1")
|
||||
ip2 := net.ParseIP("36.112.24.10")
|
||||
|
||||
fmt.Println(netutil.IsPublicIP(ip1)) //false
|
||||
fmt.Println(netutil.IsPublicIP(ip2)) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
<p>发送http get请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpGet(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
resp, err := netutil.HttpGet(url, header)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
<p>发送http post请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPost(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, "TestAddToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
<p>发送http put请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPut(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
type Todo struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, 1, "TestPutToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPut(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
<p>发送http delete请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
resp, err := netutil.HttpDelete(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
<p>发送http patch请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
type Todo struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, 1, "TestPatchToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPatch(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ParseHttpResponse">ParseHttpResponse</span>
|
||||
<p>将http请求响应解码成特定struct值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ParseHttpResponse(resp *http.Response, obj any) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
resp, err := netutil.HttpGet(url, header)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
toDoResp := &Todo{}
|
||||
err = netutil.ParseHttpResponse(resp, toDoResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(toDoResp)
|
||||
}
|
||||
```
|
||||
|
||||
138
docs/random.md
Normal file
138
docs/random.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Random
|
||||
Package random implements some basic functions to generate random int and string.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [RandBytes](#RandBytes)
|
||||
- [RandInt](#RandInt)
|
||||
- [RandString](#RandString)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="RandBytes">RandBytes</span>
|
||||
<p>Generate random byte slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandBytes(length int) []byte
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randBytes := random.RandBytes(4)
|
||||
fmt.Println(randBytes)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RandInt">RandInt</span>
|
||||
<p>Generate random int between min and max, may contain min, not max.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandInt(min, max int) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rInt := random.RandInt(1, 10)
|
||||
fmt.Println(rInt)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RandString">RandInt</span>
|
||||
<p>Generate random given length string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandString(length int) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="UUIdV4">UUIdV4</span>
|
||||
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UUIdV4() (string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
uuid, err := random.UUIdV4()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
138
docs/random_zh-CN.md
Normal file
138
docs/random_zh-CN.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Random
|
||||
random随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [RandBytes](#RandBytes)
|
||||
- [RandInt](#RandInt)
|
||||
- [RandString](#RandString)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
### <span id="RandBytes">RandBytes</span>
|
||||
<p>生成随机字节切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandBytes(length int) []byte
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randBytes := random.RandBytes(4)
|
||||
fmt.Println(randBytes)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RandInt">RandInt</span>
|
||||
<p>生成随机int, 范围[min, max)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandInt(min, max int) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
rInt := random.RandInt(1, 10)
|
||||
fmt.Println(rInt)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RandString">RandInt</span>
|
||||
<p>生成随机给定长度的随机字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandString(length int) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="UUIdV4">UUIdV4</span>
|
||||
<p>生成UUID v4字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UUIdV4() (string, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
uuid, err := random.UUIdV4()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
236
docs/retry.md
Normal file
236
docs/retry.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# Retry
|
||||
Package retry is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Context](#Context)
|
||||
- [Retry](#Retry)
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="Context">Context</span>
|
||||
<p>Set retry context config, can cancel the retry with context.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Context(ctx context.Context)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number > 3 {
|
||||
cancel()
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber,
|
||||
retry.RetryDuration(time.Microsecond*50),
|
||||
retry.Context(ctx),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err) //retry is cancelled
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RetryFunc">RetryFunc</span>
|
||||
<p>Function that retry executes.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type RetryFunc func() error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
var increaseNumber retry.RetryFunc
|
||||
increaseNumber = func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryTimes">RetryTimes</span>
|
||||
<p>Set times of retry. Default times is 5.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RetryTimes(n uint)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
|
||||
if err != nil {
|
||||
log.Fatal(err) //2022/02/01 18:42:25 function main.main.func1 run failed after 2 times retry exit status 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryDuration">RetryDuration</span>
|
||||
<p>Set duration of retries. Default duration is 3 second.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RetryDuration(d time.Duration)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Retry">Retry</span>
|
||||
<p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Retry(retryFunc RetryFunc, opts ...Option) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
}
|
||||
```
|
||||
238
docs/retry_zh-CN.md
Normal file
238
docs/retry_zh-CN.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# Retry
|
||||
retry重试执行函数直到函数运行成功或被context cancel。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Context](#Context)
|
||||
- [Retry](#Retry)
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
|
||||
## Document文档
|
||||
|
||||
|
||||
### <span id="Context">Context</span>
|
||||
<p>设置重试context参数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Context(ctx context.Context)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"lancet-demo/retry"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number > 3 {
|
||||
cancel()
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber,
|
||||
retry.RetryDuration(time.Microsecond*50),
|
||||
retry.Context(ctx),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err) //retry is cancelled
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RetryFunc">RetryFunc</span>
|
||||
<p>被重试执行的函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type RetryFunc func() error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
var increaseNumber retry.RetryFunc
|
||||
increaseNumber = func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryTimes">RetryTimes</span>
|
||||
<p>设置重试次数,默认5</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RetryTimes(n uint)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
|
||||
if err != nil {
|
||||
log.Fatal(err) //2022/02/01 18:42:25 function main.main.func1 run failed after 2 times retry exit status 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryDuration">RetryDuration</span>
|
||||
<p>设置重试间隔时间,默认3秒</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RetryDuration(d time.Duration)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Retry">Retry</span>
|
||||
<p>重试执行函数retryFunc,直到函数运行成功,或被context停止</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Retry(retryFunc RetryFunc, opts ...Option) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
}
|
||||
```
|
||||
1021
docs/slice.md
Normal file
1021
docs/slice.md
Normal file
File diff suppressed because it is too large
Load Diff
1021
docs/slice_zh-CN.md
Normal file
1021
docs/slice_zh-CN.md
Normal file
File diff suppressed because it is too large
Load Diff
574
docs/strutil.md
Normal file
574
docs/strutil.md
Normal file
@@ -0,0 +1,574 @@
|
||||
# Strutil
|
||||
Package strutil contains some functions to manipulate string.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [After](#After)
|
||||
- [AfterLast](#AfterLast)
|
||||
- [Before](#Before)
|
||||
- [BeforeLast](#BeforeLast)
|
||||
- [CamelCase](#CamelCase)
|
||||
- [Capitalize](#Capitalize)
|
||||
- [IsString](#IsString)
|
||||
- [KebabCase](#KebabCase)
|
||||
- [LowerFirst](#LowerFirst)
|
||||
- [UpperFirst](#UpperFirst)
|
||||
- [PadEnd](#PadEnd)
|
||||
- [PadStart](#PadStart)
|
||||
- [ReverseStr](#ReverseStr)
|
||||
- [SnakeCase](#SnakeCase)
|
||||
- [Wrap](#Wrap)
|
||||
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="After">After</span>
|
||||
<p>Creates substring in source string after position when char first appear.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func After(s, char string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.After("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.After("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //test/lancet
|
||||
|
||||
s3 := strutil.After("github.com/test/lancet", "test")
|
||||
fmt.Println(s3) // /lancet
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="AfterLast">AfterLast</span>
|
||||
<p>Creates substring in source string after position when char last appear.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AfterLast(s, char string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.AfterLast("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.AfterLast("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //lancet
|
||||
|
||||
s3 := strutil.AfterLast("github.com/test/test/lancet", "test")
|
||||
fmt.Println(s3) // /test/lancet
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Before">Before</span>
|
||||
<p>Creates substring in source string before position when char first appear.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Before(s, char string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Before("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.Before("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //github.com
|
||||
|
||||
s3 := strutil.Before("github.com/test/lancet", "test")
|
||||
fmt.Println(s3) // github.com/
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BeforeLast">BeforeLast</span>
|
||||
<p>Creates substring in source string before position when char first appear.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeforeLast(s, char string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.BeforeLast("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.BeforeLast("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //github.com/test
|
||||
|
||||
s3 := strutil.BeforeLast("github.com/test/test/lancet", "test")
|
||||
fmt.Println(s3) //github.com/test/
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="CamelCase">CamelCase</span>
|
||||
<p>Covert string to camelCase string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CamelCase(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.CamelCase("foo_bar")
|
||||
fmt.Println(s1) //fooBar
|
||||
|
||||
s2 := strutil.CamelCase("Foo-Bar")
|
||||
fmt.Println(s2) //fooBar
|
||||
|
||||
s3 := strutil.CamelCase("Foo&bar")
|
||||
fmt.Println(s3) //fooBar
|
||||
|
||||
s4 := strutil.CamelCase("foo bar")
|
||||
fmt.Println(s4) //fooBar
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Capitalize">Capitalize</span>
|
||||
<p>Convert the first character of a string to upper case.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Capitalize(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Capitalize("foo")
|
||||
fmt.Println(s1) //foo
|
||||
|
||||
s2 := strutil.Capitalize("Foo")
|
||||
fmt.Println(s2) //foo
|
||||
|
||||
s3 := strutil.Capitalize("FOo"
|
||||
fmt.Println(s3) //fOo
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsString">IsString</span>
|
||||
<p>Check if the value's data type is string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsString(v any) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(strutil.IsString("lancet")) //true
|
||||
fmt.Println(strutil.IsString("")) //true
|
||||
|
||||
fmt.Println(strutil.IsString(1)) //false
|
||||
fmt.Println(strutil.IsString("")) //false
|
||||
fmt.Println(strutil.IsString([]string{})) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="KebabCase">KebabCase</span>
|
||||
<p>Covert string to kebab-case.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func KebabCase(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.KebabCase("Foo Bar-")
|
||||
fmt.Println(s1) //foo-bar
|
||||
|
||||
s2 := strutil.KebabCase("foo_Bar")
|
||||
fmt.Println(s2) //foo-bar
|
||||
|
||||
s3 := strutil.KebabCase("fooBar")
|
||||
fmt.Println(s3) //foo-bar
|
||||
|
||||
s4 := strutil.KebabCase("__FOO_BAR__")
|
||||
fmt.Println(s4) //f-o-o-b-a-r
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LowerFirst">LowerFirst</span>
|
||||
<p>Convert the first character of string to lower case.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func LowerFirst(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.LowerFirst("foo")
|
||||
fmt.Println(s1) //foo
|
||||
|
||||
s2 := strutil.LowerFirst("BAR")
|
||||
fmt.Println(s2) //bAR
|
||||
|
||||
s3 := strutil.LowerFirst("FOo")
|
||||
fmt.Println(s3) //fOo
|
||||
|
||||
s4 := strutil.LowerFirst("fOo大")
|
||||
fmt.Println(s4) //fOo大
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="UpperFirst">UpperFirst</span>
|
||||
<p>Convert the first character of string to upper case.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UpperFirst(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.UpperFirst("foo")
|
||||
fmt.Println(s1) //Foo
|
||||
|
||||
s2 := strutil.UpperFirst("bAR")
|
||||
fmt.Println(s2) //BAR
|
||||
|
||||
s3 := strutil.UpperFirst("FOo")
|
||||
fmt.Println(s3) //FOo
|
||||
|
||||
s4 := strutil.UpperFirst("fOo大")
|
||||
fmt.Println(s4) //FOo大
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PadEnd">PadEnd</span>
|
||||
<p>Pads string on the right side if it's shorter than size.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func PadEnd(source string, size int, padStr string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.PadEnd("a", 1, "b")
|
||||
fmt.Println(s1) //a
|
||||
|
||||
s2 := strutil.PadEnd("a", 2, "b")
|
||||
fmt.Println(s2) //ab
|
||||
|
||||
s3 := strutil.PadEnd("abcd", 6, "mno")
|
||||
fmt.Println(s3) //abcdmn
|
||||
|
||||
s4 := strutil.PadEnd("abc", 6, "ab")
|
||||
fmt.Println(s4) //abcaba
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PadStart">PadStart</span>
|
||||
<p>Pads string on the left side if it's shorter than size.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func PadStart(source string, size int, padStr string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.PadStart("a", 1, "b")
|
||||
fmt.Println(s1) //a
|
||||
|
||||
s2 := strutil.PadStart("a", 2, "b")
|
||||
fmt.Println(s2) //ba
|
||||
|
||||
s3 := strutil.PadStart("abcd", 6, "mno")
|
||||
fmt.Println(s3) //mnabcd
|
||||
|
||||
s4 := strutil.PadStart("abc", 6, "ab")
|
||||
fmt.Println(s4) //abaabc
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ReverseStr">ReverseStr</span>
|
||||
<p>Return string whose char order is reversed to the given string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReverseStr(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.ReverseStr("abc")
|
||||
fmt.Println(s1) //cba
|
||||
|
||||
s2 := strutil.ReverseStr("12345")
|
||||
fmt.Println(s2) //54321
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SnakeCase">SnakeCase</span>
|
||||
<p>Covert string to snake_case.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SnakeCase(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.SnakeCase("Foo Bar-")
|
||||
fmt.Println(s1) //foo_bar
|
||||
|
||||
s2 := strutil.SnakeCase("foo_Bar")
|
||||
fmt.Println(s2) //foo_bar
|
||||
|
||||
s3 := strutil.SnakeCase("fooBar")
|
||||
fmt.Println(s3) //foo_bar
|
||||
|
||||
s4 := strutil.SnakeCase("__FOO_BAR__")
|
||||
fmt.Println(s4) //f_o_o_b_a_r
|
||||
|
||||
s5 := strutil.SnakeCase("aBbc-s$@a&%_B.B^C")
|
||||
fmt.Println(s5) //a_bbc_s_a_b_b_c
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Wrap">Wrap</span>
|
||||
<p>Wrap a string with another string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Wrap(str string, wrapWith string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Wrap("ab", "")
|
||||
fmt.Println(s1) //ab
|
||||
|
||||
s2 := strutil.Wrap("", "*")
|
||||
fmt.Println(s2) //""
|
||||
|
||||
s3 := strutil.Wrap("ab", "*")
|
||||
fmt.Println(s3) //*ab*
|
||||
|
||||
s4 := strutil.Wrap("ab", "\"")
|
||||
fmt.Println(s4) //\"ab\"
|
||||
|
||||
s5 := strutil.Wrap("ab", "'")
|
||||
fmt.Println(s5) //'ab'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Wrap">Wrap</span>
|
||||
<p>Unwrap a given string from anther string. will change str value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Unwrap(str string, wrapToken string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Unwrap("ab", "")
|
||||
fmt.Println(s1) //ab
|
||||
|
||||
s2 := strutil.Unwrap("ab", "*")
|
||||
fmt.Println(s2) //ab
|
||||
|
||||
s3 := strutil.Unwrap("**ab**", "*")
|
||||
fmt.Println(s3) //*ab*
|
||||
|
||||
s4 := strutil.Unwrap("*ab", "*")
|
||||
fmt.Println(s4) //*ab
|
||||
|
||||
s5 := strutil.Unwrap("***", "**")
|
||||
fmt.Println(s5) //***
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
575
docs/strutil_zh-CN.md
Normal file
575
docs/strutil_zh-CN.md
Normal file
@@ -0,0 +1,575 @@
|
||||
# Strutil
|
||||
strutil包含处理字符串的相关函数。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [After](#After)
|
||||
- [AfterLast](#AfterLast)
|
||||
- [Before](#Before)
|
||||
- [BeforeLast](#BeforeLast)
|
||||
- [CamelCase](#CamelCase)
|
||||
- [Capitalize](#Capitalize)
|
||||
- [IsString](#IsString)
|
||||
- [KebabCase](#KebabCase)
|
||||
- [LowerFirst](#LowerFirst)
|
||||
- [UpperFirst](#UpperFirst)
|
||||
- [PadEnd](#PadEnd)
|
||||
- [PadStart](#PadStart)
|
||||
- [ReverseStr](#ReverseStr)
|
||||
- [SnakeCase](#SnakeCase)
|
||||
- [Wrap](#Wrap)
|
||||
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
|
||||
## Documentation文档
|
||||
|
||||
|
||||
### <span id="After">After</span>
|
||||
<p>截取源字符串中char首次出现时的位置之后的子字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func After(s, char string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.After("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.After("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //test/lancet
|
||||
|
||||
s3 := strutil.After("github.com/test/lancet", "test")
|
||||
fmt.Println(s3) // /lancet
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="AfterLast">AfterLast</span>
|
||||
<p>截取源字符串中char最后一次出现时的位置之后的子字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AfterLast(s, char string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.AfterLast("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.AfterLast("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //lancet
|
||||
|
||||
s3 := strutil.AfterLast("github.com/test/test/lancet", "test")
|
||||
fmt.Println(s3) // /lancet
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Before">Before</span>
|
||||
<p>截取源字符串中char首次出现时的位置之前的子字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Before(s, char string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Before("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.Before("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //github.com
|
||||
|
||||
s3 := strutil.Before("github.com/test/lancet", "test")
|
||||
fmt.Println(s3) // github.com/
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="BeforeLast">BeforeLast</span>
|
||||
<p>截取源字符串中char最后一次出现时的位置之前的子字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeforeLast(s, char string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.BeforeLast("lancet", "")
|
||||
fmt.Println(s1) //lancet
|
||||
|
||||
s2 := strutil.BeforeLast("github.com/test/lancet", "/")
|
||||
fmt.Println(s2) //github.com/test
|
||||
|
||||
s3 := strutil.BeforeLast("github.com/test/test/lancet", "test")
|
||||
fmt.Println(s3) //github.com/test/
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="CamelCase">CamelCase</span>
|
||||
<p>将字符串转换为驼峰式字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CamelCase(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.CamelCase("foo_bar")
|
||||
fmt.Println(s1) //fooBar
|
||||
|
||||
s2 := strutil.CamelCase("Foo-Bar")
|
||||
fmt.Println(s2) //fooBar
|
||||
|
||||
s3 := strutil.CamelCase("Foo&bar")
|
||||
fmt.Println(s3) //fooBar
|
||||
|
||||
s4 := strutil.CamelCase("foo bar")
|
||||
fmt.Println(s4) //fooBar
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Capitalize">Capitalize</span>
|
||||
<p>将字符串的第一个字符转换为大写</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Capitalize(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Capitalize("foo")
|
||||
fmt.Println(s1) //foo
|
||||
|
||||
s2 := strutil.Capitalize("Foo")
|
||||
fmt.Println(s2) //foo
|
||||
|
||||
s3 := strutil.Capitalize("FOo"
|
||||
fmt.Println(s3) //fOo
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsString">IsString</span>
|
||||
<p>检查值的数据类型是否为字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsString(v any) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(strutil.IsString("lancet")) //true
|
||||
fmt.Println(strutil.IsString("")) //true
|
||||
|
||||
fmt.Println(strutil.IsString(1)) //false
|
||||
fmt.Println(strutil.IsString("")) //false
|
||||
fmt.Println(strutil.IsString([]string{})) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="KebabCase">KebabCase</span>
|
||||
<p>将字符串转换为kebab-case</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func KebabCase(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.KebabCase("Foo Bar-")
|
||||
fmt.Println(s1) //foo-bar
|
||||
|
||||
s2 := strutil.KebabCase("foo_Bar")
|
||||
fmt.Println(s2) //foo-bar
|
||||
|
||||
s3 := strutil.KebabCase("fooBar")
|
||||
fmt.Println(s3) //foo-bar
|
||||
|
||||
s4 := strutil.KebabCase("__FOO_BAR__")
|
||||
fmt.Println(s4) //f-o-o-b-a-r
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="LowerFirst">LowerFirst</span>
|
||||
<p>将字符串的第一个字符转换为小写</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LowerFirst(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.LowerFirst("foo")
|
||||
fmt.Println(s1) //foo
|
||||
|
||||
s2 := strutil.LowerFirst("BAR")
|
||||
fmt.Println(s2) //bAR
|
||||
|
||||
s3 := strutil.LowerFirst("FOo")
|
||||
fmt.Println(s3) //fOo
|
||||
|
||||
s4 := strutil.LowerFirst("fOo大")
|
||||
fmt.Println(s4) //fOo大
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="UpperFirst">UpperFirst</span>
|
||||
<p>将字符串的第一个字符转换为大写</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UpperFirst(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.UpperFirst("foo")
|
||||
fmt.Println(s1) //Foo
|
||||
|
||||
s2 := strutil.UpperFirst("bAR")
|
||||
fmt.Println(s2) //BAR
|
||||
|
||||
s3 := strutil.UpperFirst("FOo")
|
||||
fmt.Println(s3) //FOo
|
||||
|
||||
s4 := strutil.UpperFirst("fOo大")
|
||||
fmt.Println(s4) //FOo大
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PadEnd">PadEnd</span>
|
||||
<p>如果字符串长度短于size,则在右侧填充字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func PadEnd(source string, size int, padStr string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.PadEnd("a", 1, "b")
|
||||
fmt.Println(s1) //a
|
||||
|
||||
s2 := strutil.PadEnd("a", 2, "b")
|
||||
fmt.Println(s2) //ab
|
||||
|
||||
s3 := strutil.PadEnd("abcd", 6, "mno")
|
||||
fmt.Println(s3) //abcdmn
|
||||
|
||||
s4 := strutil.PadEnd("abc", 6, "ab")
|
||||
fmt.Println(s4) //abcaba
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="PadStart">PadStart</span>
|
||||
<p>如果字符串长度短于size,则在左侧填充字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func PadStart(source string, size int, padStr string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.PadStart("a", 1, "b")
|
||||
fmt.Println(s1) //a
|
||||
|
||||
s2 := strutil.PadStart("a", 2, "b")
|
||||
fmt.Println(s2) //ba
|
||||
|
||||
s3 := strutil.PadStart("abcd", 6, "mno")
|
||||
fmt.Println(s3) //mnabcd
|
||||
|
||||
s4 := strutil.PadStart("abc", 6, "ab")
|
||||
fmt.Println(s4) //abaabc
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ReverseStr">ReverseStr</span>
|
||||
<p>返回字符顺序与给定字符串相反的字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReverseStr(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.ReverseStr("abc")
|
||||
fmt.Println(s1) //cba
|
||||
|
||||
s2 := strutil.ReverseStr("12345")
|
||||
fmt.Println(s2) //54321
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SnakeCase">SnakeCase</span>
|
||||
<p>将字符串转换为snake_case形式</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SnakeCase(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.SnakeCase("Foo Bar-")
|
||||
fmt.Println(s1) //foo_bar
|
||||
|
||||
s2 := strutil.SnakeCase("foo_Bar")
|
||||
fmt.Println(s2) //foo_bar
|
||||
|
||||
s3 := strutil.SnakeCase("fooBar")
|
||||
fmt.Println(s3) //foo_bar
|
||||
|
||||
s4 := strutil.SnakeCase("__FOO_BAR__")
|
||||
fmt.Println(s4) //f_o_o_b_a_r
|
||||
|
||||
s5 := strutil.SnakeCase("aBbc-s$@a&%_B.B^C")
|
||||
fmt.Println(s5) //a_bbc_s_a_b_b_c
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Wrap">Wrap</span>
|
||||
<p>用另一个字符串包裹一个字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Wrap(str string, wrapWith string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Wrap("ab", "")
|
||||
fmt.Println(s1) //ab
|
||||
|
||||
s2 := strutil.Wrap("", "*")
|
||||
fmt.Println(s2) //""
|
||||
|
||||
s3 := strutil.Wrap("ab", "*")
|
||||
fmt.Println(s3) //*ab*
|
||||
|
||||
s4 := strutil.Wrap("ab", "\"")
|
||||
fmt.Println(s4) //\"ab\"
|
||||
|
||||
s5 := strutil.Wrap("ab", "'")
|
||||
fmt.Println(s5) //'ab'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
<p>用另一个字符串解开包裹一个字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Unwrap(str string, wrapToken string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := strutil.Unwrap("ab", "")
|
||||
fmt.Println(s1) //ab
|
||||
|
||||
s2 := strutil.Unwrap("ab", "*")
|
||||
fmt.Println(s2) //ab
|
||||
|
||||
s3 := strutil.Unwrap("**ab**", "*")
|
||||
fmt.Println(s3) //*ab*
|
||||
|
||||
s4 := strutil.Unwrap("*ab", "*")
|
||||
fmt.Println(s4) //*ab
|
||||
|
||||
s5 := strutil.Unwrap("***", "**")
|
||||
fmt.Println(s5) //***
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
242
docs/system.md
Normal file
242
docs/system.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# System
|
||||
Package system contains some functions about os, runtime, shell command.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [IsWindows](#IsWindows)
|
||||
- [IsLinux](#IsLinux)
|
||||
- [IsMac](#IsMac)
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="IsWindows">IsWindows</span>
|
||||
<p>Check if current os is windows.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsWindows() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsWindows := system.IsWindows()
|
||||
fmt.Println(isOsWindows)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsLinux">IsLinux</span>
|
||||
<p>Check if current os is linux.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsLinux() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsLinux := system.IsLinux()
|
||||
fmt.Println(isOsLinux)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsMac">IsMac</span>
|
||||
<p>Check if current os is macos.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsMac() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsMac := system.IsMac
|
||||
fmt.Println(isOsMac)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsEnv">GetOsEnv</span>
|
||||
<p>Gets the value of the environment variable named by the key.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetOsEnv(key string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fooEnv := system.GetOsEnv("foo")
|
||||
fmt.Println(fooEnv)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SetOsEnv">SetOsEnv</span>
|
||||
<p>Sets the value of the environment variable named by the key.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SetOsEnv(key, value string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.SetOsEnv("foo", "foo_value")
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RemoveOsEnv">RemoveOsEnv</span>
|
||||
<p>Remove a single environment variable.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RemoveOsEnv(key string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.RemoveOsEnv("foo")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CompareOsEnv">CompareOsEnv</span>
|
||||
<p>Get env named by the key and compare it with comparedEnv.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CompareOsEnv(key, comparedEnv string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
system.SetOsEnv("foo", "foo_value")
|
||||
res := system.CompareOsEnv("foo", "foo_value")
|
||||
fmt.Println(res) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ExecCommand">CompareOsEnv</span>
|
||||
<p>use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
out, errout, err := system.ExecCommand("ls")
|
||||
fmt.Println(out)
|
||||
fmt.Println(errout)
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
242
docs/system_zh-CN.md
Normal file
242
docs/system_zh-CN.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# System
|
||||
system包含os, runtime, shell command相关函数。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [IsWindows](#IsWindows)
|
||||
- [IsLinux](#IsLinux)
|
||||
- [IsMac](#IsMac)
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation文档
|
||||
|
||||
|
||||
### <span id="IsWindows">IsWindows</span>
|
||||
<p>检查当前操作系统是否是windows</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsWindows() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsWindows := system.IsWindows()
|
||||
fmt.Println(isOsWindows)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsLinux">IsLinux</span>
|
||||
<p>检查当前操作系统是否是linux</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsLinux() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsLinux := system.IsLinux()
|
||||
fmt.Println(isOsLinux)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsMac">IsMac</span>
|
||||
<p>检查当前操作系统是否是macos</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsMac() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsMac := system.IsMac
|
||||
fmt.Println(isOsMac)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsEnv">GetOsEnv</span>
|
||||
<p>获取key命名的环境变量的值</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetOsEnv(key string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fooEnv := system.GetOsEnv("foo")
|
||||
fmt.Println(fooEnv)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SetOsEnv">SetOsEnv</span>
|
||||
<p>设置由key命名的环境变量的值</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SetOsEnv(key, value string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.SetOsEnv("foo", "foo_value")
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RemoveOsEnv">RemoveOsEnv</span>
|
||||
<p>删除单个环境变量</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RemoveOsEnv(key string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.RemoveOsEnv("foo")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CompareOsEnv">CompareOsEnv</span>
|
||||
<p>获取key命名的环境变量值并与compareEnv进行比较</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CompareOsEnv(key, comparedEnv string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
system.SetOsEnv("foo", "foo_value")
|
||||
res := system.CompareOsEnv("foo", "foo_value")
|
||||
fmt.Println(res) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ExecCommand">CompareOsEnv</span>
|
||||
<p>使用shell /bin/bash -c(linux) 或 cmd (windows) 执行shell命令</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
out, errout, err := system.ExecCommand("ls")
|
||||
fmt.Println(out)
|
||||
fmt.Println(errout)
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
799
docs/validator.md
Normal file
799
docs/validator.md
Normal file
@@ -0,0 +1,799 @@
|
||||
# Validator
|
||||
Package validator contains some functions for data validation.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [ContainChinese](#ContainChinese)
|
||||
- [ContainLetter](#ContainLetter)
|
||||
- [ContainLower](#ContainLower)
|
||||
- [ContainUpper](#ContainUpper)
|
||||
- [IsAlpha](#IsAlpha)
|
||||
- [IsAllUpper](#IsAllUpper)
|
||||
- [IsAllLower](#IsAllLower)
|
||||
- [IsBase64](#IsBase64)
|
||||
- [IsChineseMobile](#IsChineseMobile)
|
||||
- [IsChineseIdNum](#IsChineseIdNum)
|
||||
- [IsChinesePhone](#IsChinesePhone)
|
||||
- [IsCreditCard](#IsCreditCard)
|
||||
- [IsDns](#IsDns)
|
||||
- [IsEmail](#IsEmail)
|
||||
|
||||
- [IsEmptyString](#IsEmptyString)
|
||||
- [IsFloatStr](#IsFloatStr)
|
||||
- [IsNumberStr](#IsNumberStr)
|
||||
- [IsJSON](#IsJSON)
|
||||
- [IsRegexMatch](#IsRegexMatch)
|
||||
- [IsIntStr](#IsIntStr)
|
||||
- [IsIp](#IsIp)
|
||||
- [IsIpV4](#IsIpV4)
|
||||
- [IsIpV6](#IsIpV6)
|
||||
- [IsStrongPassword](#IsStrongPassword)
|
||||
- [IsUrl](#IsUrl)
|
||||
- [IsWeakPassword](#IsWeakPassword)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="ContainChinese">ContainChinese</span>
|
||||
<p>Check if the string contain mandarin chinese.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainChinese(s string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainChinese("你好")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.ContainChinese("你好hello")
|
||||
fmt.Println(res2) //true
|
||||
|
||||
res3 := validator.ContainChinese("hello")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ContainLetter">ContainLetter</span>
|
||||
<p>Check if the string contain at least one letter.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainLetter(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainLetter("1bc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.ContainLetter("123")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.ContainLetter("&@#$%^&*")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainLower">ContainLower</span>
|
||||
<p>Check if the string contain at least one lower case letter a-z.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainLower(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainLower("1bc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.ContainLower("123")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.ContainLower("1BC")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainUpper">ContainUpper</span>
|
||||
<p>Check if the string contain at least one upper case letter A-Z.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainUpper(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainUpper("1bc")
|
||||
fmt.Println(res1) //false
|
||||
|
||||
res2 := validator.ContainUpper("123")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.ContainUpper("1BC")
|
||||
fmt.Println(res3) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsAlpha">IsAlpha</span>
|
||||
<p>Check if the string contains only letters (a-zA-Z).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsAlpha(s string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsAlpha("abc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsAlpha("1bc")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.IsAlpha("")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsAllUpper">IsAllUpper</span>
|
||||
<p>Check if string is all upper case letters A-Z.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsAllUpper(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsAllUpper("ABC")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsAllUpper("aBC")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsAllLower">IsAllLower</span>
|
||||
<p>Check if string is all lower case letters a-z.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsAllLower(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsAllLower("abc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsAllLower("abC")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsBase64">IsBase64</span>
|
||||
<p>Check if the string is base64 string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsBase64(base64 string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsBase64("aGVsbG8=")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsBase64("123456")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsChineseMobile">IsChineseMobile</span>
|
||||
<p>Check if the string is valid chinese mobile number.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsChineseMobile(mobileNum string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsChineseMobile("13263527980")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsChineseMobile("434324324")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsChineseIdNum">IsChineseIdNum</span>
|
||||
<p>Check if the string is chinese id number.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsChineseIdNum(id string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsChineseIdNum("210911192105130715")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsChineseIdNum("123456")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsChinesePhone">IsChinesePhone</span>
|
||||
<p>Check if the string is chinese phone number.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsChinesePhone(phone string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsChinesePhone("010-32116675")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsChinesePhone("123-87562")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsCreditCard">IsCreditCard</span>
|
||||
<p>Check if the string is credit card.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsCreditCard(creditCart string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsCreditCard("4111111111111111")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsCreditCard("123456")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsDns">IsDns</span>
|
||||
<p>Check if the string is valid dns.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsDns(dns string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsDns("abc.com")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsDns("a.b.com")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.IsDns("http://abc.com")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmail">IsEmail</span>
|
||||
<p>Check if the string is email address.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsEmail(email string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsEmail("abc@xyz.com")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsEmail("a.b@@com")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmptyString">IsEmptyString</span>
|
||||
<p>Check if the string is empty or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsEmptyString(s string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsEmptyString("")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsEmptyString("abc")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsFloatStr">IsFloatStr</span>
|
||||
<p>Check if the string can convert to a float.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsFloatStr(s string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsFloatStr("")) //false
|
||||
fmt.Println(validator.IsFloatStr("12a")) //false
|
||||
fmt.Println(validator.IsFloatStr("3.")) //true
|
||||
fmt.Println(validator.IsFloatStr("+3.")) //true
|
||||
fmt.Println(validator.IsFloatStr("-3.")) //true
|
||||
fmt.Println(validator.IsFloatStr("12")) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsNumberStr">IsNumberStr</span>
|
||||
<p>Check if the string can convert to a number.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsNumberStr(s string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsNumberStr("")) //false
|
||||
fmt.Println(validator.IsNumberStr("12a")) //false
|
||||
fmt.Println(validator.IsNumberStr("3.")) //true
|
||||
fmt.Println(validator.IsNumberStr("+3.")) //true
|
||||
fmt.Println(validator.IsNumberStr("-3.")) //true
|
||||
fmt.Println(validator.IsNumberStr("+3e2")) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsJSON">IsJSON</span>
|
||||
<p>Check if the string is valid JSON.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsJSON(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsJSON("")) //false
|
||||
fmt.Println(validator.IsJSON("abc")) //false
|
||||
fmt.Println(validator.IsJSON("{}")) //true
|
||||
fmt.Println(validator.IsJSON("[]")) //true
|
||||
fmt.Println(validator.IsJSON("123")) //true
|
||||
fmt.Println(validator.IsJSON("{\"name\": \"test\"}")) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsRegexMatch">IsRegexMatch</span>
|
||||
<p>Check if the string match the regexp.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsRegexMatch(s, regex string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsRegexMatch("abc", `^[a-zA-Z]+$`)) //true
|
||||
fmt.Println(validator.IsRegexMatch("1ab", `^[a-zA-Z]+$`)) //false
|
||||
fmt.Println(validator.IsRegexMatch("", `^[a-zA-Z]+$`)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIntStr">IsIntStr</span>
|
||||
<p>Check if the string can convert to a integer.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsIntStr(s string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIntStr("+3")) //true
|
||||
fmt.Println(validator.IsIntStr("-3")) //true
|
||||
fmt.Println(validator.IsIntStr("3.")) //false
|
||||
fmt.Println(validator.IsIntStr("abc")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIp">IsIp</span>
|
||||
<p>Check if the string is a ip address.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsIp(ipstr string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIp("127.0.0.1")) //true
|
||||
fmt.Println(validator.IsIp("::0:0:0:0:0:0:1")) //true
|
||||
fmt.Println(validator.IsIp("127.0.0")) //false
|
||||
fmt.Println(validator.IsIp("127")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIpV4">IsIpV4</span>
|
||||
<p>Check if the string is a ipv4 address.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsIpV4(ipstr string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIpV4("127.0.0.1")) //true
|
||||
fmt.Println(validator.IsIpV4("::0:0:0:0:0:0:1")) //false
|
||||
fmt.Println(validator.IsIpV4("127.0.0")) //false
|
||||
fmt.Println(validator.IsIpV4("127")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIpV6">IsIpV6</span>
|
||||
<p>Check if the string is a ipv6 address.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsIpV6(ipstr string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIpV6("127.0.0.1")) //false
|
||||
fmt.Println(validator.IsIpV6("::0:0:0:0:0:0:1")) //true
|
||||
fmt.Println(validator.IsIpV6("127.0.0")) //false
|
||||
fmt.Println(validator.IsIpV6("127")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsStrongPassword">IsStrongPassword</span>
|
||||
<p>Check if the string is strong password (alpha(lower+upper) + number + special chars(!@#$%^&*()?><)).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsStrongPassword(password string, length int) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsStrongPassword("abc", 3)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abc123", 6)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abcABC", 6)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abcABC123@#$", 16)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abcABC123@#$", 12)) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsUrl">IsUrl</span>
|
||||
<p>Check if the string is url.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsUrl(str string) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsUrl("http://abc.com")) //true
|
||||
fmt.Println(validator.IsUrl("abc.com")) //true
|
||||
fmt.Println(validator.IsUrl("a.b.com")) //true
|
||||
fmt.Println(validator.IsUrl("abc")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsWeakPassword">IsWeakPassword</span>
|
||||
<p>Check if the string is weak password(only letter or only number or letter + number)
|
||||
.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsWeakPassword(password string, length int) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsWeakPassword("abc")) //true
|
||||
fmt.Println(validator.IsWeakPassword("123")) //true
|
||||
fmt.Println(validator.IsWeakPassword("abc123")) //true
|
||||
fmt.Println(validator.IsWeakPassword("abc123@#$")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
799
docs/validator_zh-CN.md
Normal file
799
docs/validator_zh-CN.md
Normal file
@@ -0,0 +1,799 @@
|
||||
# Validator
|
||||
validator验证器包,包含常用字符串格式验证函数。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录:
|
||||
- [ContainChinese](#ContainChinese)
|
||||
- [ContainLetter](#ContainLetter)
|
||||
- [ContainLower](#ContainLower)
|
||||
- [ContainUpper](#ContainUpper)
|
||||
- [IsAlpha](#IsAlpha)
|
||||
- [IsAllUpper](#IsAllUpper)
|
||||
- [IsAllLower](#IsAllLower)
|
||||
- [IsBase64](#IsBase64)
|
||||
- [IsChineseMobile](#IsChineseMobile)
|
||||
- [IsChineseIdNum](#IsChineseIdNum)
|
||||
- [IsChinesePhone](#IsChinesePhone)
|
||||
- [IsCreditCard](#IsCreditCard)
|
||||
- [IsDns](#IsDns)
|
||||
- [IsEmail](#IsEmail)
|
||||
|
||||
- [IsEmptyString](#IsEmptyString)
|
||||
- [IsFloatStr](#IsFloatStr)
|
||||
- [IsNumberStr](#IsNumberStr)
|
||||
- [IsJSON](#IsJSON)
|
||||
- [IsRegexMatch](#IsRegexMatch)
|
||||
- [IsIntStr](#IsIntStr)
|
||||
- [IsIp](#IsIp)
|
||||
- [IsIpV4](#IsIpV4)
|
||||
- [IsIpV6](#IsIpV6)
|
||||
- [IsStrongPassword](#IsStrongPassword)
|
||||
- [IsUrl](#IsUrl)
|
||||
- [IsWeakPassword](#IsWeakPassword)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
### <span id="ContainChinese">ContainChinese</span>
|
||||
<p>验证字符串是否包含中文字符</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainChinese(s string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainChinese("你好")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.ContainChinese("你好hello")
|
||||
fmt.Println(res2) //true
|
||||
|
||||
res3 := validator.ContainChinese("hello")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ContainLetter">ContainLetter</span>
|
||||
<p>验证字符串是否包含至少一个英文字母</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainLetter(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainLetter("1bc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.ContainLetter("123")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.ContainLetter("&@#$%^&*")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainLower">ContainLower</span>
|
||||
<p>验证字符串是否包含至少一个英文小写字母</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainLower(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainLower("1bc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.ContainLower("123")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.ContainLower("1BC")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainUpper">ContainUpper</span>
|
||||
<p>验证字符串是否包含至少一个英文大写字母.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainUpper(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.ContainUpper("1bc")
|
||||
fmt.Println(res1) //false
|
||||
|
||||
res2 := validator.ContainUpper("123")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.ContainUpper("1BC")
|
||||
fmt.Println(res3) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsAlpha">IsAlpha</span>
|
||||
<p>验证字符串是否只包含英文字母</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsAlpha(s string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsAlpha("abc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsAlpha("1bc")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.IsAlpha("")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsAllUpper">IsAllUpper</span>
|
||||
<p>验证字符串是否全是大写英文字母</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsAllUpper(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsAllUpper("ABC")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsAllUpper("aBC")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsAllLower">IsAllLower</span>
|
||||
<p>验证字符串是否全是小写英文字母</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsAllLower(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsAllLower("abc")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsAllLower("abC")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsBase64">IsBase64</span>
|
||||
<p>验证字符串是否是base64编码</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsBase64(base64 string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsBase64("aGVsbG8=")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsBase64("123456")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsChineseMobile">IsChineseMobile</span>
|
||||
<p>验证字符串是否是中国手机号码</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsChineseMobile(mobileNum string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsChineseMobile("13263527980")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsChineseMobile("434324324")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsChineseIdNum">IsChineseIdNum</span>
|
||||
<p>验证字符串是否是中国身份证号码</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsChineseIdNum(id string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsChineseIdNum("210911192105130715")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsChineseIdNum("123456")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsChinesePhone">IsChinesePhone</span>
|
||||
<p>验证字符串是否是中国电话座机号码</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsChinesePhone(phone string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsChinesePhone("010-32116675")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsChinesePhone("123-87562")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsCreditCard">IsCreditCard</span>
|
||||
<p>验证字符串是否是信用卡号码</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsCreditCard(creditCart string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsCreditCard("4111111111111111")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsCreditCard("123456")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsDns">IsDns</span>
|
||||
<p>验证字符串是否是有效dns</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsDns(dns string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsDns("abc.com")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsDns("a.b.com")
|
||||
fmt.Println(res2) //false
|
||||
|
||||
res3 := validator.IsDns("http://abc.com")
|
||||
fmt.Println(res3) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmail">IsEmail</span>
|
||||
<p>验证字符串是否是有效电子邮件地址</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsEmail(email string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsEmail("abc@xyz.com")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsEmail("a.b@@com")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsEmptyString">IsEmptyString</span>
|
||||
<p>验证字符串是否是空字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsEmptyString(s string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
res1 := validator.IsEmptyString("")
|
||||
fmt.Println(res1) //true
|
||||
|
||||
res2 := validator.IsEmptyString("abc")
|
||||
fmt.Println(res2) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsFloatStr">IsFloatStr</span>
|
||||
<p>验证字符串是否是可以转换为浮点数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsFloatStr(s string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsFloatStr("")) //false
|
||||
fmt.Println(validator.IsFloatStr("12a")) //false
|
||||
fmt.Println(validator.IsFloatStr("3.")) //true
|
||||
fmt.Println(validator.IsFloatStr("+3.")) //true
|
||||
fmt.Println(validator.IsFloatStr("-3.")) //true
|
||||
fmt.Println(validator.IsFloatStr("12")) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsNumberStr">IsNumberStr</span>
|
||||
<p>验证字符串是否是可以转换为数字</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsNumberStr(s string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsNumberStr("")) //false
|
||||
fmt.Println(validator.IsNumberStr("12a")) //false
|
||||
fmt.Println(validator.IsNumberStr("3.")) //true
|
||||
fmt.Println(validator.IsNumberStr("+3.")) //true
|
||||
fmt.Println(validator.IsNumberStr("-3.")) //true
|
||||
fmt.Println(validator.IsNumberStr("+3e2")) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsJSON">IsJSON</span>
|
||||
<p>验证字符串是否是有效json</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsJSON(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsJSON("")) //false
|
||||
fmt.Println(validator.IsJSON("abc")) //false
|
||||
fmt.Println(validator.IsJSON("{}")) //true
|
||||
fmt.Println(validator.IsJSON("[]")) //true
|
||||
fmt.Println(validator.IsJSON("123")) //true
|
||||
fmt.Println(validator.IsJSON("{\"name\": \"test\"}")) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsRegexMatch">IsRegexMatch</span>
|
||||
<p>验证字符串是否可以匹配正则表达式</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsRegexMatch(s, regex string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsRegexMatch("abc", `^[a-zA-Z]+$`)) //true
|
||||
fmt.Println(validator.IsRegexMatch("1ab", `^[a-zA-Z]+$`)) //false
|
||||
fmt.Println(validator.IsRegexMatch("", `^[a-zA-Z]+$`)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIntStr">IsIntStr</span>
|
||||
<p>验证字符串是否是可以转换为整数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsIntStr(s string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIntStr("+3")) //true
|
||||
fmt.Println(validator.IsIntStr("-3")) //true
|
||||
fmt.Println(validator.IsIntStr("3.")) //false
|
||||
fmt.Println(validator.IsIntStr("abc")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIp">IsIp</span>
|
||||
<p>验证字符串是否是ip地址</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsIp(ipstr string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIp("127.0.0.1")) //true
|
||||
fmt.Println(validator.IsIp("::0:0:0:0:0:0:1")) //true
|
||||
fmt.Println(validator.IsIp("127.0.0")) //false
|
||||
fmt.Println(validator.IsIp("127")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIpV4">IsIpV4</span>
|
||||
<p>验证字符串是否是ipv4地址</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsIpV4(ipstr string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIpV4("127.0.0.1")) //true
|
||||
fmt.Println(validator.IsIpV4("::0:0:0:0:0:0:1")) //false
|
||||
fmt.Println(validator.IsIpV4("127.0.0")) //false
|
||||
fmt.Println(validator.IsIpV4("127")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsIpV6">IsIpV6</span>
|
||||
<p>验证字符串是否是ipv6地址</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsIpV6(ipstr string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsIpV6("127.0.0.1")) //false
|
||||
fmt.Println(validator.IsIpV6("::0:0:0:0:0:0:1")) //true
|
||||
fmt.Println(validator.IsIpV6("127.0.0")) //false
|
||||
fmt.Println(validator.IsIpV6("127")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsStrongPassword">IsStrongPassword</span>
|
||||
<p>验证字符串是否是强密码:(alpha(lower+upper) + number + special chars(!@#$%^&*()?><))</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsStrongPassword(password string, length int) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsStrongPassword("abc", 3)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abc123", 6)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abcABC", 6)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abcABC123@#$", 16)) //false
|
||||
fmt.Println(validator.IsStrongPassword("abcABC123@#$", 12)) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsUrl">IsUrl</span>
|
||||
<p>验证字符串是否是url</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsUrl(str string) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsUrl("http://abc.com")) //true
|
||||
fmt.Println(validator.IsUrl("abc.com")) //true
|
||||
fmt.Println(validator.IsUrl("a.b.com")) //true
|
||||
fmt.Println(validator.IsUrl("abc")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsWeakPassword">IsWeakPassword</span>
|
||||
<p>验证字符串是否是弱密码:(only letter or only number or letter + number)
|
||||
.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsWeakPassword(password string, length int) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsWeakPassword("abc")) //true
|
||||
fmt.Println(validator.IsWeakPassword("123")) //true
|
||||
fmt.Println(validator.IsWeakPassword("abc123")) //true
|
||||
fmt.Println(validator.IsWeakPassword("abc123@#$")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
57
docs/xerror.md
Normal file
57
docs/xerror.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Xerror
|
||||
Package xerror implements helpers for errors.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/xerror"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
<p>Unwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Unwrap[T any](val T, err error) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/xerror"
|
||||
)
|
||||
|
||||
func main() {
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
|
||||
}()
|
||||
|
||||
xerror.Unwrap(strconv.Atoi("4o2"))
|
||||
}
|
||||
```
|
||||
57
docs/xerror_zh-CN.md
Normal file
57
docs/xerror_zh-CN.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Xerror
|
||||
xerror错误处理逻辑封装
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/xerror"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
<p>如果err为nil则展开,则它返回一个有效值。 如果err不是nil则Unwrap使用err发生恐慌。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Unwrap[T any](val T, err error) T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/xerror"
|
||||
)
|
||||
|
||||
func main() {
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
|
||||
}()
|
||||
|
||||
xerror.Unwrap(strconv.Atoi("4o2"))
|
||||
}
|
||||
```
|
||||
148
fileutil/file.go
148
fileutil/file.go
@@ -5,11 +5,16 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsExist checks if a file or directory exists
|
||||
@@ -148,3 +153,146 @@ func ListFileNames(path string) ([]string, error) {
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Zip create zip file, fpath could be a single file or a directory
|
||||
func Zip(fpath string, destPath string) error {
|
||||
zipFile, err := os.Create(destPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
archive := zip.NewWriter(zipFile)
|
||||
defer archive.Close()
|
||||
|
||||
filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = strings.TrimPrefix(path, filepath.Dir(fpath)+"/")
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(writer, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnZip unzip the file and save it to destPath
|
||||
func UnZip(zipFile string, destPath string) error {
|
||||
zipReader, err := zip.OpenReader(zipFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipReader.Close()
|
||||
|
||||
for _, f := range zipReader.File {
|
||||
path := filepath.Join(destPath, f.Name)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(path, os.ModePerm)
|
||||
} else {
|
||||
if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inFile, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer inFile.Close()
|
||||
|
||||
outFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outFile.Close()
|
||||
|
||||
_, err = io.Copy(outFile, inFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsLink checks if a file is symbol link or not
|
||||
func IsLink(path string) bool {
|
||||
fi, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return fi.Mode()&os.ModeSymlink != 0
|
||||
}
|
||||
|
||||
// FileMode return file's mode and permission
|
||||
func FileMode(path string) (fs.FileMode, error) {
|
||||
fi, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return fi.Mode(), nil
|
||||
}
|
||||
|
||||
// MiMeType return file mime type
|
||||
// param `file` should be string(file path) or *os.File
|
||||
func MiMeType(file any) string {
|
||||
var mediatype string
|
||||
|
||||
readBuffer := func(f *os.File) ([]byte, error) {
|
||||
buffer := make([]byte, 512)
|
||||
_, err := f.Read(buffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
if filePath, ok := file.(string); ok {
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return mediatype
|
||||
}
|
||||
buffer, err := readBuffer(f)
|
||||
if err != nil {
|
||||
return mediatype
|
||||
}
|
||||
return http.DetectContentType(buffer)
|
||||
}
|
||||
|
||||
if f, ok := file.(*os.File); ok {
|
||||
buffer, err := readBuffer(f)
|
||||
if err != nil {
|
||||
return mediatype
|
||||
}
|
||||
return http.DetectContentType(buffer)
|
||||
}
|
||||
return mediatype
|
||||
}
|
||||
|
||||
@@ -2,137 +2,201 @@ package fileutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestIsExist(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsExist")
|
||||
|
||||
cases := []string{"./", "./file.go", "./a.txt"}
|
||||
expected := []bool{true, true, false}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res := IsExist(cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "IsExist", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual := IsExist(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCreateFile")
|
||||
|
||||
f := "./text.txt"
|
||||
if CreateFile(f) {
|
||||
file, err := os.Open(f)
|
||||
if err != nil {
|
||||
utils.LogFailedTestInfo(t, "CreateFile", f, f, "create file error: "+err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
if file.Name() != f {
|
||||
utils.LogFailedTestInfo(t, "CreateFile", f, f, file.Name())
|
||||
t.FailNow()
|
||||
}
|
||||
assert.IsNil(err)
|
||||
assert.Equal(f, file.Name())
|
||||
} else {
|
||||
utils.LogFailedTestInfo(t, "CreateFile", f, f, "create file error")
|
||||
t.FailNow()
|
||||
}
|
||||
os.Remove(f)
|
||||
}
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsDir")
|
||||
|
||||
cases := []string{"./", "./a.txt"}
|
||||
expected := []bool{true, false}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
res := IsDir(cases[i])
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "IsDir", cases[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual := IsDir(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRemoveFile")
|
||||
f := "./text.txt"
|
||||
if CreateFile(f) {
|
||||
if !IsExist(f) {
|
||||
CreateFile(f)
|
||||
err := RemoveFile(f)
|
||||
if err != nil {
|
||||
utils.LogFailedTestInfo(t, "RemoveFile", f, f, err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
} else {
|
||||
utils.LogFailedTestInfo(t, "RemoveFile", f, f, "create file error")
|
||||
t.FailNow()
|
||||
assert.IsNil(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCopyFile")
|
||||
|
||||
srcFile := "./text.txt"
|
||||
CreateFile(srcFile)
|
||||
|
||||
dstFile := "./text_copy.txt"
|
||||
destFile := "./text_copy.txt"
|
||||
|
||||
err := CopyFile(srcFile, dstFile)
|
||||
err := CopyFile(srcFile, destFile)
|
||||
if err != nil {
|
||||
file, err := os.Open(dstFile)
|
||||
if err != nil {
|
||||
utils.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, "create file error: "+err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
if file.Name() != dstFile {
|
||||
utils.LogFailedTestInfo(t, "CopyFile", srcFile, dstFile, file.Name())
|
||||
t.FailNow()
|
||||
}
|
||||
file, err := os.Open(destFile)
|
||||
assert.IsNil(err)
|
||||
assert.Equal(destFile, file.Name())
|
||||
}
|
||||
os.Remove(srcFile)
|
||||
os.Remove(destFile)
|
||||
}
|
||||
|
||||
func TestListFileNames(t *testing.T) {
|
||||
filesInCurrentPath, err := ListFileNames("../datetime/")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
expected := []string{"datetime.go", "datetime_test.go"}
|
||||
if !reflect.DeepEqual(filesInCurrentPath, expected) {
|
||||
utils.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
|
||||
t.FailNow()
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestListFileNames")
|
||||
|
||||
filesInPath, err := ListFileNames("./")
|
||||
assert.IsNil(err)
|
||||
|
||||
expected := []string{"file.go", "file_test.go"}
|
||||
assert.Equal(expected, filesInPath)
|
||||
}
|
||||
|
||||
func TestReadFileToString(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReadFileToString")
|
||||
|
||||
path := "./text.txt"
|
||||
CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
res, _ := ReadFileToString(path)
|
||||
if res != "hello world" {
|
||||
utils.LogFailedTestInfo(t, "ReadFileToString", path, "hello world", res)
|
||||
}
|
||||
content, _ := ReadFileToString(path)
|
||||
assert.Equal("hello world", content)
|
||||
|
||||
os.Remove(path)
|
||||
}
|
||||
|
||||
func TestClearFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestClearFile")
|
||||
|
||||
path := "./text.txt"
|
||||
CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
|
||||
f.WriteString("hello world")
|
||||
|
||||
CreateFile(path)
|
||||
err := ClearFile(path)
|
||||
assert.IsNil(err)
|
||||
|
||||
res, _ := ReadFileToString(path)
|
||||
if res != "" {
|
||||
utils.LogFailedTestInfo(t, "CreateFile", path, "", res)
|
||||
}
|
||||
content, _ := ReadFileToString(path)
|
||||
assert.Equal("", content)
|
||||
|
||||
os.Remove(path)
|
||||
}
|
||||
|
||||
func TestReadFileByLine(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReadFileByLine")
|
||||
|
||||
path := "./text.txt"
|
||||
CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
expected := []string{"hello", "world"}
|
||||
res, _ := ReadFileByLine(path)
|
||||
if !reflect.DeepEqual(res, expected) {
|
||||
utils.LogFailedTestInfo(t, "ReadFileByLine", path, expected, res)
|
||||
}
|
||||
actual, _ := ReadFileByLine(path)
|
||||
assert.Equal(expected, actual)
|
||||
|
||||
os.Remove(path)
|
||||
}
|
||||
|
||||
func TestZipAndUnZip(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestZipAndUnZip")
|
||||
|
||||
srcFile := "./text.txt"
|
||||
CreateFile(srcFile)
|
||||
|
||||
file, _ := os.OpenFile(srcFile, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer file.Close()
|
||||
file.WriteString("hello\nworld")
|
||||
|
||||
zipFile := "./text.zip"
|
||||
err := Zip(srcFile, zipFile)
|
||||
assert.IsNil(err)
|
||||
|
||||
unZipPath := "./unzip"
|
||||
err = UnZip(zipFile, unZipPath)
|
||||
assert.IsNil(err)
|
||||
|
||||
unZipFile := "./unzip/text.txt"
|
||||
assert.Equal(true, IsExist(unZipFile))
|
||||
|
||||
os.Remove(srcFile)
|
||||
os.Remove(zipFile)
|
||||
os.RemoveAll(unZipPath)
|
||||
}
|
||||
|
||||
func TestFileMode(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFileMode")
|
||||
|
||||
srcFile := "./text.txt"
|
||||
CreateFile(srcFile)
|
||||
|
||||
mode, err := FileMode(srcFile)
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log(mode)
|
||||
|
||||
os.Remove(srcFile)
|
||||
}
|
||||
|
||||
func TestIsLink(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsLink")
|
||||
|
||||
srcFile := "./text.txt"
|
||||
CreateFile(srcFile)
|
||||
|
||||
linkFile := "./text.link"
|
||||
if !IsExist(linkFile) {
|
||||
_ = os.Symlink(srcFile, linkFile)
|
||||
}
|
||||
assert.Equal(true, IsLink(linkFile))
|
||||
|
||||
assert.Equal(false, IsLink("./file.go"))
|
||||
|
||||
os.Remove(srcFile)
|
||||
os.Remove(linkFile)
|
||||
}
|
||||
|
||||
func TestMiMeType(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMiMeType")
|
||||
|
||||
f, _ := os.Open("./file.go")
|
||||
assert.Equal("text/plain; charset=utf-8", MiMeType(f))
|
||||
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package formatter
|
||||
import "strings"
|
||||
|
||||
// Comma add comma to number by every 3 numbers from right. ahead by symbol char
|
||||
func Comma(v interface{}, symbol string) string {
|
||||
func Comma(v any, symbol string) string {
|
||||
s := numString(v)
|
||||
dotIndex := strings.Index(s, ".")
|
||||
if dotIndex != -1 {
|
||||
|
||||
@@ -14,7 +14,7 @@ func commaString(s string) string {
|
||||
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
|
||||
}
|
||||
|
||||
func numString(value interface{}) string {
|
||||
func numString(value any) string {
|
||||
switch reflect.TypeOf(value).Kind() {
|
||||
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
|
||||
return fmt.Sprintf("%v", value)
|
||||
@@ -3,26 +3,21 @@ package formatter
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestComma(t *testing.T) {
|
||||
comma(t, "", "", "")
|
||||
comma(t, "aa", "", "")
|
||||
comma(t, "aa.a", "", "")
|
||||
comma(t, []int{1}, "", "")
|
||||
comma(t, "123", "", "123")
|
||||
comma(t, "12345", "", "12,345")
|
||||
comma(t, 12345, "", "12,345")
|
||||
comma(t, 12345, "$", "$12,345")
|
||||
comma(t, 12345, "¥", "¥12,345")
|
||||
comma(t, 12345.6789, "", "12,345.6789")
|
||||
}
|
||||
assert := internal.NewAssert(t, "TestComma")
|
||||
|
||||
func comma(t *testing.T, test interface{}, symbol string, expected interface{}) {
|
||||
res := Comma(test, symbol)
|
||||
if res != expected {
|
||||
utils.LogFailedTestInfo(t, "Comma", test, expected, res)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal("", Comma("", ""))
|
||||
assert.Equal("", Comma("aa", ""))
|
||||
assert.Equal("", Comma("aa.a", ""))
|
||||
assert.Equal("", Comma([]int{1}, ""))
|
||||
assert.Equal("123", Comma("123", ""))
|
||||
assert.Equal("12,345", Comma("12345", ""))
|
||||
|
||||
assert.Equal("12,345", Comma(12345, ""))
|
||||
assert.Equal("$12,345", Comma(12345, "$"))
|
||||
assert.Equal("¥12,345", Comma(12345, "¥"))
|
||||
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@ import (
|
||||
)
|
||||
|
||||
// After creates a function that invokes func once it's called n or more times
|
||||
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||
func After(n int, fn any) func(args ...any) []reflect.Value {
|
||||
// Catch programming error while constructing the closure
|
||||
MustBeFunction(fn)
|
||||
return func(args ...interface{}) []reflect.Value {
|
||||
mustBeFunction(fn)
|
||||
|
||||
return func(args ...any) []reflect.Value {
|
||||
n--
|
||||
if n < 1 {
|
||||
return unsafeInvokeFunc(fn, args...)
|
||||
@@ -23,11 +24,11 @@ func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||
}
|
||||
|
||||
// Before creates a function that invokes func once it's called less than n times
|
||||
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||
func Before(n int, fn any) func(args ...any) []reflect.Value {
|
||||
// Catch programming error while constructing the closure
|
||||
MustBeFunction(fn)
|
||||
mustBeFunction(fn)
|
||||
var res []reflect.Value
|
||||
return func(args ...interface{}) []reflect.Value {
|
||||
return func(args ...any) []reflect.Value {
|
||||
if n > 0 {
|
||||
res = unsafeInvokeFunc(fn, args...)
|
||||
}
|
||||
@@ -39,20 +40,20 @@ func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||
}
|
||||
}
|
||||
|
||||
// Fn is for curry function which is func(...interface{}) interface{}
|
||||
type Fn func(...interface{}) interface{}
|
||||
// Fn is for curry function which is func(...any) any
|
||||
type Fn func(...any) any
|
||||
|
||||
// Curry make a curry function
|
||||
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} {
|
||||
return func(values ...interface{}) interface{} {
|
||||
v := append([]interface{}{i}, values...)
|
||||
func (f Fn) Curry(i any) func(...any) any {
|
||||
return func(values ...any) any {
|
||||
v := append([]any{i}, values...)
|
||||
return f(v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Compose compose the functions from right to left
|
||||
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} {
|
||||
return func(s ...interface{}) interface{} {
|
||||
func Compose(fnList ...func(...any) any) func(...any) any {
|
||||
return func(s ...any) any {
|
||||
f := fnList[0]
|
||||
restFn := fnList[1:]
|
||||
|
||||
@@ -65,15 +66,39 @@ func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) in
|
||||
}
|
||||
|
||||
// Delay make the function execution after delayed time
|
||||
func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
|
||||
func Delay(delay time.Duration, fn any, args ...any) {
|
||||
// Catch programming error while constructing the closure
|
||||
mustBeFunction(fn)
|
||||
|
||||
time.Sleep(delay)
|
||||
invokeFunc(fn, args...)
|
||||
}
|
||||
|
||||
// Schedule invoke function every duration time, util close the returned bool chan
|
||||
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
|
||||
// Debounced creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.
|
||||
func Debounced(fn func(), duration time.Duration) func() {
|
||||
// Catch programming error while constructing the closure
|
||||
MustBeFunction(fn)
|
||||
mustBeFunction(fn)
|
||||
|
||||
timer := time.NewTimer(duration)
|
||||
timer.Stop()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-timer.C:
|
||||
go fn()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return func() { timer.Reset(duration) }
|
||||
}
|
||||
|
||||
// Schedule invoke function every duration time, util close the returned bool chan
|
||||
func Schedule(d time.Duration, fn any, args ...any) chan bool {
|
||||
// Catch programming error while constructing the closure
|
||||
mustBeFunction(fn)
|
||||
|
||||
quit := make(chan bool)
|
||||
go func() {
|
||||
for {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||
func invokeFunc(fn any, args ...any) []reflect.Value {
|
||||
fv := functionValue(fn)
|
||||
params := make([]reflect.Value, len(args))
|
||||
for i, item := range args {
|
||||
@@ -14,7 +14,7 @@ func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||
return fv.Call(params)
|
||||
}
|
||||
|
||||
func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||
func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
|
||||
fv := reflect.ValueOf(fn)
|
||||
params := make([]reflect.Value, len(args))
|
||||
for i, item := range args {
|
||||
@@ -23,7 +23,7 @@ func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||
return fv.Call(params)
|
||||
}
|
||||
|
||||
func functionValue(function interface{}) reflect.Value {
|
||||
func functionValue(function any) reflect.Value {
|
||||
v := reflect.ValueOf(function)
|
||||
if v.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
|
||||
@@ -31,7 +31,7 @@ func functionValue(function interface{}) reflect.Value {
|
||||
return v
|
||||
}
|
||||
|
||||
func MustBeFunction(function interface{}) {
|
||||
func mustBeFunction(function any) {
|
||||
v := reflect.ValueOf(function)
|
||||
if v.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestAfter(t *testing.T) {
|
||||
@@ -14,7 +16,7 @@ func TestAfter(t *testing.T) {
|
||||
fmt.Println("print done")
|
||||
return i
|
||||
})
|
||||
type cb func(args ...interface{}) []reflect.Value
|
||||
type cb func(args ...any) []reflect.Value
|
||||
print := func(i int, s string, fn cb) {
|
||||
fmt.Printf("print: arr[%d] is %s \n", i, s)
|
||||
v := fn(i)
|
||||
@@ -32,15 +34,16 @@ func TestAfter(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBefore(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := Before(3, func(i int) int {
|
||||
return i
|
||||
})
|
||||
|
||||
var res []int64
|
||||
type cb func(args ...interface{}) []reflect.Value
|
||||
type cb func(args ...any) []reflect.Value
|
||||
appendStr := func(i int, s string, fn cb) {
|
||||
fmt.Printf("appendStr: arr[%d] is %s \n", i, s)
|
||||
v := fn(i)
|
||||
res = append(res, v[0].Int())
|
||||
}
|
||||
@@ -49,56 +52,74 @@ func TestBefore(t *testing.T) {
|
||||
appendStr(i, arr[i], f)
|
||||
}
|
||||
|
||||
expect := []int64{0, 1, 2, 2, 2}
|
||||
if !reflect.DeepEqual(expect, res) {
|
||||
t.FailNow()
|
||||
}
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
}
|
||||
|
||||
func TestCurry(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCurry")
|
||||
|
||||
add := func(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
var addCurry Fn = func(values ...interface{}) interface{} {
|
||||
var addCurry Fn = func(values ...any) any {
|
||||
return add(values[0].(int), values[1].(int))
|
||||
}
|
||||
|
||||
add1 := addCurry.Curry(1)
|
||||
v := add1(2)
|
||||
if v != 3 {
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal(3, add1(2))
|
||||
}
|
||||
|
||||
func TestCompose(t *testing.T) {
|
||||
toUpper := func(a ...interface{}) interface{} {
|
||||
assert := internal.NewAssert(t, "TestCompose")
|
||||
|
||||
toUpper := func(a ...any) any {
|
||||
return strings.ToUpper(a[0].(string))
|
||||
}
|
||||
toLower := func(a ...interface{}) interface{} {
|
||||
toLower := func(a ...any) any {
|
||||
return strings.ToLower(a[0].(string))
|
||||
}
|
||||
|
||||
expect := toUpper(toLower("aBCde"))
|
||||
expected := toUpper(toLower("aBCde"))
|
||||
cf := Compose(toUpper, toLower)
|
||||
res := cf("aBCde")
|
||||
|
||||
if res != expect {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(expected, res)
|
||||
}
|
||||
|
||||
func TestDelay(t *testing.T) {
|
||||
var print = func(s string) {
|
||||
fmt.Println(s)
|
||||
t.Log(s)
|
||||
}
|
||||
Delay(2*time.Second, print, "test delay")
|
||||
}
|
||||
|
||||
func TestDebounced(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDebounced")
|
||||
|
||||
count := 0
|
||||
add := func() {
|
||||
count++
|
||||
}
|
||||
|
||||
debouncedAdd := Debounced(add, 50*time.Microsecond)
|
||||
debouncedAdd()
|
||||
debouncedAdd()
|
||||
debouncedAdd()
|
||||
debouncedAdd()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
assert.Equal(1, count)
|
||||
|
||||
debouncedAdd()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
assert.Equal(2, count)
|
||||
}
|
||||
|
||||
func TestSchedule(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSchedule")
|
||||
|
||||
var res []string
|
||||
appendStr := func(s string) {
|
||||
fmt.Println(s)
|
||||
res = append(res, s)
|
||||
}
|
||||
|
||||
@@ -106,9 +127,6 @@ func TestSchedule(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
close(stop)
|
||||
|
||||
expect := []string{"*", "*", "*", "*", "*"}
|
||||
if !reflect.DeepEqual(expect, res) {
|
||||
t.FailNow()
|
||||
}
|
||||
fmt.Println("done")
|
||||
expected := []string{"*", "*", "*", "*", "*"}
|
||||
assert.Equal(expected, res)
|
||||
}
|
||||
|
||||
37
function/watcher.go
Normal file
37
function/watcher.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package function
|
||||
|
||||
import "time"
|
||||
|
||||
// Watcher is used for record code excution time
|
||||
type Watcher struct {
|
||||
startTime int64
|
||||
stopTime int64
|
||||
excuting bool
|
||||
}
|
||||
|
||||
// Start the watch timer.
|
||||
func (w *Watcher) Start() {
|
||||
w.startTime = time.Now().UnixNano()
|
||||
w.excuting = true
|
||||
}
|
||||
|
||||
// Stop the watch timer.
|
||||
func (w *Watcher) Stop() {
|
||||
w.stopTime = time.Now().UnixNano()
|
||||
w.excuting = false
|
||||
}
|
||||
|
||||
// GetElapsedTime get excute elapsed time.
|
||||
func (w *Watcher) GetElapsedTime() time.Duration {
|
||||
if w.excuting {
|
||||
return time.Duration(time.Now().UnixNano() - w.startTime)
|
||||
}
|
||||
return time.Duration(w.stopTime - w.startTime)
|
||||
}
|
||||
|
||||
// Reset the watch timer.
|
||||
func (w *Watcher) Reset() {
|
||||
w.startTime = 0
|
||||
w.stopTime = 0
|
||||
w.excuting = false
|
||||
}
|
||||
37
function/watcher_test.go
Normal file
37
function/watcher_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package function
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestWatcher(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWatcher")
|
||||
|
||||
w := &Watcher{}
|
||||
w.Start()
|
||||
|
||||
longRunningTask()
|
||||
|
||||
assert.Equal(true, w.excuting)
|
||||
|
||||
w.Stop()
|
||||
|
||||
eapsedTime := w.GetElapsedTime().Milliseconds()
|
||||
t.Log("Elapsed Time (milsecond)", eapsedTime)
|
||||
|
||||
assert.Equal(false, w.excuting)
|
||||
|
||||
w.Reset()
|
||||
|
||||
assert.Equal(int64(0), w.startTime)
|
||||
assert.Equal(int64(0), w.stopTime)
|
||||
}
|
||||
|
||||
func longRunningTask() {
|
||||
var slice []int64
|
||||
for i := 0; i < 10000000; i++ {
|
||||
slice = append(slice, int64(i))
|
||||
}
|
||||
}
|
||||
4
go.mod
4
go.mod
@@ -1,3 +1,3 @@
|
||||
module github.com/duke-git/lancet
|
||||
module github.com/duke-git/lancet/v2
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
171
internal/assert.go
Normal file
171
internal/assert.go
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package internal is for internal use.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
compareNotEqual int = iota - 2
|
||||
compareLess
|
||||
compareEqual
|
||||
compareGreater
|
||||
)
|
||||
|
||||
// Assert is a simple implementation of assertion, only for internal usage
|
||||
type Assert struct {
|
||||
T *testing.T
|
||||
CaseName string
|
||||
}
|
||||
|
||||
// NewAssert return instance of Assert
|
||||
func NewAssert(t *testing.T, caseName string) *Assert {
|
||||
return &Assert{T: t, CaseName: caseName}
|
||||
}
|
||||
|
||||
// Equal check if expected is equal with actual
|
||||
func (a *Assert) Equal(expected, actual any) {
|
||||
if compare(expected, actual) != compareEqual {
|
||||
makeTestFailed(a.T, a.CaseName, expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// NotEqual check if expected is not equal with actual
|
||||
func (a *Assert) NotEqual(expected, actual any) {
|
||||
if compare(expected, actual) == compareEqual {
|
||||
expectedInfo := fmt.Sprintf("not %v", expected)
|
||||
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// Greater check if expected is greate than actual
|
||||
func (a *Assert) Greater(expected, actual any) {
|
||||
if compare(expected, actual) != compareGreater {
|
||||
expectedInfo := fmt.Sprintf("> %v", expected)
|
||||
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// GreaterOrEqual check if expected is greate than or equal with actual
|
||||
func (a *Assert) GreaterOrEqual(expected, actual any) {
|
||||
isGreatOrEqual := compare(expected, actual) == compareGreater || compare(expected, actual) == compareEqual
|
||||
if !isGreatOrEqual {
|
||||
expectedInfo := fmt.Sprintf(">= %v", expected)
|
||||
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// Less check if expected is less than actual
|
||||
func (a *Assert) Less(expected, actual any) {
|
||||
if compare(expected, actual) != compareLess {
|
||||
expectedInfo := fmt.Sprintf("< %v", expected)
|
||||
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// LessOrEqual check if expected is less than or equal with actual
|
||||
func (a *Assert) LessOrEqual(expected, actual any) {
|
||||
isLessOrEqual := compare(expected, actual) == compareLess || compare(expected, actual) == compareEqual
|
||||
if !isLessOrEqual {
|
||||
expectedInfo := fmt.Sprintf("<= %v", expected)
|
||||
makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil check if value is nil
|
||||
func (a *Assert) IsNil(value any) {
|
||||
if value != nil {
|
||||
makeTestFailed(a.T, a.CaseName, nil, value)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotNil check if value is not nil
|
||||
func (a *Assert) IsNotNil(value any) {
|
||||
if value == nil {
|
||||
makeTestFailed(a.T, a.CaseName, "not nil", value)
|
||||
}
|
||||
}
|
||||
|
||||
// compare x and y return :
|
||||
// x > y -> 1, x < y -> -1, x == y -> 0, x != y -> -2
|
||||
func compare(x, y any) int {
|
||||
vx := reflect.ValueOf(x)
|
||||
vy := reflect.ValueOf(y)
|
||||
|
||||
if vx.Type() != vy.Type() {
|
||||
return compareNotEqual
|
||||
}
|
||||
|
||||
switch vx.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
xInt := vx.Int()
|
||||
yInt := vy.Int()
|
||||
if xInt > yInt {
|
||||
return compareGreater
|
||||
}
|
||||
if xInt == yInt {
|
||||
return compareEqual
|
||||
}
|
||||
if xInt < yInt {
|
||||
return compareLess
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
xUint := vx.Uint()
|
||||
yUint := vy.Uint()
|
||||
if xUint > yUint {
|
||||
return compareGreater
|
||||
}
|
||||
if xUint == yUint {
|
||||
return compareEqual
|
||||
}
|
||||
if xUint < yUint {
|
||||
return compareLess
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
xFloat := vx.Float()
|
||||
yFloat := vy.Float()
|
||||
if xFloat > yFloat {
|
||||
return compareGreater
|
||||
}
|
||||
if xFloat == yFloat {
|
||||
return compareEqual
|
||||
}
|
||||
if xFloat < yFloat {
|
||||
return compareLess
|
||||
}
|
||||
case reflect.String:
|
||||
xString := vx.String()
|
||||
yString := vy.String()
|
||||
if xString > yString {
|
||||
return compareGreater
|
||||
}
|
||||
if xString == yString {
|
||||
return compareEqual
|
||||
}
|
||||
if xString < yString {
|
||||
return compareLess
|
||||
}
|
||||
default:
|
||||
if reflect.DeepEqual(x, y) {
|
||||
return compareEqual
|
||||
}
|
||||
return compareNotEqual
|
||||
}
|
||||
|
||||
return compareNotEqual
|
||||
|
||||
}
|
||||
|
||||
// logFailedInfo make test failed and log error info
|
||||
func makeTestFailed(t *testing.T, caseName string, expected, actual any) {
|
||||
_, file, line, _ := runtime.Caller(2)
|
||||
errInfo := fmt.Sprintf("Case %v failed. file: %v, line: %v, expected: %v, actual: %v.", caseName, file, line, expected, actual)
|
||||
t.Error(errInfo)
|
||||
t.FailNow()
|
||||
}
|
||||
50
internal/assert_test.go
Normal file
50
internal/assert_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAssert(t *testing.T) {
|
||||
assert := NewAssert(t, "TestAssert")
|
||||
assert.Equal(0, 0)
|
||||
assert.NotEqual(1, 0)
|
||||
|
||||
assert.NotEqual("1", 1)
|
||||
var uInt1 uint
|
||||
var uInt2 uint
|
||||
var uInt8 uint8
|
||||
var uInt16 uint16
|
||||
var uInt32 uint32
|
||||
var uInt64 uint64
|
||||
assert.NotEqual(uInt1, uInt8)
|
||||
assert.NotEqual(uInt8, uInt16)
|
||||
assert.NotEqual(uInt16, uInt32)
|
||||
assert.NotEqual(uInt32, uInt64)
|
||||
|
||||
assert.Equal(uInt1, uInt2)
|
||||
|
||||
uInt1 = 1
|
||||
uInt2 = 2
|
||||
assert.Less(uInt1, uInt2)
|
||||
|
||||
assert.Greater(1, 0)
|
||||
assert.GreaterOrEqual(1, 1)
|
||||
assert.Less(0, 1)
|
||||
assert.LessOrEqual(0, 0)
|
||||
|
||||
assert.Equal(0.1, 0.1)
|
||||
assert.Greater(1.1, 0.1)
|
||||
assert.Less(0.1, 1.1)
|
||||
|
||||
assert.Equal("abc", "abc")
|
||||
assert.NotEqual("abc", "abd")
|
||||
assert.Less("abc", "abd")
|
||||
assert.Greater("abd", "abc")
|
||||
|
||||
assert.Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||
assert.NotEqual([]int{1, 2, 3}, []int{1, 2})
|
||||
|
||||
assert.IsNil(nil)
|
||||
assert.IsNotNil("abc")
|
||||
|
||||
}
|
||||
18
lancetconstraints/constraints.go
Normal file
18
lancetconstraints/constraints.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package lancetconstraints contain some comstomer constraints.
|
||||
package lancetconstraints
|
||||
|
||||
// Comparator is for comparing two values
|
||||
type Comparator interface {
|
||||
// Compare v1 and v2
|
||||
// Ascending order: should return 1 -> v1 > v2, 0 -> v1 = v2, -1 -> v1 < v2
|
||||
// Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2
|
||||
Compare(v1, v2 any) int
|
||||
}
|
||||
|
||||
// Number contains all types of number and uintptr, used for generics constraint
|
||||
type Number interface {
|
||||
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64
|
||||
}
|
||||
131
mathutil/mathutil.go
Normal file
131
mathutil/mathutil.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package mathutil implements some functions for math calculation.
|
||||
package mathutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
// Exponent calculate x^n
|
||||
func Exponent(x, n int64) int64 {
|
||||
if n == 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
t := Exponent(x, n/2)
|
||||
|
||||
if n%2 == 1 {
|
||||
return t * t * x
|
||||
}
|
||||
|
||||
return t * t
|
||||
}
|
||||
|
||||
// Fibonacci calculate fibonacci number before n
|
||||
func Fibonacci(first, second, n int) int {
|
||||
if n <= 0 {
|
||||
return 0
|
||||
}
|
||||
if n < 3 {
|
||||
return 1
|
||||
} else if n == 3 {
|
||||
return first + second
|
||||
} else {
|
||||
return Fibonacci(second, first+second, n-1)
|
||||
}
|
||||
}
|
||||
|
||||
// Factorial calculate x!
|
||||
func Factorial(x uint) uint {
|
||||
var f uint = 1
|
||||
for ; x > 1; x-- {
|
||||
f *= x
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// Percent calculate the percentage of val to total
|
||||
func Percent(val, total float64, n int) float64 {
|
||||
if total == 0 {
|
||||
return float64(0)
|
||||
}
|
||||
tmp := val / total * 100
|
||||
res := RoundToFloat(tmp, n)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// RoundToString round up to n decimal places
|
||||
func RoundToString(x float64, n int) string {
|
||||
tmp := math.Pow(10.0, float64(n))
|
||||
x *= tmp
|
||||
x = math.Round(x)
|
||||
res := strconv.FormatFloat(x/tmp, 'f', n, 64)
|
||||
return res
|
||||
}
|
||||
|
||||
// RoundToFloat round up to n decimal places
|
||||
func RoundToFloat(x float64, n int) float64 {
|
||||
tmp := math.Pow(10.0, float64(n))
|
||||
x *= tmp
|
||||
x = math.Round(x)
|
||||
return x / tmp
|
||||
}
|
||||
|
||||
// TruncRound round off n decimal places
|
||||
func TruncRound(x float64, n int) float64 {
|
||||
floatStr := fmt.Sprintf("%."+strconv.Itoa(n+1)+"f", x)
|
||||
temp := strings.Split(floatStr, ".")
|
||||
var newFloat string
|
||||
if len(temp) < 2 || n >= len(temp[1]) {
|
||||
newFloat = floatStr
|
||||
} else {
|
||||
newFloat = temp[0] + "." + temp[1][:n]
|
||||
}
|
||||
res, _ := strconv.ParseFloat(newFloat, 64)
|
||||
return res
|
||||
}
|
||||
|
||||
// Max return max value of params
|
||||
func Max[T lancetconstraints.Number](numbers ...T) T {
|
||||
max := numbers[0]
|
||||
|
||||
for _, v := range numbers {
|
||||
if max < v {
|
||||
max = v
|
||||
}
|
||||
}
|
||||
|
||||
return max
|
||||
}
|
||||
|
||||
// Min return min value of params
|
||||
func Min[T lancetconstraints.Number](numbers ...T) T {
|
||||
min := numbers[0]
|
||||
|
||||
for _, v := range numbers {
|
||||
if min > v {
|
||||
min = v
|
||||
}
|
||||
}
|
||||
|
||||
return min
|
||||
}
|
||||
|
||||
// Average return average value of params
|
||||
func Average[T lancetconstraints.Number](numbers ...T) T {
|
||||
var sum T
|
||||
n := T(len(numbers))
|
||||
|
||||
for _, v := range numbers {
|
||||
sum += v
|
||||
}
|
||||
return sum / n
|
||||
}
|
||||
98
mathutil/mathutil_test.go
Normal file
98
mathutil/mathutil_test.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package mathutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestExponent(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestExponent")
|
||||
|
||||
assert.Equal(int64(1), Exponent(10, 0))
|
||||
assert.Equal(int64(10), Exponent(10, 1))
|
||||
assert.Equal(int64(100), Exponent(10, 2))
|
||||
}
|
||||
|
||||
func TestFibonacci(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFibonacci")
|
||||
|
||||
assert.Equal(0, Fibonacci(1, 1, 0))
|
||||
assert.Equal(1, Fibonacci(1, 1, 1))
|
||||
assert.Equal(1, Fibonacci(1, 1, 2))
|
||||
assert.Equal(5, Fibonacci(1, 1, 5))
|
||||
}
|
||||
|
||||
func TestFactorial(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFactorial")
|
||||
|
||||
assert.Equal(uint(1), Factorial(0))
|
||||
assert.Equal(uint(1), Factorial(1))
|
||||
assert.Equal(uint(2), Factorial(2))
|
||||
assert.Equal(uint(6), Factorial(3))
|
||||
}
|
||||
|
||||
func TestPercent(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestPercent")
|
||||
|
||||
assert.Equal(float64(50), Percent(1, 2, 2))
|
||||
assert.Equal(float64(33.33), Percent(0.1, 0.3, 2))
|
||||
}
|
||||
|
||||
func TestRoundToFloat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRoundToFloat")
|
||||
|
||||
assert.Equal(RoundToFloat(0, 0), float64(0))
|
||||
assert.Equal(RoundToFloat(0, 1), float64(0))
|
||||
assert.Equal(RoundToFloat(0.124, 2), float64(0.12))
|
||||
assert.Equal(RoundToFloat(0.125, 2), float64(0.13))
|
||||
assert.Equal(RoundToFloat(0.125, 3), float64(0.125))
|
||||
assert.Equal(RoundToFloat(33.33333, 2), float64(33.33))
|
||||
}
|
||||
|
||||
func TestRoundToString(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRoundToString")
|
||||
|
||||
assert.Equal(RoundToString(0, 0), "0")
|
||||
assert.Equal(RoundToString(0, 1), "0.0")
|
||||
assert.Equal(RoundToString(0.124, 2), "0.12")
|
||||
assert.Equal(RoundToString(0.125, 2), "0.13")
|
||||
assert.Equal(RoundToString(0.125, 3), "0.125")
|
||||
}
|
||||
|
||||
func TestTruncRound(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestTruncRound")
|
||||
|
||||
assert.Equal(TruncRound(0, 0), float64(0))
|
||||
assert.Equal(TruncRound(0, 1), float64(0))
|
||||
assert.Equal(TruncRound(0.124, 2), float64(0.12))
|
||||
assert.Equal(TruncRound(0.125, 2), float64(0.12))
|
||||
assert.Equal(TruncRound(0.125, 3), float64(0.125))
|
||||
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
|
||||
}
|
||||
|
||||
func TestAverage(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAverage")
|
||||
|
||||
assert.Equal(Average(0, 0), 0)
|
||||
assert.Equal(Average(1, 1), 1)
|
||||
avg := Average(1.2, 1.4)
|
||||
t.Log(avg)
|
||||
assert.Equal(1.3, RoundToFloat(avg, 1))
|
||||
}
|
||||
|
||||
func TestMax(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMax")
|
||||
|
||||
assert.Equal(Max(0, 0), 0)
|
||||
assert.Equal(Max(1, 2, 3), 3)
|
||||
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
|
||||
}
|
||||
|
||||
func TestMin(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMin")
|
||||
|
||||
assert.Equal(Min(0, 0), 0)
|
||||
assert.Equal(Min(1, 2, 3), 1)
|
||||
assert.Equal(Min(1.2, 1.4, 1.1, 1.4), 1.1)
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required.
|
||||
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is:
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]interface{},
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
package netutil
|
||||
@@ -21,32 +21,32 @@ import (
|
||||
)
|
||||
|
||||
//HttpGet send get http request
|
||||
func HttpGet(url string, params ...interface{}) (*http.Response, error) {
|
||||
return request(http.MethodGet, url, params...)
|
||||
func HttpGet(url string, params ...any) (*http.Response, error) {
|
||||
return doHttpRequest(http.MethodGet, url, params...)
|
||||
}
|
||||
|
||||
//HttpPost send post http request
|
||||
func HttpPost(url string, params ...interface{}) (*http.Response, error) {
|
||||
return request(http.MethodPost, url, params...)
|
||||
func HttpPost(url string, params ...any) (*http.Response, error) {
|
||||
return doHttpRequest(http.MethodPost, url, params...)
|
||||
}
|
||||
|
||||
//HttpPut send put http request
|
||||
func HttpPut(url string, params ...interface{}) (*http.Response, error) {
|
||||
return request(http.MethodPut, url, params...)
|
||||
func HttpPut(url string, params ...any) (*http.Response, error) {
|
||||
return doHttpRequest(http.MethodPut, url, params...)
|
||||
}
|
||||
|
||||
//HttpDelete send delete http request
|
||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) {
|
||||
return request(http.MethodDelete, url, params...)
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error) {
|
||||
return doHttpRequest(http.MethodDelete, url, params...)
|
||||
}
|
||||
|
||||
// HttpPatch send patch http request
|
||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) {
|
||||
return request(http.MethodPatch, url, params...)
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error) {
|
||||
return doHttpRequest(http.MethodPatch, url, params...)
|
||||
}
|
||||
|
||||
// ParseHttpResponse decode http response to specified interface
|
||||
func ParseHttpResponse(resp *http.Response, obj interface{}) error {
|
||||
func ParseHttpResponse(resp *http.Response, obj any) error {
|
||||
if resp == nil {
|
||||
return errors.New("InvalidResp")
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func ParseHttpResponse(resp *http.Response, obj interface{}) error {
|
||||
}
|
||||
|
||||
// ConvertMapToQueryString convert map to sorted url query string
|
||||
func ConvertMapToQueryString(param map[string]interface{}) string {
|
||||
func ConvertMapToQueryString(param map[string]any) string {
|
||||
if param == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -2,12 +2,11 @@ package netutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestHttpGet(t *testing.T) {
|
||||
@@ -23,7 +22,7 @@ func TestHttpGet(t *testing.T) {
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestHttpPost(t *testing.T) {
|
||||
@@ -44,7 +43,7 @@ func TestHttpPost(t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestHttpPut(t *testing.T) {
|
||||
@@ -66,7 +65,7 @@ func TestHttpPut(t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestHttpPatch(t *testing.T) {
|
||||
@@ -88,7 +87,7 @@ func TestHttpPatch(t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestHttpDelete(t *testing.T) {
|
||||
@@ -99,22 +98,18 @@ func TestHttpDelete(t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestConvertMapToQueryString(t *testing.T) {
|
||||
var m = map[string]interface{}{
|
||||
assert := internal.NewAssert(t, "TestConvertMapToQueryString")
|
||||
|
||||
var m = map[string]any{
|
||||
"c": 3,
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
|
||||
expected := "a=1&b=2&c=3"
|
||||
r := ConvertMapToQueryString(m)
|
||||
if r != expected {
|
||||
utils.LogFailedTestInfo(t, "ConvertMapToQueryString", m, expected, r)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.Equal("a=1&b=2&c=3", ConvertMapToQueryString(m))
|
||||
}
|
||||
|
||||
func TestParseResponse(t *testing.T) {
|
||||
@@ -142,5 +137,5 @@ func TestParseResponse(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
fmt.Println("response: ", toDoResp)
|
||||
t.Log("response: ", toDoResp)
|
||||
}
|
||||
@@ -47,6 +47,46 @@ func GetPublicIpInfo() (*PublicIpInfo, error) {
|
||||
return &ip, nil
|
||||
}
|
||||
|
||||
// GetIps return all ipv4 of system
|
||||
func GetIps() []string {
|
||||
var ips []string
|
||||
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return ips
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
ipNet, isValid := addr.(*net.IPNet)
|
||||
if isValid && !ipNet.IP.IsLoopback() {
|
||||
if ipNet.IP.To4() != nil {
|
||||
ips = append(ips, ipNet.IP.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
// GetMacAddrs get mac address
|
||||
func GetMacAddrs() []string {
|
||||
var macAddrs []string
|
||||
|
||||
nets, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return macAddrs
|
||||
}
|
||||
|
||||
for _, net := range nets {
|
||||
macAddr := net.HardwareAddr.String()
|
||||
if len(macAddr) == 0 {
|
||||
continue
|
||||
}
|
||||
macAddrs = append(macAddrs, macAddr)
|
||||
}
|
||||
|
||||
return macAddrs
|
||||
}
|
||||
|
||||
// PublicIpInfo public ip info: country, region, isp, city, lat, lon, ip
|
||||
type PublicIpInfo struct {
|
||||
Status string `json:"status"`
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func request(method, reqUrl string, params ...interface{}) (*http.Response, error) {
|
||||
func doHttpRequest(method, reqUrl string, params ...any) (*http.Response, error) {
|
||||
if len(reqUrl) == 0 {
|
||||
return nil, errors.New("url should be specified")
|
||||
}
|
||||
@@ -24,53 +24,29 @@ func request(method, reqUrl string, params ...interface{}) (*http.Response, erro
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
err := setUrl(req, reqUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch len(params) {
|
||||
case 0:
|
||||
err := setUrl(req, reqUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 1:
|
||||
err := setUrl(req, reqUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setHeader(req, params[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 2:
|
||||
err := setHeader(req, params[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setQueryParam(req, reqUrl, params[1])
|
||||
err := setHeaderAndQueryParam(req, reqUrl, params[0], params[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 3:
|
||||
err := setHeader(req, params[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setQueryParam(req, reqUrl, params[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setBodyByte(req, params[2])
|
||||
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 4:
|
||||
err := setHeader(req, params[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setQueryParam(req, reqUrl, params[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setBodyByte(req, params[2])
|
||||
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -78,14 +54,41 @@ func request(method, reqUrl string, params ...interface{}) (*http.Response, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resp, e := client.Do(req)
|
||||
return resp, e
|
||||
}
|
||||
|
||||
func setHeader(req *http.Request, header interface{}) error {
|
||||
func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam any) error {
|
||||
err := setHeader(req, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = setQueryParam(req, reqUrl, queryParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body any) error {
|
||||
err := setHeader(req, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = setQueryParam(req, reqUrl, queryParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = setBodyByte(req, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setHeader(req *http.Request, header any) error {
|
||||
if header != nil {
|
||||
switch v := header.(type) {
|
||||
case map[string]string:
|
||||
@@ -109,6 +112,7 @@ func setHeader(req *http.Request, header interface{}) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setUrl(req *http.Request, reqUrl string) error {
|
||||
u, err := url.Parse(reqUrl)
|
||||
if err != nil {
|
||||
@@ -117,11 +121,12 @@ func setUrl(req *http.Request, reqUrl string) error {
|
||||
req.URL = u
|
||||
return nil
|
||||
}
|
||||
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
|
||||
|
||||
func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
|
||||
var values url.Values
|
||||
if queryParam != nil {
|
||||
switch v := queryParam.(type) {
|
||||
case map[string]interface{}:
|
||||
case map[string]any:
|
||||
values = url.Values{}
|
||||
for k := range v {
|
||||
values.Set(k, fmt.Sprintf("%v", v[k]))
|
||||
@@ -129,7 +134,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
|
||||
case url.Values:
|
||||
values = v
|
||||
default:
|
||||
return errors.New("query params type should be url.Values or map[string]interface{}")
|
||||
return errors.New("query params type should be url.Values or map[string]any")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,23 +155,20 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func setBodyByte(req *http.Request, body interface{}) error {
|
||||
func setBodyByte(req *http.Request, body any) error {
|
||||
if body != nil {
|
||||
var bodyByte []byte
|
||||
if body != nil {
|
||||
switch v := body.(type) {
|
||||
case []byte:
|
||||
bodyByte = v
|
||||
default:
|
||||
return errors.New("body type should be []byte")
|
||||
}
|
||||
switch b := body.(type) {
|
||||
case []byte:
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
req.ContentLength = int64(len(b))
|
||||
default:
|
||||
return errors.New("body type should be []byte")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(bodyByte))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getClient(client interface{}) (*http.Client, error) {
|
||||
func getClient(client any) (*http.Client, error) {
|
||||
c := http.Client{}
|
||||
if client != nil {
|
||||
switch v := client.(type) {
|
||||
@@ -1,31 +1,32 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/utils"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestGetInternalIp(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetInternalIp")
|
||||
|
||||
internalIp := GetInternalIp()
|
||||
ip := net.ParseIP(internalIp)
|
||||
if ip == nil {
|
||||
utils.LogFailedTestInfo(t, "GetInternalIp", "GetInternalIp", "", ip)
|
||||
t.FailNow()
|
||||
}
|
||||
assert.IsNotNil(ip)
|
||||
}
|
||||
|
||||
func TestGetPublicIpInfo(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
||||
|
||||
publicIpInfo, err := GetPublicIpInfo()
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
fmt.Printf("public ip info is: %+v \n", *publicIpInfo)
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Logf("public ip info is: %+v \n", *publicIpInfo)
|
||||
}
|
||||
|
||||
func TestIsPublicIP(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsPublicIP")
|
||||
|
||||
ips := []net.IP{
|
||||
net.ParseIP("127.0.0.1"),
|
||||
net.ParseIP("192.168.0.1"),
|
||||
@@ -37,11 +38,17 @@ func TestIsPublicIP(t *testing.T) {
|
||||
expected := []bool{false, false, false, false, true}
|
||||
|
||||
for i := 0; i < len(ips); i++ {
|
||||
res := IsPublicIP(ips[i])
|
||||
|
||||
if res != expected[i] {
|
||||
utils.LogFailedTestInfo(t, "IsPublicIP", ips[i], expected[i], res)
|
||||
t.FailNow()
|
||||
}
|
||||
actual := IsPublicIP(ips[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIps(t *testing.T) {
|
||||
ips := GetIps()
|
||||
t.Log(ips)
|
||||
}
|
||||
|
||||
func TestGetMacAddrs(t *testing.T) {
|
||||
macAddrs := GetMacAddrs()
|
||||
t.Log(macAddrs)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user