1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35:28 +08:00

Compare commits

..

4 Commits

Author SHA1 Message Date
dudaodong bc3c080ac3 doc: normalize document 2023-01-15 12:43:00 +08:00
dudaodong d3fab15af3 refactor: clean structure for netutil package 2023-01-14 14:39:06 +08:00
dudaodong 6e3e411d46 doc: normalize document 2023-01-14 12:48:39 +08:00
dudaodong f976941e36 doc: normalize document 2023-01-14 12:32:27 +08:00
24 changed files with 4617 additions and 3572 deletions
+362 -319
View File
File diff suppressed because it is too large Load Diff
+365 -320
View File
File diff suppressed because it is too large Load Diff
+16 -16
View File
@@ -56,8 +56,8 @@ import (
) )
func main() { func main() {
randBytes := random.RandBytes(4) randBytes := random.RandBytes(4)
fmt.Println(randBytes) fmt.Println(randBytes)
} }
``` ```
@@ -82,8 +82,8 @@ import (
) )
func main() { func main() {
rInt := random.RandInt(1, 10) rInt := random.RandInt(1, 10)
fmt.Println(rInt) fmt.Println(rInt)
} }
``` ```
@@ -108,8 +108,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //pGWsze fmt.Println(randStr) //pGWsze
} }
``` ```
@@ -134,8 +134,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //PACWGF fmt.Println(randStr) //PACWGF
} }
``` ```
@@ -160,8 +160,8 @@ import (
) )
func main() { func main() {
randStr := random.RandLower(6) randStr := random.RandLower(6)
fmt.Println(randStr) //siqbew fmt.Println(randStr) //siqbew
} }
``` ```
@@ -186,8 +186,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeral(6) randStr := random.RandNumeral(6)
fmt.Println(randStr) //035172 fmt.Println(randStr) //035172
} }
``` ```
@@ -212,8 +212,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeralOrLetter(6) randStr := random.RandNumeralOrLetter(6)
fmt.Println(randStr) //0aW7cQ fmt.Println(randStr) //0aW7cQ
} }
``` ```
@@ -238,10 +238,10 @@ import (
) )
func main() { func main() {
uuid, err := random.UUIdV4() uuid, err := random.UUIdV4()
if err != nil { if err != nil {
return return
} }
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```
+16 -16
View File
@@ -56,8 +56,8 @@ import (
) )
func main() { func main() {
randBytes := random.RandBytes(4) randBytes := random.RandBytes(4)
fmt.Println(randBytes) fmt.Println(randBytes)
} }
``` ```
@@ -82,8 +82,8 @@ import (
) )
func main() { func main() {
rInt := random.RandInt(1, 10) rInt := random.RandInt(1, 10)
fmt.Println(rInt) fmt.Println(rInt)
} }
``` ```
@@ -108,8 +108,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //pGWsze fmt.Println(randStr) //pGWsze
} }
``` ```
@@ -134,8 +134,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //PACWGF fmt.Println(randStr) //PACWGF
} }
``` ```
@@ -160,8 +160,8 @@ import (
) )
func main() { func main() {
randStr := random.RandLower(6) randStr := random.RandLower(6)
fmt.Println(randStr) //siqbew fmt.Println(randStr) //siqbew
} }
``` ```
@@ -186,8 +186,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeral(6) randStr := random.RandNumeral(6)
fmt.Println(randStr) //035172 fmt.Println(randStr) //035172
} }
``` ```
@@ -212,8 +212,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeralOrLetter(6) randStr := random.RandNumeralOrLetter(6)
fmt.Println(randStr) //0aW7cQ fmt.Println(randStr) //0aW7cQ
} }
``` ```
@@ -238,10 +238,10 @@ import (
) )
func main() { func main() {
uuid, err := random.UUIdV4() uuid, err := random.UUIdV4()
if err != nil { if err != nil {
return return
} }
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```
+108 -84
View File
@@ -1,16 +1,17 @@
# Retry # Retry
Package retry is for executing a function repeatedly until it was successful or canceled by the context. Package retry is for executing a function repeatedly until it was successful or canceled by the context.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Source: ## 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> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
@@ -20,18 +21,19 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Context](#Context)
- [Retry](#Retry) - [Context](#Context)
- [RetryFunc](#RetryFunc) - [Retry](#Retry)
- [RetryDuration](#RetryDuration) - [RetryFunc](#RetryFunc)
- [RetryTimes](#RetryTimes) - [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Context">Context</span> ### <span id="Context">Context</span>
<p>Set retry context config, can cancel the retry with context.</p> <p>Set retry context config, can cancel the retry with context.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -39,43 +41,46 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
"time" "time"
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) 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, number := 0
retry.RetryDuration(time.Microsecond*50), increaseNumber := func() error {
retry.Context(ctx), number++
) if number > 3 {
cancel()
}
return errors.New("error occurs")
}
if err != nil { duration := retry.RetryDuration(time.Microsecond*50)
fmt.Println(err) //retry is cancelled
} retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
fmt.Println(number)
// Output:
// 4
} }
``` ```
### <span id="RetryFunc">RetryFunc</span> ### <span id="RetryFunc">RetryFunc</span>
<p>Function that retry executes.</p> <p>Function that retry executes.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -83,6 +88,7 @@ func main() {
```go ```go
type RetryFunc func() error type RetryFunc func() error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -96,28 +102,31 @@ import (
) )
func main() { 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 { duration := retry.RetryDuration(time.Microsecond*50)
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="RetryTimes">RetryTimes</span> ### <span id="RetryTimes">RetryTimes</span>
<p>Set times of retry. Default times is 5.</p> <p>Set times of retry. Default times is 5.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -125,6 +134,7 @@ func main() {
```go ```go
func RetryTimes(n uint) func RetryTimes(n uint)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -138,26 +148,28 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryTimes(2)) err := retry.Retry(increaseNumber, retry.RetryTimes(2))
if err != nil { 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> ### <span id="RetryDuration">RetryDuration</span>
<p>Set duration of retries. Default duration is 3 second.</p> <p>Set duration of retries. Default duration is 3 second.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -165,6 +177,7 @@ func main() {
```go ```go
func RetryDuration(d time.Duration) func RetryDuration(d time.Duration)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -178,26 +191,31 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") 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 { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="Retry">Retry</span> ### <span id="Retry">Retry</span>
<p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p> <p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -205,6 +223,7 @@ func main() {
```go ```go
func Retry(retryFunc RetryFunc, opts ...Option) error func Retry(retryFunc RetryFunc, opts ...Option) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -218,20 +237,25 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") 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 { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
+111 -87
View File
@@ -1,16 +1,17 @@
# Retry # Retry
retry重试执行函数直到函数运行成功或被context cancel。
retry 重试执行函数直到函数运行成功或被 context cancel。
<div STYLE="page-break-after: always;"></div> <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> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
@@ -20,20 +21,19 @@ import (
<div STYLE="page-break-after: always;"></div> <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> <div STYLE="page-break-after: always;"></div>
## Document 文档
## Document文档
### <span id="Context">Context</span> ### <span id="Context">Context</span>
<p>设置重试context参数</p> <p>设置重试context参数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -41,43 +41,46 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"lancet-demo/retry" "lancet-demo/retry"
"time" "time"
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) 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, number := 0
retry.RetryDuration(time.Microsecond*50), increaseNumber := func() error {
retry.Context(ctx), number++
) if number > 3 {
cancel()
}
return errors.New("error occurs")
}
if err != nil { duration := retry.RetryDuration(time.Microsecond*50)
fmt.Println(err) //retry is cancelled
} retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
fmt.Println(number)
// Output:
// 4
} }
``` ```
### <span id="RetryFunc">RetryFunc</span> ### <span id="RetryFunc">RetryFunc</span>
<p>被重试执行的函数</p> <p>被重试执行的函数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -85,6 +88,7 @@ func main() {
```go ```go
type RetryFunc func() error type RetryFunc func() error
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
@@ -98,27 +102,31 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { var increaseNumber retry.RetryFunc = func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") 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 { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="RetryTimes">RetryTimes</span> ### <span id="RetryTimes">RetryTimes</span>
<p>设置重试次数,默认5</p> <p>设置重试次数,默认5</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -126,6 +134,7 @@ func main() {
```go ```go
func RetryTimes(n uint) func RetryTimes(n uint)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
@@ -139,25 +148,28 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
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 { 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> ### <span id="RetryDuration">RetryDuration</span>
<p>设置重试间隔时间,默认3秒</p> <p>设置重试间隔时间,默认3秒</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -165,6 +177,7 @@ func main() {
```go ```go
func RetryDuration(d time.Duration) func RetryDuration(d time.Duration)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
@@ -178,26 +191,31 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") 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 { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="Retry">Retry</span> ### <span id="Retry">Retry</span>
<p>重试执行函数retryFunc,直到函数运行成功,或被context停止</p> <p>重试执行函数retryFunc,直到函数运行成功,或被context停止</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -205,6 +223,7 @@ func main() {
```go ```go
func Retry(retryFunc RetryFunc, opts ...Option) error func Retry(retryFunc RetryFunc, opts ...Option) error
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
@@ -218,20 +237,25 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") 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 { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
+663 -386
View File
File diff suppressed because it is too large Load Diff
+668 -389
View File
File diff suppressed because it is too large Load Diff
+378 -348
View File
File diff suppressed because it is too large Load Diff
+382 -344
View File
File diff suppressed because it is too large Load Diff
+116 -89
View File
@@ -1,16 +1,17 @@
# System # System
Package system contains some functions about os, runtime, shell command. Package system contains some functions about os, runtime, shell command.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Source: ## 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> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
@@ -20,23 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsWindows](#IsWindows)
- [IsMac](#IsMac) - [IsLinux](#IsLinux)
- [GetOsEnv](#GetOsEnv) - [IsMac](#IsMac)
- [SetOsEnv](#SetOsEnv) - [GetOsEnv](#GetOsEnv)
- [RemoveOsEnv](#RemoveOsEnv) - [SetOsEnv](#SetOsEnv)
- [CompareOsEnv](#CompareOsEnv) - [RemoveOsEnv](#RemoveOsEnv)
- [ExecCommand](#ExecCommand) - [CompareOsEnv](#CompareOsEnv)
- [GetOsBits](#GetOsBits) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>Check if current os is windows.</p> <p>Check if current os is windows.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -44,24 +45,23 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsWindows := system.IsWindows() isOsWindows := system.IsWindows()
fmt.Println(isOsWindows) fmt.Println(isOsWindows)
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>Check if current os is linux.</p> <p>Check if current os is linux.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,23 +69,23 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsLinux := system.IsLinux() isOsLinux := system.IsLinux()
fmt.Println(isOsLinux) fmt.Println(isOsLinux)
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>Check if current os is macos.</p> <p>Check if current os is macos.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,23 +93,23 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsMac := system.IsMac() isOsMac := system.IsMac()
fmt.Println(isOsMac) fmt.Println(isOsMac)
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>Gets the value of the environment variable named by the key.</p> <p>Gets the value of the environment variable named by the key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,23 +117,29 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
fooEnv := system.GetOsEnv("foo") err := system.SetOsEnv("foo", "abc")
fmt.Println(fooEnv) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="SetOsEnv">SetOsEnv</span> ### <span id="SetOsEnv">SetOsEnv</span>
<p>Sets the value of the environment variable named by the key.</p> <p>Sets the value of the environment variable named by the key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -141,24 +147,29 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
fmt.Println(err) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="RemoveOsEnv">RemoveOsEnv</span> ### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>Remove a single environment variable.</p> <p>Remove a single environment variable.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,25 +177,37 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.RemoveOsEnv("foo") err1 := system.SetOsEnv("foo", "abc")
if err != nil { result1 := GetOsEnv("foo")
fmt.Println(err)
} 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> ### <span id="CompareOsEnv">CompareOsEnv</span>
<p>Get env named by the key and compare it with comparedEnv.</p> <p>Get env named by the key and compare it with comparedEnv.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,25 +215,32 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
res := system.CompareOsEnv("foo", "foo_value") if err != nil {
fmt.Println(res) //true return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
} }
``` ```
### <span id="ExecCommand">CompareOsEnv</span> ### <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> <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> <b>Signature:</b>
@@ -218,40 +248,39 @@ func main() {
```go ```go
func ExecCommand(command string) (stdout, stderr string, err error) func ExecCommand(command string) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
// linux or mac // linux or mac
stdout, stderr, err := system.ExecCommand("ls") stdout, stderr, err := system.ExecCommand("ls")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
assert.Equal("", stderr) assert.Equal("", stderr)
// windows // windows
stdout, stderr, err = system.ExecCommand("dir") stdout, stderr, err = system.ExecCommand("dir")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
// error command // error command
stdout, stderr, err = system.ExecCommand("abc") stdout, stderr, err = system.ExecCommand("abc")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p> <p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
<b>Signature:</b> <b>Signature:</b>
@@ -259,19 +288,17 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```
+118 -95
View File
@@ -1,16 +1,17 @@
# System # System
system包含os, runtime, shell command相关函数。
system 包含 os, runtime, shell command 相关函数。
<div STYLE="page-break-after: always;"></div> <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> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
@@ -20,23 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsWindows](#IsWindows)
- [IsMac](#IsMac) - [IsLinux](#IsLinux)
- [GetOsEnv](#GetOsEnv) - [IsMac](#IsMac)
- [SetOsEnv](#SetOsEnv) - [GetOsEnv](#GetOsEnv)
- [RemoveOsEnv](#RemoveOsEnv) - [SetOsEnv](#SetOsEnv)
- [CompareOsEnv](#CompareOsEnv) - [RemoveOsEnv](#RemoveOsEnv)
- [ExecCommand](#ExecCommand) - [CompareOsEnv](#CompareOsEnv)
- [GetOsBits](#GetOsBits) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation文档 ## Documentation 文档
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>检查当前操作系统是否是windows</p> <p>检查当前操作系统是否是windows</p>
<b>Signature:</b> <b>Signature:</b>
@@ -44,24 +45,23 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsWindows := system.IsWindows() isOsWindows := system.IsWindows()
fmt.Println(isOsWindows) fmt.Println(isOsWindows)
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>检查当前操作系统是否是linux</p> <p>检查当前操作系统是否是linux</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,23 +69,23 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsLinux := system.IsLinux() isOsLinux := system.IsLinux()
fmt.Println(isOsLinux) fmt.Println(isOsLinux)
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>检查当前操作系统是否是macos</p> <p>检查当前操作系统是否是macos</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,23 +93,23 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsMac := system.IsMac() isOsMac := system.IsMac()
fmt.Println(isOsMac) fmt.Println(isOsMac)
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>获取key命名的环境变量的值</p> <p>获取key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,23 +117,29 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
fooEnv := system.GetOsEnv("foo") err := system.SetOsEnv("foo", "abc")
fmt.Println(fooEnv) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="SetOsEnv">SetOsEnv</span> ### <span id="SetOsEnv">SetOsEnv</span>
<p>设置由key命名的环境变量的值</p> <p>设置由key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -141,24 +147,29 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
fmt.Println(err) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="RemoveOsEnv">RemoveOsEnv</span> ### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>删除单个环境变量</p> <p>删除单个环境变量</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,25 +177,37 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.RemoveOsEnv("foo") err1 := system.SetOsEnv("foo", "abc")
if err != nil { result1 := GetOsEnv("foo")
fmt.Println(err)
} 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> ### <span id="CompareOsEnv">CompareOsEnv</span>
<p>获取key命名的环境变量值并与compareEnv进行比较</p> <p>获取key命名的环境变量值并与compareEnv进行比较</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,25 +215,32 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
res := system.CompareOsEnv("foo", "foo_value") if err != nil {
fmt.Println(res) //true return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
} }
``` ```
### <span id="ExecCommand">ExecCommand</span> ### <span id="ExecCommand">ExecCommand</span>
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-alinux),dirwindows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p> <p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-alinux),dirwindows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p>
<b>Signature:</b> <b>Signature:</b>
@@ -218,40 +248,39 @@ func main() {
```go ```go
func ExecCommand(command string) (stdout, stderr string, err error) func ExecCommand(command string) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
// linux or mac // linux or mac
stdout, stderr, err := system.ExecCommand("ls") stdout, stderr, err := system.ExecCommand("ls")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
assert.Equal("", stderr) assert.Equal("", stderr)
// windows // windows
stdout, stderr, err = system.ExecCommand("dir") stdout, stderr, err = system.ExecCommand("dir")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
// error command // error command
stdout, stderr, err = system.ExecCommand("abc") stdout, stderr, err = system.ExecCommand("abc")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>获取当前操作系统位数,返回32或64</p> <p>获取当前操作系统位数,返回32或64</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -259,23 +288,17 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```
+442 -307
View File
File diff suppressed because it is too large Load Diff
+445 -298
View File
File diff suppressed because it is too large Load Diff
+19 -16
View File
@@ -1,15 +1,17 @@
# Xerror # Xerror
Package xerror implements helpers for errors. Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Source: ## 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> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/xerror" "github.com/duke-git/lancet/v2/xerror"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Unwrap](#Unwrap)
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Unwrap">Unwrap</span> ### <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> <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> <b>Signature:</b>
@@ -35,6 +37,7 @@ import (
```go ```go
func Unwrap[T any](val T, err error) T func Unwrap[T any](val T, err error) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -46,20 +49,20 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42")) result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1) fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
defer func() { defer func() {
v := recover() v := recover()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error()) result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2) fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.Unwrap(strconv.Atoi("4o2"))
// Output: // Output:
// 42 // 42
// true // true
} }
``` ```
+20 -17
View File
@@ -1,15 +1,17 @@
# Xerror # Xerror
xerror错误处理逻辑封装
xerror 错误处理逻辑封装
<div STYLE="page-break-after: always;"></div> <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> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/xerror" "github.com/duke-git/lancet/v2/xerror"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Unwrap](#Unwrap)
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="Unwrap">Unwrap</span> ### <span id="Unwrap">Unwrap</span>
<p>检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则Unwrap使用err发生panic。</p> <p>检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则Unwrap使用err发生panic。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -35,6 +37,7 @@ import (
```go ```go
func Unwrap[T any](val T, err error) T func Unwrap[T any](val T, err error) T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
@@ -46,20 +49,20 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42")) result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1) fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
defer func() { defer func() {
v := recover() v := recover()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error()) result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2) fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.Unwrap(strconv.Atoi("4o2"))
// Output: // Output:
// 42 // 42
// true // true
} }
``` ```
+226
View File
@@ -13,12 +13,21 @@
package netutil package netutil
import ( import (
"bytes"
"crypto/tls"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/url"
"reflect"
"regexp"
"sort" "sort"
"strings" "strings"
"time"
"github.com/duke-git/lancet/v2/slice"
) )
// HttpGet send get http request. // HttpGet send get http request.
@@ -78,3 +87,220 @@ func ConvertMapToQueryString(param map[string]any) string {
} }
return build.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
}
-235
View File
@@ -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
}
-98
View File
@@ -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))
}
-99
View File
@@ -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
}
+88
View File
@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"log" "log"
"net/http"
"net/url" "net/url"
"testing" "testing"
@@ -156,3 +157,90 @@ func TestParseResponse(t *testing.T) {
} }
t.Log("response: ", toDoResp) 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))
}
+65
View File
@@ -89,3 +89,68 @@ func ExampleEncodeUrl() {
// Output: // Output:
// http://www.lancet.com?a=1&b=%5B2%5D // 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
}
-1
View File
@@ -6,7 +6,6 @@ import (
) )
func ExampleRandInt() { func ExampleRandInt() {
result := RandInt(1, 10) result := RandInt(1, 10)
if result >= 1 && result < 10 { if result >= 1 && result < 10 {
+9 -8
View File
@@ -3,10 +3,10 @@ package system
import "fmt" import "fmt"
func ExampleSetOsEnv() { func ExampleSetOsEnv() {
ok := SetOsEnv("foo", "abc") err := SetOsEnv("foo", "abc")
result := GetOsEnv("foo") result := GetOsEnv("foo")
fmt.Println(ok) fmt.Println(err)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// <nil> // <nil>
@@ -25,14 +25,14 @@ func ExampleGetOsEnv() {
} }
func ExampleRemoveOsEnv() { func ExampleRemoveOsEnv() {
ok1 := SetOsEnv("foo", "abc") err1 := SetOsEnv("foo", "abc")
result1 := GetOsEnv("foo") result1 := GetOsEnv("foo")
ok2 := RemoveOsEnv("foo") err2 := RemoveOsEnv("foo")
result2 := GetOsEnv("foo") result2 := GetOsEnv("foo")
fmt.Println(ok1) fmt.Println(err1)
fmt.Println(ok2) fmt.Println(err2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
@@ -49,9 +49,10 @@ func ExampleCompareOsEnv() {
return return
} }
result1 := CompareOsEnv("foo", "abc") result := CompareOsEnv("foo", "abc")
fmt.Println(result)
fmt.Println(result1)
// Output: // Output:
// true // true
} }