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

Compare commits

...

9 Commits

Author SHA1 Message Date
dudaodong
c8a65c33a4 format code 2023-06-13 15:09:31 +08:00
dudaodong
69a797f8ed doc: format code in doc file 2023-06-13 15:08:40 +08:00
dudaodong
1e5b69e9bf feat: add RemoveWhiteSpace 2023-06-13 15:06:27 +08:00
dudaodong
275abcc8c2 feat: add RandUniqueIntSlice 2023-06-13 15:03:45 +08:00
dudaodong
065b3b84fe add os_test.go 2023-06-13 15:00:40 +08:00
dudaodong
4bc43f3278 feat: add Log 2023-06-13 14:59:30 +08:00
dudaodong
f3382ceac9 feat: add WirteCsvFile 2023-06-13 14:56:43 +08:00
dudaodong
d20f8783b2 feat: add Utf8ToGbk and GbkToUtf8 2023-06-13 14:49:40 +08:00
dudaodong
8432a4e1ee test: update TestExecCommand 2023-06-03 18:33:16 +08:00
30 changed files with 943 additions and 361 deletions

View File

@@ -11,11 +11,15 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"math" "math"
"reflect" "reflect"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
) )
// ToBool convert string to a boolean // ToBool convert string to a boolean
@@ -374,3 +378,17 @@ func ToInterface(v reflect.Value) (value interface{}, ok bool) {
return nil, false return nil, false
} }
} }
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
func Utf8ToGbk(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewEncoder())
b, err := io.ReadAll(r)
return b, err
}
// GbkToUtf8 convert GBK encoding data to utf8 encoding data.
func GbkToUtf8(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
b, err := io.ReadAll(r)
return b, err
}

View File

@@ -4,8 +4,10 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"testing" "testing"
"unicode/utf8"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/internal"
"github.com/duke-git/lancet/validator"
) )
func TestToChar(t *testing.T) { func TestToChar(t *testing.T) {
@@ -339,3 +341,25 @@ func TestToInterface(t *testing.T) {
assert.EqualValues(nil, nilVal) assert.EqualValues(nil, nilVal)
assert.Equal(false, ok) assert.Equal(false, ok)
} }
func TestUtf8ToGbk(t *testing.T) {
assert := internal.NewAssert(t, "TestUtf8ToGbk")
utf8Data := []byte("hello")
gbkData, err := Utf8ToGbk(utf8Data)
assert.Equal(true, utf8.Valid(utf8Data))
assert.Equal(true, validator.IsGBK(gbkData))
assert.IsNil(err)
}
func TestGbkToUtf8(t *testing.T) {
assert := internal.NewAssert(t, "TestGbkToUtf8")
gbkData, err := Utf8ToGbk([]byte("hello"))
utf8Data, err := GbkToUtf8(gbkData)
assert.IsNil(err)
assert.Equal(true, utf8.Valid(utf8Data))
assert.Equal("hello", string(utf8Data))
}

View File

@@ -38,6 +38,8 @@ import (
- [DeepClone](#DeepClone) - [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties) - [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface) - [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -618,3 +620,70 @@ func main() {
// true // true
} }
``` ```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>Converts utf8 encoding data to GBK encoding data.</p>
<b>Signature:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>Converts GBK encoding data to utf8 encoding data.</p>
<b>Signature:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}
```

View File

@@ -38,6 +38,8 @@ import (
- [DeepClone](#DeepClone) - [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties) - [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface) - [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -618,3 +620,70 @@ func main() {
// true // true
} }
``` ```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>utf8编码转GBK编码。</p>
<b>函数签名:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
"github.com/duke-git/lancet/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>GBK编码转utf8编码。</p>
<b>函数签名:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}
```

View File

