mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-15 10:12:29 +08:00
Compare commits
4 Commits
4c5524354c
...
bc3c080ac3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc3c080ac3 | ||
|
|
d3fab15af3 | ||
|
|
6e3e411d46 | ||
|
|
f976941e36 |
681
docs/netutil.md
681
docs/netutil.md
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -56,8 +56,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randBytes := random.RandBytes(4)
|
||||
fmt.Println(randBytes)
|
||||
randBytes := random.RandBytes(4)
|
||||
fmt.Println(randBytes)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -82,8 +82,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
rInt := random.RandInt(1, 10)
|
||||
fmt.Println(rInt)
|
||||
rInt := random.RandInt(1, 10)
|
||||
fmt.Println(rInt)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -108,8 +108,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //pGWsze
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //pGWsze
|
||||
}
|
||||
```
|
||||
|
||||
@@ -134,8 +134,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //PACWGF
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //PACWGF
|
||||
}
|
||||
```
|
||||
|
||||
@@ -160,8 +160,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandLower(6)
|
||||
fmt.Println(randStr) //siqbew
|
||||
randStr := random.RandLower(6)
|
||||
fmt.Println(randStr) //siqbew
|
||||
}
|
||||
```
|
||||
|
||||
@@ -186,8 +186,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandNumeral(6)
|
||||
fmt.Println(randStr) //035172
|
||||
randStr := random.RandNumeral(6)
|
||||
fmt.Println(randStr) //035172
|
||||
}
|
||||
```
|
||||
|
||||
@@ -212,8 +212,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandNumeralOrLetter(6)
|
||||
fmt.Println(randStr) //0aW7cQ
|
||||
randStr := random.RandNumeralOrLetter(6)
|
||||
fmt.Println(randStr) //0aW7cQ
|
||||
}
|
||||
```
|
||||
|
||||
@@ -238,10 +238,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
uuid, err := random.UUIdV4()
|
||||
uuid, err := random.UUIdV4()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(uuid)
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -56,8 +56,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randBytes := random.RandBytes(4)
|
||||
fmt.Println(randBytes)
|
||||
randBytes := random.RandBytes(4)
|
||||
fmt.Println(randBytes)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -82,8 +82,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
rInt := random.RandInt(1, 10)
|
||||
fmt.Println(rInt)
|
||||
rInt := random.RandInt(1, 10)
|
||||
fmt.Println(rInt)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -108,8 +108,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //pGWsze
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //pGWsze
|
||||
}
|
||||
```
|
||||
|
||||
@@ -134,8 +134,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //PACWGF
|
||||
randStr := random.RandString(6)
|
||||
fmt.Println(randStr) //PACWGF
|
||||
}
|
||||
```
|
||||
|
||||
@@ -160,8 +160,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandLower(6)
|
||||
fmt.Println(randStr) //siqbew
|
||||
randStr := random.RandLower(6)
|
||||
fmt.Println(randStr) //siqbew
|
||||
}
|
||||
```
|
||||
|
||||
@@ -186,8 +186,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandNumeral(6)
|
||||
fmt.Println(randStr) //035172
|
||||
randStr := random.RandNumeral(6)
|
||||
fmt.Println(randStr) //035172
|
||||
}
|
||||
```
|
||||
|
||||
@@ -212,8 +212,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandNumeralOrLetter(6)
|
||||
fmt.Println(randStr) //0aW7cQ
|
||||
randStr := random.RandNumeralOrLetter(6)
|
||||
fmt.Println(randStr) //0aW7cQ
|
||||
}
|
||||
```
|
||||
|
||||
@@ -238,10 +238,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
uuid, err := random.UUIdV4()
|
||||
uuid, err := random.UUIdV4()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(uuid)
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
192
docs/retry.md
192
docs/retry.md
@@ -1,16 +1,17 @@
|
||||
# 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)
|
||||
|
||||
- [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"
|
||||
@@ -20,18 +21,19 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Context](#Context)
|
||||
- [Retry](#Retry)
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
|
||||
- [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>
|
||||
@@ -39,43 +41,46 @@ import (
|
||||
```go
|
||||
func Context(ctx context.Context)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
"time"
|
||||
"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")
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
|
||||
err := retry.Retry(increaseNumber,
|
||||
retry.RetryDuration(time.Microsecond*50),
|
||||
retry.Context(ctx),
|
||||
)
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number > 3 {
|
||||
cancel()
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err) //retry is cancelled
|
||||
}
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
retry.Retry(increaseNumber,
|
||||
duration,
|
||||
retry.Context(ctx),
|
||||
)
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RetryFunc">RetryFunc</span>
|
||||
|
||||
<p>Function that retry executes.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -83,6 +88,7 @@ func main() {
|
||||
```go
|
||||
type RetryFunc func() error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -96,28 +102,31 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
number := 0
|
||||
var increaseNumber retry.RetryFunc = func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryTimes">RetryTimes</span>
|
||||
|
||||
<p>Set times of retry. Default times is 5.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -125,6 +134,7 @@ func main() {
|
||||
```go
|
||||
func RetryTimes(n uint)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -138,26 +148,28 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
number := 0
|
||||
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
|
||||
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
|
||||
}
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// function main.main.func1 run failed after 2 times retry
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryDuration">RetryDuration</span>
|
||||
|
||||
<p>Set duration of retries. Default duration is 3 second.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -165,6 +177,7 @@ func main() {
|
||||
```go
|
||||
func RetryDuration(d time.Duration)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -178,26 +191,31 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Retry">Retry</span>
|
||||
|
||||
<p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -205,6 +223,7 @@ func main() {
|
||||
```go
|
||||
func Retry(retryFunc RetryFunc, opts ...Option) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -218,20 +237,25 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# Retry
|
||||
retry重试执行函数直到函数运行成功或被context cancel。
|
||||
|
||||
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)
|
||||
|
||||
- [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"
|
||||
@@ -20,20 +21,19 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Context](#Context)
|
||||
- [Retry](#Retry)
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
|
||||
- [Context](#Context)
|
||||
- [Retry](#Retry)
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
|
||||
## Document文档
|
||||
|
||||
## Document 文档
|
||||
|
||||
### <span id="Context">Context</span>
|
||||
|
||||
<p>设置重试context参数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -41,43 +41,46 @@ import (
|
||||
```go
|
||||
func Context(ctx context.Context)
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"lancet-demo/retry"
|
||||
"time"
|
||||
"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")
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
|
||||
err := retry.Retry(increaseNumber,
|
||||
retry.RetryDuration(time.Microsecond*50),
|
||||
retry.Context(ctx),
|
||||
)
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number > 3 {
|
||||
cancel()
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err) //retry is cancelled
|
||||
}
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
retry.Retry(increaseNumber,
|
||||
duration,
|
||||
retry.Context(ctx),
|
||||
)
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RetryFunc">RetryFunc</span>
|
||||
|
||||
<p>被重试执行的函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -85,6 +88,7 @@ func main() {
|
||||
```go
|
||||
type RetryFunc func() error
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -98,27 +102,31 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
number := 0
|
||||
var increaseNumber retry.RetryFunc = func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryTimes">RetryTimes</span>
|
||||
|
||||
<p>设置重试次数,默认5</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -126,6 +134,7 @@ func main() {
|
||||
```go
|
||||
func RetryTimes(n uint)
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -139,25 +148,28 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
number := 0
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
|
||||
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
|
||||
}
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// function main.main.func1 run failed after 2 times retry
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="RetryDuration">RetryDuration</span>
|
||||
|
||||
<p>设置重试间隔时间,默认3秒</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -165,6 +177,7 @@ func main() {
|
||||
```go
|
||||
func RetryDuration(d time.Duration)
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -178,26 +191,31 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Retry">Retry</span>
|
||||
|
||||
<p>重试执行函数retryFunc,直到函数运行成功,或被context停止</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -205,6 +223,7 @@ func main() {
|
||||
```go
|
||||
func Retry(retryFunc RetryFunc, opts ...Option) error
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -218,20 +237,25 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number) //3
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
1049
docs/slice.md
1049
docs/slice.md
File diff suppressed because it is too large
Load Diff
1057
docs/slice_zh-CN.md
1057
docs/slice_zh-CN.md
File diff suppressed because it is too large
Load Diff
726
docs/strutil.md
726
docs/strutil.md
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
205
docs/system.md
205
docs/system.md
@@ -1,16 +1,17 @@
|
||||
# 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)
|
||||
|
||||
- [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"
|
||||
@@ -20,23 +21,23 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [IsWindows](#IsWindows)
|
||||
- [IsLinux](#IsLinux)
|
||||
- [IsMac](#IsMac)
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
|
||||
- [IsWindows](#IsWindows)
|
||||
- [IsLinux](#IsLinux)
|
||||
- [IsMac](#IsMac)
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="IsWindows">IsWindows</span>
|
||||
|
||||
<p>Check if current os is windows.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -44,24 +45,23 @@ import (
|
||||
```go
|
||||
func IsWindows() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsWindows := system.IsWindows()
|
||||
fmt.Println(isOsWindows)
|
||||
isOsWindows := system.IsWindows()
|
||||
fmt.Println(isOsWindows)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsLinux">IsLinux</span>
|
||||
|
||||
<p>Check if current os is linux.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -69,23 +69,23 @@ func main() {
|
||||
```go
|
||||
func IsLinux() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsLinux := system.IsLinux()
|
||||
fmt.Println(isOsLinux)
|
||||
isOsLinux := system.IsLinux()
|
||||
fmt.Println(isOsLinux)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsMac">IsMac</span>
|
||||
|
||||
<p>Check if current os is macos.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -93,23 +93,23 @@ func main() {
|
||||
```go
|
||||
func IsMac() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsMac := system.IsMac()
|
||||
fmt.Println(isOsMac)
|
||||
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>
|
||||
@@ -117,23 +117,29 @@ func main() {
|
||||
```go
|
||||
func GetOsEnv(key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fooEnv := system.GetOsEnv("foo")
|
||||
fmt.Println(fooEnv)
|
||||
err := system.SetOsEnv("foo", "abc")
|
||||
result := system.GetOsEnv("foo")
|
||||
|
||||
fmt.Println(err)
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// <nil>
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SetOsEnv">SetOsEnv</span>
|
||||
|
||||
<p>Sets the value of the environment variable named by the key.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -141,24 +147,29 @@ func main() {
|
||||
```go
|
||||
func SetOsEnv(key, value string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.SetOsEnv("foo", "foo_value")
|
||||
fmt.Println(err)
|
||||
err := system.SetOsEnv("foo", "abc")
|
||||
result := system.GetOsEnv("foo")
|
||||
|
||||
fmt.Println(err)
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// <nil>
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RemoveOsEnv">RemoveOsEnv</span>
|
||||
|
||||
<p>Remove a single environment variable.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -166,25 +177,37 @@ func main() {
|
||||
```go
|
||||
func RemoveOsEnv(key string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.RemoveOsEnv("foo")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
err1 := system.SetOsEnv("foo", "abc")
|
||||
result1 := GetOsEnv("foo")
|
||||
|
||||
err2 := system.RemoveOsEnv("foo")
|
||||
result2 := GetOsEnv("foo")
|
||||
|
||||
fmt.Println(err1)
|
||||
fmt.Println(err2)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// <nil>
|
||||
// abc
|
||||
//
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CompareOsEnv">CompareOsEnv</span>
|
||||
|
||||
<p>Get env named by the key and compare it with comparedEnv.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -192,25 +215,32 @@ func main() {
|
||||
```go
|
||||
func CompareOsEnv(key, comparedEnv string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"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
|
||||
err := system.SetOsEnv("foo", "abc")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result := system.CompareOsEnv("foo", "abc")
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ExecCommand">CompareOsEnv</span>
|
||||
|
||||
<p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -218,40 +248,39 @@ func main() {
|
||||
```go
|
||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// linux or mac
|
||||
stdout, stderr, err := system.ExecCommand("ls")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
// linux or mac
|
||||
stdout, stderr, err := system.ExecCommand("ls")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
|
||||
// windows
|
||||
stdout, stderr, err = system.ExecCommand("dir")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
// windows
|
||||
stdout, stderr, err = system.ExecCommand("dir")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
|
||||
// error command
|
||||
stdout, stderr, err = system.ExecCommand("abc")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
// error command
|
||||
stdout, stderr, err = system.ExecCommand("abc")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
|
||||
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -259,19 +288,17 @@ func main() {
|
||||
```go
|
||||
func GetOsBits() int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit)
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit) // 32 or 64
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# System
|
||||
system包含os, runtime, shell command相关函数。
|
||||
|
||||
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)
|
||||
|
||||
- [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"
|
||||
@@ -20,23 +21,23 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [IsWindows](#IsWindows)
|
||||
- [IsLinux](#IsLinux)
|
||||
- [IsMac](#IsMac)
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
|
||||
- [IsWindows](#IsWindows)
|
||||
- [IsLinux](#IsLinux)
|
||||
- [IsMac](#IsMac)
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation文档
|
||||
|
||||
## Documentation 文档
|
||||
|
||||
### <span id="IsWindows">IsWindows</span>
|
||||
|
||||
<p>检查当前操作系统是否是windows</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -44,24 +45,23 @@ import (
|
||||
```go
|
||||
func IsWindows() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsWindows := system.IsWindows()
|
||||
fmt.Println(isOsWindows)
|
||||
isOsWindows := system.IsWindows()
|
||||
fmt.Println(isOsWindows)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsLinux">IsLinux</span>
|
||||
|
||||
<p>检查当前操作系统是否是linux</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -69,23 +69,23 @@ func main() {
|
||||
```go
|
||||
func IsLinux() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsLinux := system.IsLinux()
|
||||
fmt.Println(isOsLinux)
|
||||
isOsLinux := system.IsLinux()
|
||||
fmt.Println(isOsLinux)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsMac">IsMac</span>
|
||||
|
||||
<p>检查当前操作系统是否是macos</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -93,23 +93,23 @@ func main() {
|
||||
```go
|
||||
func IsMac() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isOsMac := system.IsMac()
|
||||
fmt.Println(isOsMac)
|
||||
isOsMac := system.IsMac()
|
||||
fmt.Println(isOsMac)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsEnv">GetOsEnv</span>
|
||||
|
||||
<p>获取key命名的环境变量的值</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -117,23 +117,29 @@ func main() {
|
||||
```go
|
||||
func GetOsEnv(key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fooEnv := system.GetOsEnv("foo")
|
||||
fmt.Println(fooEnv)
|
||||
err := system.SetOsEnv("foo", "abc")
|
||||
result := system.GetOsEnv("foo")
|
||||
|
||||
fmt.Println(err)
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// <nil>
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SetOsEnv">SetOsEnv</span>
|
||||
|
||||
<p>设置由key命名的环境变量的值</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -141,24 +147,29 @@ func main() {
|
||||
```go
|
||||
func SetOsEnv(key, value string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.SetOsEnv("foo", "foo_value")
|
||||
fmt.Println(err)
|
||||
err := system.SetOsEnv("foo", "abc")
|
||||
result := system.GetOsEnv("foo")
|
||||
|
||||
fmt.Println(err)
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// <nil>
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="RemoveOsEnv">RemoveOsEnv</span>
|
||||
|
||||
<p>删除单个环境变量</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -166,25 +177,37 @@ func main() {
|
||||
```go
|
||||
func RemoveOsEnv(key string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := system.RemoveOsEnv("foo")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
err1 := system.SetOsEnv("foo", "abc")
|
||||
result1 := GetOsEnv("foo")
|
||||
|
||||
err2 := system.RemoveOsEnv("foo")
|
||||
result2 := GetOsEnv("foo")
|
||||
|
||||
fmt.Println(err1)
|
||||
fmt.Println(err2)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// <nil>
|
||||
// abc
|
||||
//
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CompareOsEnv">CompareOsEnv</span>
|
||||
|
||||
<p>获取key命名的环境变量值并与compareEnv进行比较</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -192,25 +215,32 @@ func main() {
|
||||
```go
|
||||
func CompareOsEnv(key, comparedEnv string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"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
|
||||
err := system.SetOsEnv("foo", "abc")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result := system.CompareOsEnv("foo", "abc")
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ExecCommand">ExecCommand</span>
|
||||
|
||||
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-a(linux),dir(windows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -218,40 +248,39 @@ func main() {
|
||||
```go
|
||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// linux or mac
|
||||
stdout, stderr, err := system.ExecCommand("ls")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
// linux or mac
|
||||
stdout, stderr, err := system.ExecCommand("ls")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
|
||||
// windows
|
||||
stdout, stderr, err = system.ExecCommand("dir")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
// windows
|
||||
stdout, stderr, err = system.ExecCommand("dir")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
|
||||
// error command
|
||||
stdout, stderr, err = system.ExecCommand("abc")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
// error command
|
||||
stdout, stderr, err = system.ExecCommand("abc")
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
|
||||
<p>获取当前操作系统位数,返回32或64</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -259,23 +288,17 @@ func main() {
|
||||
```go
|
||||
func GetOsBits() int
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit)
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit) // 32 or 64
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,17 @@
|
||||
# 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)
|
||||
- [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"
|
||||
@@ -19,15 +21,15 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
- [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>
|
||||
@@ -35,6 +37,7 @@ import (
|
||||
```go
|
||||
func Unwrap[T any](val T, err error) T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -46,20 +49,20 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := xerror.Unwrap(strconv.Atoi("42"))
|
||||
fmt.Println(result1)
|
||||
result1 := xerror.Unwrap(strconv.Atoi("42"))
|
||||
fmt.Println(result1)
|
||||
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
|
||||
fmt.Println(result2)
|
||||
}()
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
|
||||
fmt.Println(result2)
|
||||
}()
|
||||
|
||||
xerror.Unwrap(strconv.Atoi("4o2"))
|
||||
xerror.Unwrap(strconv.Atoi("4o2"))
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
// true
|
||||
// Output:
|
||||
// 42
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
# Xerror
|
||||
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)
|
||||
- [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"
|
||||
@@ -19,15 +21,15 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
- [Unwrap](#Unwrap)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
|
||||
<p>检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则Unwrap使用err发生panic。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -35,6 +37,7 @@ import (
|
||||
```go
|
||||
func Unwrap[T any](val T, err error) T
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -46,20 +49,20 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := xerror.Unwrap(strconv.Atoi("42"))
|
||||
fmt.Println(result1)
|
||||
result1 := xerror.Unwrap(strconv.Atoi("42"))
|
||||
fmt.Println(result1)
|
||||
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
|
||||
fmt.Println(result2)
|
||||
}()
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
|
||||
fmt.Println(result2)
|
||||
}()
|
||||
|
||||
xerror.Unwrap(strconv.Atoi("4o2"))
|
||||
xerror.Unwrap(strconv.Atoi("4o2"))
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
// true
|
||||
// Output:
|
||||
// 42
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
226
netutil/http.go
226
netutil/http.go
@@ -13,12 +13,21 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
// HttpGet send get http request.
|
||||
@@ -78,3 +87,220 @@ func ConvertMapToQueryString(param map[string]any) string {
|
||||
}
|
||||
return build.String()
|
||||
}
|
||||
|
||||
// HttpRequest struct is a composed http request
|
||||
type HttpRequest struct {
|
||||
RawURL string
|
||||
Method string
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
Body []byte
|
||||
}
|
||||
|
||||
// HttpClientConfig contains some configurations for http client
|
||||
type HttpClientConfig struct {
|
||||
SSLEnabled bool
|
||||
TLSConfig *tls.Config
|
||||
Compressed bool
|
||||
HandshakeTimeout time.Duration
|
||||
ResponseTimeout time.Duration
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
// defaultHttpClientConfig defalut client config
|
||||
var defaultHttpClientConfig = &HttpClientConfig{
|
||||
Compressed: false,
|
||||
HandshakeTimeout: 20 * time.Second,
|
||||
ResponseTimeout: 40 * time.Second,
|
||||
}
|
||||
|
||||
// HttpClient is used for sending http request
|
||||
type HttpClient struct {
|
||||
*http.Client
|
||||
TLS *tls.Config
|
||||
Request *http.Request
|
||||
Config HttpClientConfig
|
||||
}
|
||||
|
||||
// NewHttpClient make a HttpClient instance
|
||||
func NewHttpClient() *HttpClient {
|
||||
client := &HttpClient{
|
||||
Client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
||||
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
||||
DisableCompression: !defaultHttpClientConfig.Compressed,
|
||||
},
|
||||
},
|
||||
Config: *defaultHttpClientConfig,
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// NewHttpClientWithConfig make a HttpClient instance with pass config
|
||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
||||
if config == nil {
|
||||
config = defaultHttpClientConfig
|
||||
}
|
||||
|
||||
client := &HttpClient{
|
||||
Client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: config.HandshakeTimeout,
|
||||
ResponseHeaderTimeout: config.ResponseTimeout,
|
||||
DisableCompression: !config.Compressed,
|
||||
},
|
||||
},
|
||||
Config: *config,
|
||||
}
|
||||
|
||||
if config.SSLEnabled {
|
||||
client.TLS = config.TLSConfig
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// SendRequest send http request.
|
||||
// Play: https://go.dev/play/p/jUSgynekH7G
|
||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
|
||||
err := validateRequest(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawUrl := request.RawURL
|
||||
|
||||
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.setTLS(rawUrl)
|
||||
client.setHeader(req, request.Headers)
|
||||
|
||||
err = client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.FormData != nil {
|
||||
client.setFormData(req, request.FormData)
|
||||
}
|
||||
|
||||
client.Request = req
|
||||
|
||||
resp, err := client.Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DecodeResponse decode response into target object.
|
||||
// Play: https://go.dev/play/p/jUSgynekH7G
|
||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error {
|
||||
if resp == nil {
|
||||
return errors.New("invalid target param")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return json.NewDecoder(resp.Body).Decode(target)
|
||||
}
|
||||
|
||||
// setTLS set http client transport TLSClientConfig
|
||||
func (client *HttpClient) setTLS(rawUrl string) {
|
||||
if strings.HasPrefix(rawUrl, "https") {
|
||||
if transport, ok := client.Client.Transport.(*http.Transport); ok {
|
||||
transport.TLSClientConfig = client.TLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setHeader set http rquest header
|
||||
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
||||
if headers == nil {
|
||||
headers = make(http.Header)
|
||||
}
|
||||
|
||||
if _, ok := headers["Accept"]; !ok {
|
||||
headers["Accept"] = []string{"*/*"}
|
||||
}
|
||||
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
|
||||
headers["Accept-Encoding"] = []string{"deflate, gzip"}
|
||||
}
|
||||
|
||||
req.Header = headers
|
||||
}
|
||||
|
||||
// setQueryParam set http request query string param
|
||||
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
|
||||
if queryParam != nil {
|
||||
if !strings.Contains(reqUrl, "?") {
|
||||
reqUrl = reqUrl + "?" + queryParam.Encode()
|
||||
} else {
|
||||
reqUrl = reqUrl + "&" + queryParam.Encode()
|
||||
}
|
||||
u, err := url.Parse(reqUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.URL = u
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
||||
formData := []byte(values.Encode())
|
||||
req.Body = io.NopCloser(bytes.NewReader(formData))
|
||||
req.ContentLength = int64(len(formData))
|
||||
}
|
||||
|
||||
// validateRequest check if a request has url, and valid method.
|
||||
func validateRequest(req *HttpRequest) error {
|
||||
if req.RawURL == "" {
|
||||
return errors.New("invalid request url")
|
||||
}
|
||||
|
||||
// common HTTP methods
|
||||
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
|
||||
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
|
||||
|
||||
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
|
||||
return errors.New("invalid request method")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StructToUrlValues convert struct to url valuse,
|
||||
// only convert the field which is exported and has `json` tag.
|
||||
// Play: https://go.dev/play/p/pFqMkM40w9z
|
||||
func StructToUrlValues(targetStruct any) url.Values {
|
||||
rv := reflect.ValueOf(targetStruct)
|
||||
rt := reflect.TypeOf(targetStruct)
|
||||
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
if rt.Kind() != reflect.Struct {
|
||||
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
|
||||
}
|
||||
|
||||
result := url.Values{}
|
||||
|
||||
fieldNum := rt.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
regex := regexp.MustCompile(pattern)
|
||||
for i := 0; i < fieldNum; i++ {
|
||||
name := rt.Field(i).Name
|
||||
tag := rt.Field(i).Tag.Get("json")
|
||||
if regex.MatchString(name) && tag != "" {
|
||||
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
// HttpRequest struct is a composed http request
|
||||
type HttpRequest struct {
|
||||
RawURL string
|
||||
Method string
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
Body []byte
|
||||
}
|
||||
|
||||
// HttpClientConfig contains some configurations for http client
|
||||
type HttpClientConfig struct {
|
||||
SSLEnabled bool
|
||||
TLSConfig *tls.Config
|
||||
Compressed bool
|
||||
HandshakeTimeout time.Duration
|
||||
ResponseTimeout time.Duration
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
// defaultHttpClientConfig defalut client config
|
||||
var defaultHttpClientConfig = &HttpClientConfig{
|
||||
Compressed: false,
|
||||
HandshakeTimeout: 20 * time.Second,
|
||||
ResponseTimeout: 40 * time.Second,
|
||||
}
|
||||
|
||||
// HttpClient is used for sending http request
|
||||
type HttpClient struct {
|
||||
*http.Client
|
||||
TLS *tls.Config
|
||||
Request *http.Request
|
||||
Config HttpClientConfig
|
||||
}
|
||||
|
||||
// NewHttpClient make a HttpClient instance
|
||||
func NewHttpClient() *HttpClient {
|
||||
client := &HttpClient{
|
||||
Client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
||||
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
||||
DisableCompression: !defaultHttpClientConfig.Compressed,
|
||||
},
|
||||
},
|
||||
Config: *defaultHttpClientConfig,
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// NewHttpClientWithConfig make a HttpClient instance with pass config
|
||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
||||
if config == nil {
|
||||
config = defaultHttpClientConfig
|
||||
}
|
||||
|
||||
client := &HttpClient{
|
||||
Client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: config.HandshakeTimeout,
|
||||
ResponseHeaderTimeout: config.ResponseTimeout,
|
||||
DisableCompression: !config.Compressed,
|
||||
},
|
||||
},
|
||||
Config: *config,
|
||||
}
|
||||
|
||||
if config.SSLEnabled {
|
||||
client.TLS = config.TLSConfig
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// SendRequest send http request.
|
||||
// Play: https://go.dev/play/p/jUSgynekH7G
|
||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
|
||||
err := validateRequest(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawUrl := request.RawURL
|
||||
|
||||
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.setTLS(rawUrl)
|
||||
client.setHeader(req, request.Headers)
|
||||
|
||||
err = client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.FormData != nil {
|
||||
client.setFormData(req, request.FormData)
|
||||
}
|
||||
|
||||
client.Request = req
|
||||
|
||||
resp, err := client.Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DecodeResponse decode response into target object.
|
||||
// Play: https://go.dev/play/p/jUSgynekH7G
|
||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error {
|
||||
if resp == nil {
|
||||
return errors.New("invalid target param")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return json.NewDecoder(resp.Body).Decode(target)
|
||||
}
|
||||
|
||||
// setTLS set http client transport TLSClientConfig
|
||||
func (client *HttpClient) setTLS(rawUrl string) {
|
||||
if strings.HasPrefix(rawUrl, "https") {
|
||||
if transport, ok := client.Client.Transport.(*http.Transport); ok {
|
||||
transport.TLSClientConfig = client.TLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setHeader set http rquest header
|
||||
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
||||
if headers == nil {
|
||||
headers = make(http.Header)
|
||||
}
|
||||
|
||||
if _, ok := headers["Accept"]; !ok {
|
||||
headers["Accept"] = []string{"*/*"}
|
||||
}
|
||||
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
|
||||
headers["Accept-Encoding"] = []string{"deflate, gzip"}
|
||||
}
|
||||
|
||||
req.Header = headers
|
||||
}
|
||||
|
||||
// setQueryParam set http request query string param
|
||||
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
|
||||
if queryParam != nil {
|
||||
if !strings.Contains(reqUrl, "?") {
|
||||
reqUrl = reqUrl + "?" + queryParam.Encode()
|
||||
} else {
|
||||
reqUrl = reqUrl + "&" + queryParam.Encode()
|
||||
}
|
||||
u, err := url.Parse(reqUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.URL = u
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
||||
formData := []byte(values.Encode())
|
||||
req.Body = io.NopCloser(bytes.NewReader(formData))
|
||||
req.ContentLength = int64(len(formData))
|
||||
}
|
||||
|
||||
// validateRequest check if a request has url, and valid method.
|
||||
func validateRequest(req *HttpRequest) error {
|
||||
if req.RawURL == "" {
|
||||
return errors.New("invalid request url")
|
||||
}
|
||||
|
||||
// common HTTP methods
|
||||
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
|
||||
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
|
||||
|
||||
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
|
||||
return errors.New("invalid request method")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StructToUrlValues convert struct to url valuse,
|
||||
// only convert the field which is exported and has `json` tag.
|
||||
// Play: https://go.dev/play/p/pFqMkM40w9z
|
||||
func StructToUrlValues(targetStruct any) url.Values {
|
||||
rv := reflect.ValueOf(targetStruct)
|
||||
rt := reflect.TypeOf(targetStruct)
|
||||
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
if rt.Kind() != reflect.Struct {
|
||||
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
|
||||
}
|
||||
|
||||
result := url.Values{}
|
||||
|
||||
fieldNum := rt.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
regex := regexp.MustCompile(pattern)
|
||||
for i := 0; i < fieldNum; i++ {
|
||||
name := rt.Field(i).Name
|
||||
tag := rt.Field(i).Tag.Get("json")
|
||||
if regex.MatchString(name) && tag != "" {
|
||||
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestHttpClient_Get(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHttpClient_Get")
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
err = httpClient.DecodeResponse(resp, &todo)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
assert.Equal(1, todo.Id)
|
||||
}
|
||||
|
||||
func TestHttpClent_Post(t *testing.T) {
|
||||
header := http.Header{}
|
||||
header.Add("Content-Type", "multipart/form-data")
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "testItem")
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "POST",
|
||||
Headers: header,
|
||||
FormData: postData,
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestStructToUrlValues(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
||||
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
UserId: 1,
|
||||
}
|
||||
todoValues := StructToUrlValues(todoQuery)
|
||||
|
||||
assert.Equal("1", todoValues.Get("id"))
|
||||
assert.Equal("1", todoValues.Get("userId"))
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "GET",
|
||||
QueryParams: todoValues,
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Log("response: ", string(body))
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package netutil
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ExampleHttpClient_SendRequest() {
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
return
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
err = httpClient.DecodeResponse(resp, &todo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(todo.Id)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
|
||||
func ExampleHttpClient_DecodeResponse() {
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
return
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
err = httpClient.DecodeResponse(resp, &todo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(todo.Id)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
|
||||
func ExampleStructToUrlValues() {
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
Name: "Test",
|
||||
}
|
||||
todoValues := StructToUrlValues(todoQuery)
|
||||
|
||||
fmt.Println(todoValues.Get("id"))
|
||||
fmt.Println(todoValues.Get("name"))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// Test
|
||||
}
|
||||
|
||||
func ExampleConvertMapToQueryString() {
|
||||
var m = map[string]any{
|
||||
"c": 3,
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
|
||||
qs := ConvertMapToQueryString(m)
|
||||
|
||||
fmt.Println(qs)
|
||||
|
||||
// Output:
|
||||
// a=1&b=2&c=3
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
@@ -156,3 +157,90 @@ func TestParseResponse(t *testing.T) {
|
||||
}
|
||||
t.Log("response: ", toDoResp)
|
||||
}
|
||||
|
||||
func TestHttpClient_Get(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHttpClient_Get")
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
err = httpClient.DecodeResponse(resp, &todo)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
assert.Equal(1, todo.Id)
|
||||
}
|
||||
|
||||
func TestHttpClent_Post(t *testing.T) {
|
||||
header := http.Header{}
|
||||
header.Add("Content-Type", "multipart/form-data")
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "testItem")
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "POST",
|
||||
Headers: header,
|
||||
FormData: postData,
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestStructToUrlValues(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
||||
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
UserId: 1,
|
||||
}
|
||||
todoValues := StructToUrlValues(todoQuery)
|
||||
|
||||
assert.Equal("1", todoValues.Get("id"))
|
||||
assert.Equal("1", todoValues.Get("userId"))
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "GET",
|
||||
QueryParams: todoValues,
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Log("response: ", string(body))
|
||||
}
|
||||
|
||||
@@ -89,3 +89,68 @@ func ExampleEncodeUrl() {
|
||||
// Output:
|
||||
// http://www.lancet.com?a=1&b=%5B2%5D
|
||||
}
|
||||
|
||||
func ExampleHttpClient_DecodeResponse() {
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
return
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
err = httpClient.DecodeResponse(resp, &todo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(todo.Id)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
|
||||
func ExampleStructToUrlValues() {
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
Name: "Test",
|
||||
}
|
||||
todoValues := StructToUrlValues(todoQuery)
|
||||
|
||||
fmt.Println(todoValues.Get("id"))
|
||||
fmt.Println(todoValues.Get("name"))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// Test
|
||||
}
|
||||
|
||||
func ExampleConvertMapToQueryString() {
|
||||
var m = map[string]any{
|
||||
"c": 3,
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
|
||||
qs := ConvertMapToQueryString(m)
|
||||
|
||||
fmt.Println(qs)
|
||||
|
||||
// Output:
|
||||
// a=1&b=2&c=3
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
)
|
||||
|
||||
func ExampleRandInt() {
|
||||
|
||||
result := RandInt(1, 10)
|
||||
|
||||
if result >= 1 && result < 10 {
|
||||
|
||||
@@ -3,10 +3,10 @@ package system
|
||||
import "fmt"
|
||||
|
||||
func ExampleSetOsEnv() {
|
||||
ok := SetOsEnv("foo", "abc")
|
||||
err := SetOsEnv("foo", "abc")
|
||||
result := GetOsEnv("foo")
|
||||
|
||||
fmt.Println(ok)
|
||||
fmt.Println(err)
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// <nil>
|
||||
@@ -25,14 +25,14 @@ func ExampleGetOsEnv() {
|
||||
}
|
||||
|
||||
func ExampleRemoveOsEnv() {
|
||||
ok1 := SetOsEnv("foo", "abc")
|
||||
err1 := SetOsEnv("foo", "abc")
|
||||
result1 := GetOsEnv("foo")
|
||||
|
||||
ok2 := RemoveOsEnv("foo")
|
||||
err2 := RemoveOsEnv("foo")
|
||||
result2 := GetOsEnv("foo")
|
||||
|
||||
fmt.Println(ok1)
|
||||
fmt.Println(ok2)
|
||||
fmt.Println(err1)
|
||||
fmt.Println(err2)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
@@ -49,9 +49,10 @@ func ExampleCompareOsEnv() {
|
||||
return
|
||||
}
|
||||
|
||||
result1 := CompareOsEnv("foo", "abc")
|
||||
result := CompareOsEnv("foo", "abc")
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
fmt.Println(result1)
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user