mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
feat: merge some new functions from rc branch
This commit is contained in:
10
README.md
10
README.md
@@ -96,6 +96,7 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [ToJson](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToJson)
|
- [ToJson](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToJson)
|
||||||
- [ToString](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToString)
|
- [ToString](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToString)
|
||||||
- [StructToMap](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#StructToMap)
|
- [StructToMap](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#StructToMap)
|
||||||
|
- [MapToStruct](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#MapToStruct)
|
||||||
- [EncodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#EncodeByte)
|
- [EncodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#EncodeByte)
|
||||||
- [DecodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DecodeByte)
|
- [DecodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DecodeByte)
|
||||||
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DeepClone)
|
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DeepClone)
|
||||||
@@ -103,6 +104,10 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [ToInterface](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToInterface)
|
- [ToInterface](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToInterface)
|
||||||
- [Utf8ToGbk](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#Utf8ToGbk)
|
- [Utf8ToGbk](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#Utf8ToGbk)
|
||||||
- [GbkToUtf8](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#GbkToUtf8)
|
- [GbkToUtf8](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#GbkToUtf8)
|
||||||
|
- [ToStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToStdBase64)
|
||||||
|
- [ToUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToUrlBase64)
|
||||||
|
- [ToRawStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToRawStdBase64)
|
||||||
|
- [ToRawUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToRawUrlBase64)
|
||||||
|
|
||||||
### 3. Cryptor package is for data encryption and decryption.
|
### 3. Cryptor package is for data encryption and decryption.
|
||||||
|
|
||||||
@@ -237,6 +242,7 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Sha)
|
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Sha)
|
||||||
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadCsvFile)
|
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadCsvFile)
|
||||||
- [WriteCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteCsvFile)
|
- [WriteCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteCsvFile)
|
||||||
|
- [WriteMapsToCsv](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteMapsToCsv)
|
||||||
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteStringToFile)
|
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteStringToFile)
|
||||||
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteBytesToFile)
|
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteBytesToFile)
|
||||||
- [ReadFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFile)
|
- [ReadFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFile)
|
||||||
@@ -454,6 +460,10 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SplitAndTrim)
|
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SplitAndTrim)
|
||||||
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HideString)
|
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HideString)
|
||||||
- [RemoveWhiteSpace](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#RemoveWhiteSpace)
|
- [RemoveWhiteSpace](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#RemoveWhiteSpace)
|
||||||
|
- [SubInBetween](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SubInBetween)
|
||||||
|
- [HammingDistance](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HammingDistance)
|
||||||
|
|
||||||
|
|
||||||
### 14. System package contain some functions about os, runtime, shell command.
|
### 14. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [ToJson](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToJson)
|
- [ToJson](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToJson)
|
||||||
- [ToString](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToString)
|
- [ToString](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToString)
|
||||||
- [StructToMap](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#StructToMap)
|
- [StructToMap](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#StructToMap)
|
||||||
|
- [MapToStruct](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#MapToStruct)
|
||||||
- [EncodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#EncodeByte)
|
- [EncodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#EncodeByte)
|
||||||
- [DecodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DecodeByte)
|
- [DecodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DecodeByte)
|
||||||
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DeepClone)
|
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DeepClone)
|
||||||
@@ -102,6 +103,12 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [ToInterface](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToInterface)
|
- [ToInterface](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToInterface)
|
||||||
- [Utf8ToGbk](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#Utf8ToGbk)
|
- [Utf8ToGbk](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#Utf8ToGbk)
|
||||||
- [GbkToUtf8](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#GbkToUtf8)
|
- [GbkToUtf8](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#GbkToUtf8)
|
||||||
|
- [ToStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToStdBase64)
|
||||||
|
- [ToUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToUrlBase64)
|
||||||
|
- [ToRawStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToRawStdBase64)
|
||||||
|
- [ToRawUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToRawUrlBase64)
|
||||||
|
|
||||||
|
|
||||||
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -238,6 +245,7 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Sha)
|
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Sha)
|
||||||
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadCsvFile)
|
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadCsvFile)
|
||||||
- [WriteCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteCsvFile)
|
- [WriteCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteCsvFile)
|
||||||
|
- [WriteMapsToCsv](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteMapsToCsv)
|
||||||
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteStringToFile)
|
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteStringToFile)
|
||||||
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteBytesToFile)
|
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteBytesToFile)
|
||||||
- [ReadFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFile)
|
- [ReadFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFile)
|
||||||
@@ -454,6 +462,8 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SplitAndTrim)
|
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SplitAndTrim)
|
||||||
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HideString)
|
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HideString)
|
||||||
- [RemoveWhiteSpace](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#RemoveWhiteSpace)
|
- [RemoveWhiteSpace](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#RemoveWhiteSpace)
|
||||||
|
- [SubInBetween](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SubInBetween)
|
||||||
|
- [HammingDistance](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HammingDistance)
|
||||||
|
|
||||||
### 14. system 包含 os, runtime, shell command 相关函数。
|
### 14. system 包含 os, runtime, shell command 相关函数。
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package convertor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -364,7 +365,6 @@ func GbkToUtf8(bs []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MapToStruct converts map to struct
|
// MapToStruct converts map to struct
|
||||||
// Play: todo
|
|
||||||
func MapToStruct(m map[string]interface{}, structObj interface{}) error {
|
func MapToStruct(m map[string]interface{}, structObj interface{}) error {
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
err := setStructField(structObj, k, v)
|
err := setStructField(structObj, k, v)
|
||||||
@@ -375,3 +375,87 @@ func MapToStruct(m map[string]interface{}, structObj interface{}) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToStdBase64 convert data to standard base64 encoding.
|
||||||
|
func ToStdBase64(value interface{}) string {
|
||||||
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
switch value.(type) {
|
||||||
|
case []byte:
|
||||||
|
return base64.StdEncoding.EncodeToString(value.([]byte))
|
||||||
|
case string:
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(value.(string)))
|
||||||
|
case error:
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||||
|
default:
|
||||||
|
marshal, err := json.Marshal(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(marshal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUrlBase64 convert data to URL base64 encoding.
|
||||||
|
func ToUrlBase64(value interface{}) string {
|
||||||
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
switch value.(type) {
|
||||||
|
case []byte:
|
||||||
|
return base64.URLEncoding.EncodeToString(value.([]byte))
|
||||||
|
case string:
|
||||||
|
return base64.URLEncoding.EncodeToString([]byte(value.(string)))
|
||||||
|
case error:
|
||||||
|
return base64.URLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||||
|
default:
|
||||||
|
marshal, err := json.Marshal(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return base64.URLEncoding.EncodeToString(marshal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToRawStdBase64 convert data to raw standard base64 encoding.
|
||||||
|
func ToRawStdBase64(value interface{}) string {
|
||||||
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
switch value.(type) {
|
||||||
|
case []byte:
|
||||||
|
return base64.RawStdEncoding.EncodeToString(value.([]byte))
|
||||||
|
case string:
|
||||||
|
return base64.RawStdEncoding.EncodeToString([]byte(value.(string)))
|
||||||
|
case error:
|
||||||
|
return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||||
|
default:
|
||||||
|
marshal, err := json.Marshal(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return base64.RawStdEncoding.EncodeToString(marshal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToRawUrlBase64 convert data to raw URL base64 encoding.
|
||||||
|
func ToRawUrlBase64(value interface{}) string {
|
||||||
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
switch value.(type) {
|
||||||
|
case []byte:
|
||||||
|
return base64.RawURLEncoding.EncodeToString(value.([]byte))
|
||||||
|
case string:
|
||||||
|
return base64.RawURLEncoding.EncodeToString([]byte(value.(string)))
|
||||||
|
case error:
|
||||||
|
return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||||
|
default:
|
||||||
|
marshal, err := json.Marshal(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return base64.RawURLEncoding.EncodeToString(marshal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package convertor
|
package convertor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
"github.com/duke-git/lancet/internal"
|
||||||
"github.com/duke-git/lancet/validator"
|
"github.com/duke-git/lancet/validator"
|
||||||
@@ -400,3 +404,279 @@ func TestMapToStruct(t *testing.T) {
|
|||||||
assert.Equal("test", p.Addr.Street)
|
assert.Equal("test", p.Addr.Street)
|
||||||
assert.Equal(1, p.Addr.Number)
|
assert.Equal(1, p.Addr.Number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToStdBase64(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestToStdBase64")
|
||||||
|
|
||||||
|
r1 := ToStdBase64("abc")
|
||||||
|
d1, _ := base64.StdEncoding.DecodeString(r1)
|
||||||
|
assert.Equal("abc", string(d1))
|
||||||
|
|
||||||
|
r2 := ToStdBase64([]byte("abc"))
|
||||||
|
d2, _ := base64.StdEncoding.DecodeString(r2)
|
||||||
|
assert.Equal("abc", string(d2))
|
||||||
|
|
||||||
|
r3 := ToStdBase64(123)
|
||||||
|
d3, _ := base64.StdEncoding.DecodeString(r3)
|
||||||
|
assert.Equal("123", string(d3))
|
||||||
|
|
||||||
|
r4 := ToStdBase64(11.11)
|
||||||
|
d4, _ := base64.StdEncoding.DecodeString(r4)
|
||||||
|
assert.Equal("11.11", string(d4))
|
||||||
|
|
||||||
|
r5 := ToStdBase64(map[string]interface{}{"name": "duke", "quantity": 1})
|
||||||
|
d5, _ := base64.StdEncoding.DecodeString(r5)
|
||||||
|
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||||
|
|
||||||
|
r6 := ToStdBase64([]int64{7, 5, 9, 4, 23})
|
||||||
|
d6, _ := base64.StdEncoding.DecodeString(r6)
|
||||||
|
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||||
|
|
||||||
|
r7 := ToStdBase64([]string{"7", "5", "9", "4", "23"})
|
||||||
|
d7, _ := base64.StdEncoding.DecodeString(r7)
|
||||||
|
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||||
|
|
||||||
|
r8 := ToStdBase64(nil)
|
||||||
|
d8, _ := base64.StdEncoding.DecodeString(r8)
|
||||||
|
assert.Equal("", string(d8))
|
||||||
|
|
||||||
|
ch := make(chan int, 3)
|
||||||
|
ch <- 1
|
||||||
|
ch <- 2
|
||||||
|
r9 := ToStdBase64(ch)
|
||||||
|
d9, _ := base64.StdEncoding.DecodeString(r9)
|
||||||
|
assert.Equal("", string(d9))
|
||||||
|
|
||||||
|
r10 := ToStdBase64(io.EOF)
|
||||||
|
d10, _ := base64.StdEncoding.DecodeString(r10)
|
||||||
|
assert.Equal("EOF", string(d10))
|
||||||
|
|
||||||
|
r11 := ToStdBase64(errors.New("test"))
|
||||||
|
d11, _ := base64.StdEncoding.DecodeString(r11)
|
||||||
|
assert.Equal("test", string(d11))
|
||||||
|
|
||||||
|
typedNil := (*int)(nil)
|
||||||
|
r12 := ToStdBase64(typedNil)
|
||||||
|
d12, _ := base64.StdEncoding.DecodeString(r12)
|
||||||
|
assert.Equal("", string(d12))
|
||||||
|
|
||||||
|
type nilInterface interface {
|
||||||
|
}
|
||||||
|
var nI nilInterface = nil
|
||||||
|
d13, _ := base64.StdEncoding.DecodeString(ToStdBase64(nI))
|
||||||
|
assert.Equal("", string(d13))
|
||||||
|
|
||||||
|
var p unsafe.Pointer
|
||||||
|
d14, _ := base64.StdEncoding.DecodeString(ToStdBase64(p))
|
||||||
|
assert.Equal("", string(d14))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToUrlBase64(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestToUrlBase64")
|
||||||
|
|
||||||
|
r1 := ToUrlBase64("abc")
|
||||||
|
d1, _ := base64.URLEncoding.DecodeString(r1)
|
||||||
|
assert.Equal("abc", string(d1))
|
||||||
|
|
||||||
|
r2 := ToUrlBase64([]byte("abc"))
|
||||||
|
d2, _ := base64.URLEncoding.DecodeString(r2)
|
||||||
|
assert.Equal("abc", string(d2))
|
||||||
|
|
||||||
|
r3 := ToUrlBase64(123)
|
||||||
|
d3, _ := base64.URLEncoding.DecodeString(r3)
|
||||||
|
assert.Equal("123", string(d3))
|
||||||
|
|
||||||
|
r4 := ToUrlBase64(11.11)
|
||||||
|
d4, _ := base64.URLEncoding.DecodeString(r4)
|
||||||
|
assert.Equal("11.11", string(d4))
|
||||||
|
|
||||||
|
r5 := ToUrlBase64(map[string]interface{}{"name": "duke", "quantity": 1})
|
||||||
|
d5, _ := base64.URLEncoding.DecodeString(r5)
|
||||||
|
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||||
|
|
||||||
|
r6 := ToUrlBase64([]int64{7, 5, 9, 4, 23})
|
||||||
|
d6, _ := base64.URLEncoding.DecodeString(r6)
|
||||||
|
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||||
|
|
||||||
|
r7 := ToUrlBase64([]string{"7", "5", "9", "4", "23"})
|
||||||
|
d7, _ := base64.URLEncoding.DecodeString(r7)
|
||||||
|
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||||
|
|
||||||
|
r8 := ToUrlBase64(nil)
|
||||||
|
d8, _ := base64.URLEncoding.DecodeString(r8)
|
||||||
|
assert.Equal("", string(d8))
|
||||||
|
|
||||||
|
ch := make(chan int, 3)
|
||||||
|
ch <- 1
|
||||||
|
ch <- 2
|
||||||
|
r9 := ToUrlBase64(ch)
|
||||||
|
d9, _ := base64.URLEncoding.DecodeString(r9)
|
||||||
|
assert.Equal("", string(d9))
|
||||||
|
|
||||||
|
r10 := ToUrlBase64(io.EOF)
|
||||||
|
d10, _ := base64.URLEncoding.DecodeString(r10)
|
||||||
|
assert.Equal("EOF", string(d10))
|
||||||
|
|
||||||
|
r11 := ToUrlBase64(errors.New("test"))
|
||||||
|
d11, _ := base64.URLEncoding.DecodeString(r11)
|
||||||
|
assert.Equal("test", string(d11))
|
||||||
|
|
||||||
|
typedNil := (*int)(nil)
|
||||||
|
r12 := ToUrlBase64(typedNil)
|
||||||
|
d12, _ := base64.URLEncoding.DecodeString(r12)
|
||||||
|
assert.Equal("", string(d12))
|
||||||
|
|
||||||
|
type nilInterface interface {
|
||||||
|
}
|
||||||
|
var nI nilInterface = nil
|
||||||
|
d13, _ := base64.URLEncoding.DecodeString(ToUrlBase64(nI))
|
||||||
|
assert.Equal("", string(d13))
|
||||||
|
|
||||||
|
var p unsafe.Pointer
|
||||||
|
d14, _ := base64.URLEncoding.DecodeString(ToUrlBase64(p))
|
||||||
|
assert.Equal("", string(d14))
|
||||||
|
|
||||||
|
r15 := ToUrlBase64("4+3/4?=")
|
||||||
|
d15, _ := base64.URLEncoding.DecodeString(r15)
|
||||||
|
assert.Equal("4+3/4?=", string(d15))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToRawStdBase64(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestToRawStdBase64")
|
||||||
|
|
||||||
|
r1 := ToRawStdBase64("abc")
|
||||||
|
d1, _ := base64.RawStdEncoding.DecodeString(r1)
|
||||||
|
assert.Equal("abc", string(d1))
|
||||||
|
|
||||||
|
r2 := ToRawStdBase64([]byte("abc"))
|
||||||
|
d2, _ := base64.RawStdEncoding.DecodeString(r2)
|
||||||
|
assert.Equal("abc", string(d2))
|
||||||
|
|
||||||
|
r3 := ToRawStdBase64(123)
|
||||||
|
d3, _ := base64.RawStdEncoding.DecodeString(r3)
|
||||||
|
assert.Equal("123", string(d3))
|
||||||
|
|
||||||
|
r4 := ToRawStdBase64(11.11)
|
||||||
|
d4, _ := base64.RawStdEncoding.DecodeString(r4)
|
||||||
|
assert.Equal("11.11", string(d4))
|
||||||
|
|
||||||
|
r5 := ToRawStdBase64(map[string]interface{}{"name": "duke", "quantity": 1})
|
||||||
|
d5, _ := base64.RawStdEncoding.DecodeString(r5)
|
||||||
|
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||||
|
|
||||||
|
r6 := ToRawStdBase64([]int64{7, 5, 9, 4, 23})
|
||||||
|
d6, _ := base64.RawStdEncoding.DecodeString(r6)
|
||||||
|
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||||
|
|
||||||
|
r7 := ToRawStdBase64([]string{"7", "5", "9", "4", "23"})
|
||||||
|
d7, _ := base64.RawStdEncoding.DecodeString(r7)
|
||||||
|
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||||
|
|
||||||
|
r8 := ToRawStdBase64(nil)
|
||||||
|
d8, _ := base64.RawStdEncoding.DecodeString(r8)
|
||||||
|
assert.Equal("", string(d8))
|
||||||
|
|
||||||
|
ch := make(chan int, 3)
|
||||||
|
ch <- 1
|
||||||
|
ch <- 2
|
||||||
|
r9 := ToRawStdBase64(ch)
|
||||||
|
d9, _ := base64.RawStdEncoding.DecodeString(r9)
|
||||||
|
assert.Equal("", string(d9))
|
||||||
|
|
||||||
|
r10 := ToRawStdBase64(io.EOF)
|
||||||
|
d10, _ := base64.RawStdEncoding.DecodeString(r10)
|
||||||
|
assert.Equal("EOF", string(d10))
|
||||||
|
|
||||||
|
r11 := ToRawStdBase64(errors.New("test"))
|
||||||
|
d11, _ := base64.RawStdEncoding.DecodeString(r11)
|
||||||
|
assert.Equal("test", string(d11))
|
||||||
|
|
||||||
|
typedNil := (*int)(nil)
|
||||||
|
r12 := ToRawStdBase64(typedNil)
|
||||||
|
d12, _ := base64.RawStdEncoding.DecodeString(r12)
|
||||||
|
assert.Equal("", string(d12))
|
||||||
|
|
||||||
|
type nilInterface interface {
|
||||||
|
}
|
||||||
|
var nI nilInterface = nil
|
||||||
|
d13, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(nI))
|
||||||
|
assert.Equal("", string(d13))
|
||||||
|
|
||||||
|
var p unsafe.Pointer
|
||||||
|
d14, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(p))
|
||||||
|
assert.Equal("", string(d14))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToRawUrlBase64(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestToRawUrlBase64")
|
||||||
|
|
||||||
|
r1 := ToRawUrlBase64("abc")
|
||||||
|
d1, _ := base64.RawURLEncoding.DecodeString(r1)
|
||||||
|
assert.Equal("abc", string(d1))
|
||||||
|
|
||||||
|
r2 := ToRawUrlBase64([]byte("abc"))
|
||||||
|
d2, _ := base64.RawURLEncoding.DecodeString(r2)
|
||||||
|
assert.Equal("abc", string(d2))
|
||||||
|
|
||||||
|
r3 := ToRawUrlBase64(123)
|
||||||
|
d3, _ := base64.RawURLEncoding.DecodeString(r3)
|
||||||
|
assert.Equal("123", string(d3))
|
||||||
|
|
||||||
|
r4 := ToRawUrlBase64(11.11)
|
||||||
|
d4, _ := base64.RawURLEncoding.DecodeString(r4)
|
||||||
|
assert.Equal("11.11", string(d4))
|
||||||
|
|
||||||
|
r5 := ToRawUrlBase64(map[string]interface{}{"name": "duke", "quantity": 1})
|
||||||
|
d5, _ := base64.RawURLEncoding.DecodeString(r5)
|
||||||
|
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||||
|
|
||||||
|
r6 := ToRawUrlBase64([]int64{7, 5, 9, 4, 23})
|
||||||
|
d6, _ := base64.RawURLEncoding.DecodeString(r6)
|
||||||
|
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||||
|
|
||||||
|
r7 := ToRawUrlBase64([]string{"7", "5", "9", "4", "23"})
|
||||||
|
d7, _ := base64.RawURLEncoding.DecodeString(r7)
|
||||||
|
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||||
|
|
||||||
|
r8 := ToRawUrlBase64(nil)
|
||||||
|
d8, _ := base64.RawURLEncoding.DecodeString(r8)
|
||||||
|
assert.Equal("", string(d8))
|
||||||
|
|
||||||
|
ch := make(chan int, 3)
|
||||||
|
ch <- 1
|
||||||
|
ch <- 2
|
||||||
|
r9 := ToRawUrlBase64(ch)
|
||||||
|
d9, _ := base64.RawURLEncoding.DecodeString(r9)
|
||||||
|
assert.Equal("", string(d9))
|
||||||
|
|
||||||
|
r10 := ToRawUrlBase64(io.EOF)
|
||||||
|
d10, _ := base64.RawURLEncoding.DecodeString(r10)
|
||||||
|
assert.Equal("EOF", string(d10))
|
||||||
|
|
||||||
|
r11 := ToRawUrlBase64(errors.New("test"))
|
||||||
|
d11, _ := base64.RawURLEncoding.DecodeString(r11)
|
||||||
|
assert.Equal("test", string(d11))
|
||||||
|
|
||||||
|
typedNil := (*int)(nil)
|
||||||
|
r12 := ToRawUrlBase64(typedNil)
|
||||||
|
d12, _ := base64.RawURLEncoding.DecodeString(r12)
|
||||||
|
assert.Equal("", string(d12))
|
||||||
|
|
||||||
|
type nilInterface interface {
|
||||||
|
}
|
||||||
|
var nI nilInterface = nil
|
||||||
|
d13, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(nI))
|
||||||
|
assert.Equal("", string(d13))
|
||||||
|
|
||||||
|
var p unsafe.Pointer
|
||||||
|
d14, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(p))
|
||||||
|
assert.Equal("", string(d14))
|
||||||
|
|
||||||
|
r15 := ToRawUrlBase64("4+3/4?=")
|
||||||
|
d15, _ := base64.RawURLEncoding.DecodeString(r15)
|
||||||
|
assert.Equal("4+3/4?=", string(d15))
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,7 +41,10 @@ import (
|
|||||||
- [ToInterface](#ToInterface)
|
- [ToInterface](#ToInterface)
|
||||||
- [Utf8ToGbk](#Utf8ToGbk)
|
- [Utf8ToGbk](#Utf8ToGbk)
|
||||||
- [GbkToUtf8](#GbkToUtf8)
|
- [GbkToUtf8](#GbkToUtf8)
|
||||||
- [GbkToUtf8](#GbkToUtf8)
|
- [ToStdBase64](#ToStdBase64)
|
||||||
|
- [ToUrlBase64](#ToUrlBase64)
|
||||||
|
- [ToRawStdBase64](#ToRawStdBase64)
|
||||||
|
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -741,4 +744,273 @@ func main() {
|
|||||||
// true
|
// true
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToStdBase64">ToStdBase64</span>
|
||||||
|
|
||||||
|
<p>Convert a value to a string encoded in standard Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToStdBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
afterEncode := convertor.ToStdBase64(nil)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
afterEncode = convertor.ToStdBase64("")
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToStdBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToStdBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToStdBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToStdBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToStdBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToStdBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToStdBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// aGVsbG8=
|
||||||
|
// aGVsbG8=
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||||
|
// MTIzLjQ1Ng==
|
||||||
|
// dHJ1ZQ==
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToUrlBase64">ToUrlBase64</span>
|
||||||
|
|
||||||
|
<p>Convert a value to a string encoded in url Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToUrlBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
afterEncode := convertor.ToUrlBase64(nil)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToUrlBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToUrlBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToUrlBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToUrlBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToUrlBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToUrlBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToUrlBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// aGVsbG8=
|
||||||
|
// aGVsbG8=
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||||
|
// MTIzLjQ1Ng==
|
||||||
|
// dHJ1ZQ==
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToRawStdBase64">ToRawStdBase64</span>
|
||||||
|
|
||||||
|
<p>Convert a value to a string encoded in raw standard Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToRawStdBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToRawStdBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToRawStdBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToRawStdBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToRawStdBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToRawStdBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToRawStdBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToRawStdBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// aGVsbG8
|
||||||
|
// aGVsbG8
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||||
|
// MTIzLjQ1Ng
|
||||||
|
// dHJ1ZQ
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToRawUrlBase64">ToRawUrlBase64</span>
|
||||||
|
|
||||||
|
<p> Convert a value to a string encoded in raw url Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON-formatted string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToRawUrlBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToRawStdBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToRawStdBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// aGVsbG8
|
||||||
|
// aGVsbG8
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||||
|
// MTIzLjQ1Ng
|
||||||
|
// dHJ1ZQ
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -41,6 +41,10 @@ import (
|
|||||||
- [ToInterface](#ToInterface)
|
- [ToInterface](#ToInterface)
|
||||||
- [Utf8ToGbk](#Utf8ToGbk)
|
- [Utf8ToGbk](#Utf8ToGbk)
|
||||||
- [GbkToUtf8](#GbkToUtf8)
|
- [GbkToUtf8](#GbkToUtf8)
|
||||||
|
- [ToStdBase64](#ToStdBase64)
|
||||||
|
- [ToUrlBase64](#ToUrlBase64)
|
||||||
|
- [ToRawStdBase64](#ToRawStdBase64)
|
||||||
|
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -740,4 +744,273 @@ func main() {
|
|||||||
// true
|
// true
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToStdBase64">ToStdBase64</span>
|
||||||
|
|
||||||
|
<p>将值转换为StdBase64编码的字符串。error类型的数据也会把error的原因进行编码,复杂的结构会转为JSON格式的字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToStdBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
afterEncode := convertor.ToStdBase64(nil)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
afterEncode = convertor.ToStdBase64("")
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToStdBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToStdBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToStdBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToStdBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToStdBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToStdBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToStdBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// aGVsbG8=
|
||||||
|
// aGVsbG8=
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||||
|
// MTIzLjQ1Ng==
|
||||||
|
// dHJ1ZQ==
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToUrlBase64">ToUrlBase64</span>
|
||||||
|
|
||||||
|
<p>值转换为 ToUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToUrlBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
afterEncode := convertor.ToUrlBase64(nil)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToUrlBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToUrlBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToUrlBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToUrlBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToUrlBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToUrlBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToUrlBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// aGVsbG8=
|
||||||
|
// aGVsbG8=
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||||
|
// MTIzLjQ1Ng==
|
||||||
|
// dHJ1ZQ==
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToRawStdBase64">ToRawStdBase64</span>
|
||||||
|
|
||||||
|
<p>值转换为 ToRawStdBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToRawStdBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToRawStdBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToRawStdBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToRawStdBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToRawStdBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToRawStdBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToRawStdBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToRawStdBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// aGVsbG8
|
||||||
|
// aGVsbG8
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||||
|
// MTIzLjQ1Ng
|
||||||
|
// dHJ1ZQ
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToRawUrlBase64">ToRawUrlBase64</span>
|
||||||
|
|
||||||
|
<p>值转换为 ToRawUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToRawUrlBase64(value any) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
stringVal := "hello"
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(stringVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
byteSliceVal := []byte("hello")
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(byteSliceVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
intVal := 123
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(intVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{"hello", 3}}
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(mapVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
floatVal := 123.456
|
||||||
|
afterEncode = convertor.ToRawUrlBase64(floatVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
boolVal := true
|
||||||
|
afterEncode = convertor.ToRawStdBase64(boolVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
errVal := errors.New("err")
|
||||||
|
afterEncode = convertor.ToRawStdBase64(errVal)
|
||||||
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// aGVsbG8
|
||||||
|
// aGVsbG8
|
||||||
|
// MTIz
|
||||||
|
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||||
|
// MTIzLjQ1Ng
|
||||||
|
// dHJ1ZQ
|
||||||
|
// ZXJy
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -45,6 +45,7 @@ import (
|
|||||||
- [Sha](#Sha)
|
- [Sha](#Sha)
|
||||||
- [ReadCsvFile](#ReadCsvFile)
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
- [WriteCsvFile](#WriteCsvFile)
|
- [WriteCsvFile](#WriteCsvFile)
|
||||||
|
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||||
- [WriteStringToFile](#WriteStringToFile)
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
- [WriteBytesToFile](#WriteBytesToFile)
|
- [WriteBytesToFile](#WriteBytesToFile)
|
||||||
- [ReadFile](#ReadFile)
|
- [ReadFile](#ReadFile)
|
||||||
@@ -694,6 +695,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="WriteCsvFile">WriteCsvFile</span>
|
### <span id="WriteCsvFile">WriteCsvFile</span>
|
||||||
|
|
||||||
<p>Write content to target csv file.</p>
|
<p>Write content to target csv file.</p>
|
||||||
@@ -731,6 +733,60 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="WriteMapsToCsv">WriteMapsToCsv</span>
|
||||||
|
|
||||||
|
<p>write slice of map to csv file.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
// filepath: path of the CSV file.
|
||||||
|
// records: slice of maps to be written. the value of map should be basic type. The maps will be sorted by key in alphabeta order, then be written into csv file.
|
||||||
|
// appendToExistingFile: If true, data will be appended to the file if it exists.
|
||||||
|
// delimiter: Delimiter to use in the CSV file.
|
||||||
|
// headers: order of the csv column headers, needs to be consistent with the key of the map.
|
||||||
|
func WriteMapsToCsv(filepath string, records []map[string]interface{}, appendToExistingFile bool, delimiter rune, headers ...[]string) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fpath := "./test.csv"
|
||||||
|
fileutil.CreateFile(fpath)
|
||||||
|
|
||||||
|
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
records := []map[string]interface{}{
|
||||||
|
{"Name": "Lili", "Age": "22", "Gender": "female"},
|
||||||
|
{"Name": "Jim", "Age": "21", "Gender": "male"},
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := []string{"Name", "Age", "Gender"}
|
||||||
|
err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';', headers)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := fileutil.ReadCsvFile(csvFilePath, ';')
|
||||||
|
|
||||||
|
fmt.Println(content)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||||
|
|
||||||
<p>Writes bytes to target file.</p>
|
<p>Writes bytes to target file.</p>
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import (
|
|||||||
- [Sha](#Sha)
|
- [Sha](#Sha)
|
||||||
- [ReadCsvFile](#ReadCsvFile)
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
- [WriteCsvFile](#WriteCsvFile)
|
- [WriteCsvFile](#WriteCsvFile)
|
||||||
|
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||||
- [WriteStringToFile](#WriteStringToFile)
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
- [WriteBytesToFile](#WriteBytesToFile)
|
- [WriteBytesToFile](#WriteBytesToFile)
|
||||||
- [ReadFile](#ReadFile)
|
- [ReadFile](#ReadFile)
|
||||||
@@ -731,6 +732,59 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="WriteMapsToCsv">WriteMapsToCsv</span>
|
||||||
|
|
||||||
|
<p>将map切片写入csv文件中。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
// filepath: CSV文件路径。
|
||||||
|
// records: 写入文件的map切片。map值必须为基本类型。会以map键的字母顺序写入。
|
||||||
|
// appendToExistingFile: 是否为追加写模式。
|
||||||
|
// delimiter: CSV文件分割符。
|
||||||
|
// headers: CSV文件表头顺序(需要与map key保持一致),不指定时按字母排序。
|
||||||
|
func WriteMapsToCsv(filepath string, records []map[string]interface{}, appendToExistingFile bool, delimiter rune, headers ...[]string) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fpath := "./test.csv"
|
||||||
|
fileutil.CreateFile(fpath)
|
||||||
|
|
||||||
|
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
records := []map[string]interface{}{
|
||||||
|
{"Name": "Lili", "Age": "22", "Gender": "female"},
|
||||||
|
{"Name": "Jim", "Age": "21", "Gender": "male"},
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := []string{"Name", "Age", "Gender"}
|
||||||
|
err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';', headers)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := fileutil.ReadCsvFile(csvFilePath, ';')
|
||||||
|
|
||||||
|
fmt.Println(content)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||||
|
|
||||||
<p>将bytes写入文件。</p>
|
<p>将bytes写入文件。</p>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import (
|
|||||||
- [HideString](#HideString)
|
- [HideString](#HideString)
|
||||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||||
- [SubInBetween](#SubInBetween)
|
- [SubInBetween](#SubInBetween)
|
||||||
|
- [HammingDistance](#HammingDistance)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -1307,4 +1308,36 @@ func main() {
|
|||||||
// abc
|
// abc
|
||||||
// bc
|
// bc
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="HammingDistance">HammingDistance</span>
|
||||||
|
|
||||||
|
<p>HammingDistance calculates the Hamming distance between two strings. The Hamming distance is the number of positions at which the corresponding symbols are different.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
HammingDistance(a, b string) (int, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
result1, _ := strutil.HammingDistance("de", "de")
|
||||||
|
result2, _ := strutil.HammingDistance("a", "d")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 0
|
||||||
|
// 1
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -59,6 +59,7 @@ import (
|
|||||||
- [HideString](#HideString)
|
- [HideString](#HideString)
|
||||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||||
- [SubInBetween](#SubInBetween)
|
- [SubInBetween](#SubInBetween)
|
||||||
|
- [HammingDistance](#HammingDistance)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -1341,3 +1342,35 @@ func main() {
|
|||||||
// bc
|
// bc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HammingDistance">HammingDistance</span>
|
||||||
|
|
||||||
|
<p>计算两个字符串之间的汉明距离。汉明距离是指对应符号不同的位置数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
HammingDistance(a, b string) (int, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
result1, _ := strutil.HammingDistance("de", "de")
|
||||||
|
result2, _ := strutil.HammingDistance("a", "d")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 0
|
||||||
|
// 1
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -17,12 +17,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/validator"
|
"github.com/duke-git/lancet/validator"
|
||||||
)
|
)
|
||||||
@@ -599,8 +601,7 @@ func escapeCSVField(field string, delimiter rune) string {
|
|||||||
// appendToExistingFile: If true, data will be appended to the file if it exists.
|
// appendToExistingFile: If true, data will be appended to the file if it exists.
|
||||||
// delimiter: Delimiter to use in the CSV file.
|
// delimiter: Delimiter to use in the CSV file.
|
||||||
// headers: order of the csv column headers, needs to be consistent with the key of the map.
|
// headers: order of the csv column headers, needs to be consistent with the key of the map.
|
||||||
func WriteMapsToCsv(filepath string, records []map[string]interface{}, appendToExistingFile bool, delimiter rune,
|
func WriteMapsToCsv(filepath string, records []map[string]interface{}, appendToExistingFile bool, delimiter rune, headers ...[]string) error {
|
||||||
headers ...[]string) error {
|
|
||||||
for _, record := range records {
|
for _, record := range records {
|
||||||
for _, value := range record {
|
for _, value := range record {
|
||||||
if !isCsvSupportedType(value) {
|
if !isCsvSupportedType(value) {
|
||||||
@@ -695,3 +696,89 @@ func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) {
|
|||||||
return nil, func() {}, errors.New("unknown file type")
|
return nil, func() {}, errors.New("unknown file type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChunkRead 从文件的指定偏移读取块并返回块内所有行
|
||||||
|
func ChunkRead(f *os.File, offset int64, size int, bufPool *sync.Pool) []string {
|
||||||
|
buf := bufPool.Get().([]byte)[:size] // 从Pool获取缓冲区并调整大小
|
||||||
|
n, err := f.ReadAt(buf, offset) // 从指定偏移读取数据到缓冲区
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
buf = buf[:n] // 调整切片以匹配实际读取的字节数
|
||||||
|
|
||||||
|
var lines []string
|
||||||
|
var lineStart int
|
||||||
|
for i, b := range buf {
|
||||||
|
if b == '\n' {
|
||||||
|
line := string(buf[lineStart:i]) // 不包括换行符
|
||||||
|
lines = append(lines, line)
|
||||||
|
lineStart = i + 1 // 设置下一行的开始
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if lineStart < len(buf) { // 处理块末尾的行
|
||||||
|
line := string(buf[lineStart:])
|
||||||
|
lines = append(lines, line)
|
||||||
|
}
|
||||||
|
bufPool.Put(buf) // 读取完成后,将缓冲区放回Pool
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
// 并行读取文件并将每个块的行发送到指定通道
|
||||||
|
// filePath 文件路径
|
||||||
|
// ChunkSizeMB 分块的大小(单位MB,设置为0时使用默认100MB),设置过大反而不利,视情调整
|
||||||
|
// MaxGoroutine 并发读取分块的数量,设置为0时使用CPU核心数
|
||||||
|
// linesCh用于接收返回结果的通道。
|
||||||
|
func ParallelChunkRead(filePath string, linesCh chan<- []string, ChunkSizeMB, MaxGoroutine int) {
|
||||||
|
if ChunkSizeMB == 0 {
|
||||||
|
ChunkSizeMB = 100
|
||||||
|
}
|
||||||
|
ChunkSize := ChunkSizeMB * 1024 * 1024
|
||||||
|
// 内存复用
|
||||||
|
bufPool := sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return make([]byte, 0, ChunkSize)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if MaxGoroutine == 0 {
|
||||||
|
MaxGoroutine = runtime.NumCPU() // 设置为0时使用CPU核心数
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to open file: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
info, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to get file info: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
chunkOffsetCh := make(chan int64, MaxGoroutine)
|
||||||
|
|
||||||
|
// 分配工作
|
||||||
|
go func() {
|
||||||
|
for i := int64(0); i < info.Size(); i += int64(ChunkSize) {
|
||||||
|
chunkOffsetCh <- i
|
||||||
|
}
|
||||||
|
close(chunkOffsetCh)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 启动工作协程
|
||||||
|
for i := 0; i < MaxGoroutine; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
for chunkOffset := range chunkOffsetCh {
|
||||||
|
linesCh <- ChunkRead(f, chunkOffset, ChunkSize, &bufPool)
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有解析完成后关闭行通道
|
||||||
|
wg.Wait()
|
||||||
|
close(linesCh)
|
||||||
|
}
|
||||||
|
|||||||
260
random/random.go
260
random/random.go
@@ -8,22 +8,30 @@ import (
|
|||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NUMERAL = "0123456789"
|
MaximumCapacity = math.MaxInt>>1 + 1
|
||||||
LOWER_LETTERS = "abcdefghijklmnopqrstuvwxyz"
|
Numeral = "0123456789"
|
||||||
UPPER_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
|
||||||
LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
SymbolChars = "!@#$%^&*()_+-=[]{}|;':\",./<>?"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var rn = rand.NewSource(time.Now().UnixNano())
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandInt generate random int between min and max, maybe min, not be max
|
// RandInt generate random int between [min, max).
|
||||||
func RandInt(min, max int) int {
|
func RandInt(min, max int) int {
|
||||||
if min == max {
|
if min == max {
|
||||||
return min
|
return min
|
||||||
@@ -36,7 +44,23 @@ func RandInt(min, max int) int {
|
|||||||
return rand.Intn(max-min) + min
|
return rand.Intn(max-min) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandBytes generate random byte slice
|
// RandFloat generate random float64 number between [min, max) with specific precision.
|
||||||
|
func RandFloat(min, max float64, precision int) float64 {
|
||||||
|
if min == max {
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
if max < min {
|
||||||
|
min, max = max, min
|
||||||
|
}
|
||||||
|
|
||||||
|
n := rand.Float64()*(max-min) + min
|
||||||
|
|
||||||
|
return mathutil.RoundToFloat(n, precision)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandBytes generate random byte slice.
|
||||||
|
// Play: https://go.dev/play/p/EkiLESeXf8d
|
||||||
func RandBytes(length int) []byte {
|
func RandBytes(length int) []byte {
|
||||||
if length < 1 {
|
if length < 1 {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
@@ -46,48 +70,99 @@ func RandBytes(length int) []byte {
|
|||||||
if _, err := io.ReadFull(crand.Reader, b); err != nil {
|
if _, err := io.ReadFull(crand.Reader, b); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandString generate random string
|
// RandString generate random alpha string of specified length.
|
||||||
func RandString(length int) string {
|
func RandString(length int) string {
|
||||||
return random(LETTERS, length)
|
return random(Letters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandUpper generate a random upper case string
|
// RandUpper generate a random upper case string of specified length.
|
||||||
func RandUpper(length int) string {
|
func RandUpper(length int) string {
|
||||||
return random(UPPER_LETTERS, length)
|
return random(UpperLetters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandLower generate a random lower case string
|
// RandLower generate a random lower case string of specified length.
|
||||||
func RandLower(length int) string {
|
func RandLower(length int) string {
|
||||||
return random(LOWER_LETTERS, length)
|
return random(LowwerLetters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandNumeral generate a random numeral string
|
// RandNumeral generate a random numeral string of specified length.
|
||||||
func RandNumeral(length int) string {
|
func RandNumeral(length int) string {
|
||||||
return random(NUMERAL, length)
|
return random(Numeral, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandNumeralOrLetter generate a random numeral or letter string
|
// RandNumeralOrLetter generate a random numeral or alpha string of specified length.
|
||||||
func RandNumeralOrLetter(length int) string {
|
func RandNumeralOrLetter(length int) string {
|
||||||
return random(NUMERAL+LETTERS, length)
|
return random(Numeral+Letters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// random generate a random string based on given string range
|
// RandSymbolChar generate a random symbol char of specified length.
|
||||||
func random(s string, length int) string {
|
// symbol chars: !@#$%^&*()_+-=[]{}|;':\",./<>?.
|
||||||
b := make([]byte, length)
|
func RandSymbolChar(length int) string {
|
||||||
|
return random(SymbolChars, length)
|
||||||
|
}
|
||||||
|
|
||||||
// fix: https://github.com/duke-git/lancet/issues/75
|
// nearestPowerOfTwo 返回一个大于等于cap的最近的2的整数次幂,参考java8的hashmap的tableSizeFor函数
|
||||||
// r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
func nearestPowerOfTwo(cap int) int {
|
||||||
|
n := cap - 1
|
||||||
for i := range b {
|
n |= n >> 1
|
||||||
b[i] = s[rand.Int63()%int64(len(s))]
|
n |= n >> 2
|
||||||
|
n |= n >> 4
|
||||||
|
n |= n >> 8
|
||||||
|
n |= n >> 16
|
||||||
|
if n < 0 {
|
||||||
|
return 1
|
||||||
|
} else if n >= MaximumCapacity {
|
||||||
|
return MaximumCapacity
|
||||||
}
|
}
|
||||||
return string(b)
|
return n + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// UUIdV4 generate a random UUID of version 4 according to RFC 4122
|
// random generate a random string based on given string range.
|
||||||
|
func random(s string, length int) string {
|
||||||
|
// 仿照strings.Builder
|
||||||
|
// 创建一个长度为 length 的字节切片
|
||||||
|
bytes := make([]byte, length)
|
||||||
|
strLength := len(s)
|
||||||
|
if strLength <= 0 {
|
||||||
|
return ""
|
||||||
|
} else if strLength == 1 {
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
bytes[i] = s[0]
|
||||||
|
}
|
||||||
|
return *(*string)(unsafe.Pointer(&bytes))
|
||||||
|
}
|
||||||
|
// s的字符需要使用多少个比特位数才能表示完
|
||||||
|
// letterIdBits := int(math.Ceil(math.Log2(strLength))),下面比上面的代码快
|
||||||
|
letterIdBits := int(math.Log2(float64(nearestPowerOfTwo(strLength))))
|
||||||
|
// 最大的字母id掩码
|
||||||
|
var letterIdMask int64 = 1<<letterIdBits - 1
|
||||||
|
// 可用次数的最大值
|
||||||
|
letterIdMax := 63 / letterIdBits
|
||||||
|
// 循环生成随机字符串
|
||||||
|
for i, cache, remain := length-1, rn.Int63(), letterIdMax; i >= 0; {
|
||||||
|
// 检查随机数生成器是否用尽所有随机数
|
||||||
|
if remain == 0 {
|
||||||
|
cache, remain = rn.Int63(), letterIdMax
|
||||||
|
}
|
||||||
|
// 从可用字符的字符串中随机选择一个字符
|
||||||
|
if idx := int(cache & letterIdMask); idx < strLength {
|
||||||
|
bytes[i] = s[idx]
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
// 右移比特位数,为下次选择字符做准备
|
||||||
|
cache >>= letterIdBits
|
||||||
|
remain--
|
||||||
|
}
|
||||||
|
// 仿照strings.Builder用unsafe包返回一个字符串,避免拷贝
|
||||||
|
// 将字节切片转换为字符串并返回
|
||||||
|
return *(*string)(unsafe.Pointer(&bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UUIdV4 generate a random UUID of version 4 according to RFC 4122.
|
||||||
func UUIdV4() (string, error) {
|
func UUIdV4() (string, error) {
|
||||||
uuid := make([]byte, 16)
|
uuid := make([]byte, 16)
|
||||||
|
|
||||||
@@ -125,3 +200,136 @@ func RandUniqueIntSlice(n, min, max int) []int {
|
|||||||
|
|
||||||
return nums
|
return nums
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandFloats generate a slice of random float64 numbers of length n that do not repeat.
|
||||||
|
func RandFloats(n int, min, max float64, precision int) []float64 {
|
||||||
|
nums := make([]float64, n)
|
||||||
|
used := make(map[float64]struct{}, n)
|
||||||
|
for i := 0; i < n; {
|
||||||
|
r := RandFloat(min, max, precision)
|
||||||
|
if _, use := used[r]; use {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
used[r] = struct{}{}
|
||||||
|
nums[i] = r
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return nums
|
||||||
|
}
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// NUMERAL = "0123456789"
|
||||||
|
// LOWER_LETTERS = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
// UPPER_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
// LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
// )
|
||||||
|
|
||||||
|
// var rn = rand.NewSource(time.Now().UnixNano())
|
||||||
|
|
||||||
|
// func init() {
|
||||||
|
// rand.Seed(time.Now().UnixNano())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandInt generate random int between min and max, maybe min, not be max
|
||||||
|
// func RandInt(min, max int) int {
|
||||||
|
// if min == max {
|
||||||
|
// return min
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if max < min {
|
||||||
|
// min, max = max, min
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return rand.Intn(max-min) + min
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandBytes generate random byte slice
|
||||||
|
// func RandBytes(length int) []byte {
|
||||||
|
// if length < 1 {
|
||||||
|
// return []byte{}
|
||||||
|
// }
|
||||||
|
// b := make([]byte, length)
|
||||||
|
|
||||||
|
// if _, err := io.ReadFull(crand.Reader, b); err != nil {
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// return b
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandString generate random string
|
||||||
|
// func RandString(length int) string {
|
||||||
|
// return random(LETTERS, length)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandUpper generate a random upper case string
|
||||||
|
// func RandUpper(length int) string {
|
||||||
|
// return random(UPPER_LETTERS, length)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandLower generate a random lower case string
|
||||||
|
// func RandLower(length int) string {
|
||||||
|
// return random(LOWER_LETTERS, length)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandNumeral generate a random numeral string
|
||||||
|
// func RandNumeral(length int) string {
|
||||||
|
// return random(NUMERAL, length)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // RandNumeralOrLetter generate a random numeral or letter string
|
||||||
|
// func RandNumeralOrLetter(length int) string {
|
||||||
|
// return random(NUMERAL+LETTERS, length)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // random generate a random string based on given string range
|
||||||
|
// func random(s string, length int) string {
|
||||||
|
// b := make([]byte, length)
|
||||||
|
|
||||||
|
// // fix: https://github.com/duke-git/lancet/issues/75
|
||||||
|
// // r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
// for i := range b {
|
||||||
|
// b[i] = s[rand.Int63()%int64(len(s))]
|
||||||
|
// }
|
||||||
|
// return string(b)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // UUIdV4 generate a random UUID of version 4 according to RFC 4122
|
||||||
|
// func UUIdV4() (string, error) {
|
||||||
|
// uuid := make([]byte, 16)
|
||||||
|
|
||||||
|
// n, err := io.ReadFull(crand.Reader, uuid)
|
||||||
|
// if n != len(uuid) || err != nil {
|
||||||
|
// return "", err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uuid[8] = uuid[8]&^0xc0 | 0x80
|
||||||
|
// uuid[6] = uuid[6]&^0xf0 | 0x40
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// }
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package strutil
|
package strutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
@@ -537,3 +538,24 @@ func SubInBetween(str string, start string, end string) string {
|
|||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HammingDistance calculates the Hamming distance between two strings.
|
||||||
|
// The Hamming distance is the number of positions at which the corresponding symbols are different.
|
||||||
|
// This func returns an error if the input strings are of unequal lengths.
|
||||||
|
func HammingDistance(a, b string) (int, error) {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return -1, errors.New("a length and b length are unequal")
|
||||||
|
}
|
||||||
|
|
||||||
|
ar := []rune(a)
|
||||||
|
br := []rune(b)
|
||||||
|
|
||||||
|
var distance int
|
||||||
|
for i, codepoint := range ar {
|
||||||
|
if codepoint != br[i] {
|
||||||
|
distance++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return distance, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -224,6 +224,29 @@ func TestBeforeLast(t *testing.T) {
|
|||||||
assert.NotEqual("github.com/", BeforeLast("github.com/test/test/lancet", "test"))
|
assert.NotEqual("github.com/", BeforeLast("github.com/test/test/lancet", "test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHammingDistance(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "HammingDistance")
|
||||||
|
|
||||||
|
hd := func(a, b string) int {
|
||||||
|
c, _ := HammingDistance(a, b)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(0, hd(" ", " "))
|
||||||
|
assert.Equal(1, hd(" ", "c"))
|
||||||
|
assert.Equal(1, hd("a", "d"))
|
||||||
|
assert.Equal(1, hd("a", " "))
|
||||||
|
assert.Equal(1, hd("a", "f"))
|
||||||
|
|
||||||
|
assert.Equal(0, hd("", ""))
|
||||||
|
assert.Equal(-1, hd("abc", "ab"))
|
||||||
|
assert.Equal(3, hd("abc", "def"))
|
||||||
|
assert.Equal(-1, hd("kitten", "sitting"))
|
||||||
|
assert.Equal(1, hd("ö", "ü"))
|
||||||
|
assert.Equal(0, hd("日本語", "日本語"))
|
||||||
|
assert.Equal(3, hd("日本語", "語日本"))
|
||||||
|
}
|
||||||
|
|
||||||
func TestAfter(t *testing.T) {
|
func TestAfter(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestAfter")
|
assert := internal.NewAssert(t, "TestAfter")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user