@@ -43,6 +43,7 @@ import (
- [MTime](#MTime) - [MTime](#MTime)
- [Sha](#Sha) - [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile) - [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
- [WriteStringToFile](#WriteStringToFile) - [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile) - [WriteBytesToFile](#WriteBytesToFile)
@@ -503,7 +504,6 @@ func main() {
} }
``` ```
### <span id="IsZipFile">IsZipFile</span> ### <span id="IsZipFile">IsZipFile</span>
<p>Checks if file is zip file or not.</p> <p>Checks if file is zip file or not.</p>
@@ -664,6 +664,42 @@ func main() {
} }
``` ```
### <span id="WriteCsvFile">WriteCsvFile</span>
<p>Write content to target csv file.</p>
<b>Signature:</b>
```go
func WriteCsvFile(filepath string, records [][]string, append bool) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
)
func main() {
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile("./testdata/test2.csv", data, false)
fmt.Println(err)
content, _ := ReadCsvFile("./testdata/test2.csv")
fmt.Println(content)
// Output:
// <nil>
// [[Lili 22 female] [Jim 21 male]]
}
```
### <span id="WriteBytesToFile">WriteBytesToFile</span> ### <span id="WriteBytesToFile">WriteBytesToFile</span>
@@ -714,7 +750,6 @@ func main() {
} }
``` ```
### <span id="WriteStringToFile">WriteStringToFile</span> ### <span id="WriteStringToFile">WriteStringToFile</span>
<p>Writes string to target file.</p> <p>Writes string to target file.</p>

View File

@@ -43,6 +43,7 @@ import (
- [MTime](#MTime) - [MTime](#MTime)
- [Sha](#Sha) - [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile) - [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
- [WriteStringToFile](#WriteStringToFile) - [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile) - [WriteBytesToFile](#WriteBytesToFile)
@@ -503,7 +504,6 @@ func main() {
} }
``` ```
### <span id="IsZipFile">IsZipFile</span> ### <span id="IsZipFile">IsZipFile</span>
<p>判断文件是否是zip压缩文件。</p> <p>判断文件是否是zip压缩文件。</p>
@@ -664,6 +664,43 @@ func main() {
} }
``` ```
### <span id="WriteCsvFile">WriteCsvFile</span>
<p>向csv文件写入内容。</p>
<b>函数签名:</b>
```go
func WriteCsvFile(filepath string, records [][]string, append bool) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
)
func main() {
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile("./testdata/test2.csv", data, false)
fmt.Println(err)
content, _ := ReadCsvFile("./testdata/test2.csv")
fmt.Println(content)
// Output:
// <nil>
// [[Lili 22 female] [Jim 21 male]]
}
```
### <span id="WriteBytesToFile">WriteBytesToFile</span> ### <span id="WriteBytesToFile">WriteBytesToFile</span>
<p>将bytes写入文件。</p> <p>将bytes写入文件。</p>
@@ -713,7 +750,6 @@ func main() {
} }
``` ```
### <span id="WriteStringToFile">WriteStringToFile</span> ### <span id="WriteStringToFile">WriteStringToFile</span>
<p>将字符串写入文件。</p> <p>将字符串写入文件。</p>

View File

@@ -37,6 +37,7 @@ import (
- [LCM](#LCM) - [LCM](#LCM)
- [Cos](#Cos) - [Cos](#Cos)
- [Sin](#Sin) - [Sin](#Sin)
- [Log](#Log)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -458,7 +459,6 @@ func main() {
} }
``` ```
### <span id="Cos">Cos</span> ### <span id="Cos">Cos</span>
<p>Returns the cosine of the radian argument.</p> <p>Returns the cosine of the radian argument.</p>
@@ -501,7 +501,6 @@ func main() {
} }
``` ```
### <span id="Sin">Sin</span> ### <span id="Sin">Sin</span>
<p>Returns the sine of the radian argument.</p> <p>Returns the sine of the radian argument.</p>
@@ -543,3 +542,39 @@ func main() {
// 1 // 1
} }
``` ```
### <span id="Log">Log</span>
<p>Returns the logarithm of base n.</p>
<b>Signature:</b>
```go
func Log(n, base float64) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
result1 := mathutil.Log(8, 2)
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3
// 2.32
// 3
}
```

View File

@@ -37,6 +37,7 @@ import (
- [LCM](#LCM) - [LCM](#LCM)
- [Cos](#Cos) - [Cos](#Cos)
- [Sin](#Sin) - [Sin](#Sin)
- [Log](#Log)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -544,3 +545,39 @@ func main() {
// 1 // 1
} }
``` ```
### <span id="Log">Log</span>
<p>计算以base为底n的对数。</p>
<b>函数签名:</b>
```go
func Log(n, base float64) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
result1 := mathutil.Log(8, 2)
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3
// 2.32
// 3
}
```

View File

@@ -30,6 +30,7 @@ import (
- [RandNumeral](#RandNumeral) - [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter) - [RandNumeralOrLetter](#RandNumeralOrLetter)
- [UUIdV4](#UUIdV4) - [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -245,3 +246,29 @@ func main() {
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
<p>Generate a slice of random int of length n that do not repeat.</p>
<b>Signature:</b>
```go
func RandUniqueIntSlice(n, min, max int) []int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/random"
)
func main() {
result := RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```

View File

@@ -30,6 +30,7 @@ import (
- [RandNumeral](#RandNumeral) - [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter) - [RandNumeralOrLetter](#RandNumeralOrLetter)
- [UUIdV4](#UUIdV4) - [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -245,3 +246,29 @@ func main() {
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
<p>生成一个不重复的长度为n的随机int切片。</p>
<b>函数签名:</b>
```go
func RandUniqueIntSlice(n, min, max int) []int
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/random"
)
func main() {
result := RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```

View File

@@ -57,6 +57,7 @@ import (
- [Trim](#Trim) - [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim) - [SplitAndTrim](#SplitAndTrim)
- [HideString](#HideString) - [HideString](#HideString)
- [RemoveWhiteSpace](#RemoveWhiteSpace)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -1240,3 +1241,36 @@ func main() {
// false // false
} }
``` ```
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
<p>Remove whitespace characters from a string. when set repalceAll is true removes all whitespace, false only replaces consecutive whitespace characters with one space.</p>
<b>Signature:</b>
```go
func RemoveWhiteSpace(str string, repalceAll bool) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
)
func main() {
str := " hello \r\n \t world"
result1 := strutil.RemoveWhiteSpace(str, true)
result2 := strutil.RemoveWhiteSpace(str, false)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// helloworld
// hello world
}
```

View File

@@ -57,6 +57,8 @@ import (
- [Trim](#Trim) - [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim) - [SplitAndTrim](#SplitAndTrim)
- [HideString](#HideString) - [HideString](#HideString)
- [RemoveWhiteSpace](#RemoveWhiteSpace)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -1272,3 +1274,36 @@ func main() {
// false // false
} }
``` ```
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
<p>删除字符串中的空格当设置repalceAll为true时删除全部空格为false时替换多个空格为1个空格。</p>
<b>函数签名:</b>
```go
func RemoveWhiteSpace(str string, repalceAll bool) string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
)
func main() {
str := " hello \r\n \t world"
result1 := strutil.RemoveWhiteSpace(str, true)
result2 := strutil.RemoveWhiteSpace(str, false)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// helloworld
// hello world
}
```

View File

@@ -370,7 +370,7 @@ func MTime(filepath string) (int64, error) {
return f.ModTime().Unix(), nil return f.ModTime().Unix(), nil
} }
// MTime returns file sha value, param `shaType` should be 1, 256 or 512. // Sha returns file sha value, param `shaType` should be 1, 256 or 512.
func Sha(filepath string, shaType ...int) (string, error) { func Sha(filepath string, shaType ...int) (string, error) {
file, err := os.Open(filepath) file, err := os.Open(filepath)
if err != nil { if err != nil {
@@ -420,6 +420,27 @@ func ReadCsvFile(filepath string) ([][]string, error) {
return records, nil return records, nil
} }
// WriteCsvFile write content to target csv file.
func WriteCsvFile(filepath string, records [][]string, append bool) error {
flag := os.O_RDWR | os.O_CREATE
if append {
flag = flag | os.O_APPEND
}
f, err := os.OpenFile(filepath, flag, 0644)
if err != nil {
return err
}
defer f.Close()
writer := csv.NewWriter(f)
writer.Comma = ','
return writer.WriteAll(records)
}
// WriteStringToFile write string to target file. // WriteStringToFile write string to target file.
func WriteStringToFile(filepath string, content string, append bool) error { func WriteStringToFile(filepath string, content string, append bool) error {
flag := os.O_RDWR | os.O_CREATE flag := os.O_RDWR | os.O_CREATE

View File

@@ -268,7 +268,7 @@ func TestSha(t *testing.T) {
func TestReadCsvFile(t *testing.T) { func TestReadCsvFile(t *testing.T) {
assert := internal.NewAssert(t, "TestReadCsvFile") assert := internal.NewAssert(t, "TestReadCsvFile")
content, err := ReadCsvFile("./testdata/test.csv") content, err := ReadCsvFile("./testdata/demo.csv")
t.Log(content) t.Log(content)
assert.IsNil(err) assert.IsNil(err)
@@ -278,6 +278,27 @@ func TestReadCsvFile(t *testing.T) {
assert.Equal("Bob", content[0][0]) assert.Equal("Bob", content[0][0])
} }
func TestWriteCsvFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteCsvFile")
csvFilePath := "./testdata/test1.csv"
content := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile(csvFilePath, content, false)
assert.IsNil(err)
readContent, err := ReadCsvFile(csvFilePath)
assert.IsNil(err)
assert.Equal(2, len(readContent))
assert.Equal(3, len(readContent[0]))
assert.Equal("Lili", content[0][0])
}
func TestWriteStringToFile(t *testing.T) { func TestWriteStringToFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteStringToFile") assert := internal.NewAssert(t, "TestWriteStringToFile")

2
fileutil/testdata/test1.csv vendored Normal file
View File

@@ -0,0 +1,2 @@
Lili,22,female
Jim,21,male
1 Lili 22 female
2 Jim 21 male

View File

@@ -189,3 +189,8 @@ func Cos(radian float64, precision ...int) float64 {
func Sin(radian float64, precision ...int) float64 { func Sin(radian float64, precision ...int) float64 {
return Cos((math.Pi / 2) - radian) return Cos((math.Pi / 2) - radian)
} }
// Log returns the logarithm of base n.
func Log(n, base float64) float64 {
return math.Log(n) / math.Log(base)
}

View File

@@ -172,3 +172,11 @@ func TestSin(t *testing.T) {
assert.EqualValues(0, Sin(math.Pi)) assert.EqualValues(0, Sin(math.Pi))
assert.EqualValues(1, Sin(math.Pi/2)) assert.EqualValues(1, Sin(math.Pi/2))
} }
func TestLog(t *testing.T) {
assert := internal.NewAssert(t, "TestLog")
assert.EqualValues(3, Log(8, 2))
assert.EqualValues(3, TruncRound(Log(27, 3), 0))
assert.EqualValues(2.32, TruncRound(Log(5, 2), 2))
}

View File

@@ -72,10 +72,3 @@ func TestTelnetConnected(t *testing.T) {
result2 := IsTelnetConnected("www.baidu.com", "123") result2 := IsTelnetConnected("www.baidu.com", "123")
assert.Equal(false, result2) assert.Equal(false, result2)
} }
// func TestDownloadFile(t *testing.T) {
// assert := internal.NewAssert(t, "TestDownloadFile")
// err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
// assert.IsNil(err)
// }

View File

@@ -101,3 +101,27 @@ func UUIdV4() (string, error) {
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
} }
// RandUniqueIntSlice generate a slice of random int of length n that do not repeat.
func RandUniqueIntSlice(n, min, max int) []int {
if min > max {
return []int{}
}
if n > max-min {
n = max - min
}
nums := make([]int, n)
used := make(map[int]struct{}, n)
for i := 0; i < n; {
r := RandInt(min, max)
if _, use := used[r]; use {
continue
}
used[r] = struct{}{}
nums[i] = r
i++
}
return nums
}

View File

@@ -105,3 +105,36 @@ func TestUUIdV4(t *testing.T) {
isUUiDV4 := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`) isUUiDV4 := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`)
assert.Equal(true, isUUiDV4.MatchString(uuid)) assert.Equal(true, isUUiDV4.MatchString(uuid))
} }
func TestRandUniqueIntSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestRandUniqueIntSlice")
r1 := RandUniqueIntSlice(5, 0, 9)
assert.Equal(len(r1), 5)
if hasDuplicate(r1) {
t.Error("hasDuplicate int")
}
r2 := RandUniqueIntSlice(20, 0, 10)
assert.Equal(len(r2), 10)
if hasDuplicate(r2) {
t.Error("hasDuplicate int")
}
r3 := RandUniqueIntSlice(10, 20, 10)
assert.Equal(len(r3), 0)
r4 := RandUniqueIntSlice(0, 20, 10)
assert.Equal(len(r4), 0)
}
func hasDuplicate(arr []int) bool {
elements := make(map[int]bool)
for _, v := range arr {
if elements[v] {
return true
}
elements[v] = true
}
return false
}

View File

@@ -6,6 +6,7 @@ package strutil
import ( import (
"reflect" "reflect"
"regexp"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
@@ -503,3 +504,21 @@ func ContainsAny(str string, substrs []string) bool {
return false return false
} }
var (
whitespaceRegexMatcher *regexp.Regexp = regexp.MustCompile(`\s`)
mutiWhitespaceRegexMatcher *regexp.Regexp = regexp.MustCompile(`[[:space:]]{2,}|[\s\p{Zs}]{2,}`)
)
// RemoveWhiteSpace remove whitespace characters from a string.
// when set repalceAll is true removes all whitespace, false only replaces consecutive whitespace characters with one space.
func RemoveWhiteSpace(str string, repalceAll bool) string {
if repalceAll && str != "" {
return strings.Join(strings.Fields(str), "")
} else if str != "" {
str = mutiWhitespaceRegexMatcher.ReplaceAllString(str, " ")
str = whitespaceRegexMatcher.ReplaceAllString(str, " ")
}
return strings.TrimSpace(str)
}

View File

@@ -455,3 +455,13 @@ func TestContainsAny(t *testing.T) {
assert.Equal(true, ContainsAny("hello world", []string{"hello", "abc"})) assert.Equal(true, ContainsAny("hello world", []string{"hello", "abc"}))
assert.Equal(false, ContainsAny("hello world", []string{"123", "abc"})) assert.Equal(false, ContainsAny("hello world", []string{"123", "abc"}))
} }
func TestRemoveWhiteSpace(t *testing.T) {
assert := internal.NewAssert(t, "TestRemoveWhiteSpace")
str := " hello \r\n \t world"
assert.Equal("", RemoveWhiteSpace("", true))
assert.Equal("helloworld", RemoveWhiteSpace(str, true))
assert.Equal("hello world", RemoveWhiteSpace(str, false))
}

View File

@@ -45,7 +45,7 @@ func TestExecCommand(t *testing.T) {
assert := internal.NewAssert(t, "TestExecCommand") assert := internal.NewAssert(t, "TestExecCommand")
// linux or mac // linux or mac
stdout, stderr, err := ExecCommand("ls", WithForeground()) stdout, stderr, err := ExecCommand("ls")
t.Log("std out: ", stdout) t.Log("std out: ", stdout)
t.Log("std err: ", stderr) t.Log("std err: ", stderr)
assert.Equal("", stderr) assert.Equal("", stderr)