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

Compare commits

...

2 Commits

Author SHA1 Message Date
dudaodong
27667f8b3a fix: fix bugs in test 2025-04-21 15:08:16 +08:00
dudaodong
0b5dc86d70 refactor: refact some strutil functions 2025-04-21 14:07:52 +08:00
8 changed files with 140 additions and 140 deletions

View File

@@ -1,51 +1,51 @@
-----BEGIN rsa private key-----
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
-----END rsa private key-----

View File

@@ -1,14 +1,14 @@
-----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtKEukXkdl8ggX5I5Us0M
BcsrFzbTgwOn8u72IhJzruvsHcjlGGF5L1eXh3C0zbcoWq+Bxf8NnXvSXASZlZHT
iSVLFerxFw2LwTNcyfOz/Y/wIbtrYu4ZdttLKdJS607UvnZ57O7SQni5rxYAP5j+
veKHEJgAO7Sn0lEEWwkeudsfVrQmQx6JHYtCtx78p2GHXPj9wXWHxWHKMkczKtmB
FDLlYocPhQfWzx87sYKjGmTMGzVddsrllAqVozlxXTQndOdozx8BWHSBiYWguOvW
iYjvryrIf0B7wn4wt3o2Yre3w4BkwrTUE73JWG2q1NLuPoT27m7WcdVFGGcKAygA
dMMSwS530v8tnAw876/w1SfUmtkIcqknysMjsvxHx1fbEfkl3b0yBnzcUrT1qxzm
NEqJSQXBtFYFyGgyeL8J1ul/T5hPSNz0we5TO/xRkX5Y1HNJ+a2r8EnE1PU8zgQG
BxYSIub4ajSUccyn5yHQ/k2FlsolZiu/UzfnzMgdg55svgf5x1ntKYBoVHuYe84A
b3WRAeVlUi0OphvFlBzfIQvrG2sRbiPZRZZ0E8kBH94zPmrFmyX+7TwlSqVHtNFc
+Ynz+hrHcd4z6N7fIb+D1gSYuukkcRqr4ANO0ugZk0YYKaWDf86H7OZOXna8ObIA
i+3gx+Wcp1lm7Ffk9sn+dGkCAwEAAQ==
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtXr+2FbR6Prdf9U0gfq2
OJbTD82m84bbdeyfsakabYp8Haw6mZW6ebRNPJvQ87H6DbA55hK1E7y6m+wjvbUo
pnkGh75Cp04CoQvaU8Rs7MrQcJ2Zz1VRRgugmqwJMWE/FC5eGXvvpDjF2h2lqThK
ZTKcvhqfZ3dNX+6v4EQ4BbjSGKdzpyexzR1WSV9IzZYRHMk8jCoEHOx9ItEzoToB
f9yAq0DhufylqSRbjKLhR7A3IiRSLVNfu0Sz5cfNlS7eUA060QS8AV9BgGNTkl75
aj8BCOmoHIW85SsSZvdQWYwmlM76Jn+tfNNnY7Uuqtz2gI1odcy1nXembXWJryxu
YCkSAwpU8UNIQpZeKwBnBxaf0pj3W1m3UzEqhGkkCrKq8LkNSGZSkhT+bI65fNx2
LZ7lS165szkeyqS8aikxcBpdx7Z/bqbFFuI42KX+IpXAJCAtvsQ0XXinr83MLcY/
I2Ic/5Sgz7txfZsKKwKt48ETS9BjxGPWo1Dd5YjM8ZJWJv2Rf0mwVjUMClFSNBm8
x+aWGVIKjpocN/plpEZmFrWdPcWM4ZH3qGCEnVVkqPvqClahNSQXsM4W7msYts1I
Uq31tjBSV5bL6l2K8jFJa4PRYdzh1vHhDOAYTpgDkQbNaoDlDS2o/0TkAGUfXWJt
R3D35wRJzoa7bCMt5BuFE3sCAwEAAQ==
-----END rsa public key-----

View File

@@ -15,7 +15,6 @@ func TestSinglyLink_InsertAtFirst(t *testing.T) {
link.InsertAtHead(1)
link.InsertAtHead(2)
link.InsertAtHead(3)
link.Print()
expected := []int{3, 2, 1}
values := link.Values()
@@ -32,7 +31,6 @@ func TestSinglyLink_InsertAtTail(t *testing.T) {
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
@@ -77,7 +75,6 @@ func TestSinglyLink_DeleteAtHead(t *testing.T) {
link.InsertAtTail(4)
link.DeleteAtHead()
link.Print()
expected := []int{2, 3, 4}
values := link.Values()

View File

@@ -2,6 +2,7 @@ package eventbus
import (
"fmt"
"sort"
"sync"
"time"
)
@@ -224,6 +225,7 @@ func ExampleEventBus_GetEvents() {
eb.Subscribe("event2", func(eventData int) {}, false, 0, nil)
events := eb.GetEvents()
sort.Strings(events)
for _, event := range events {
fmt.Println(event)

View File

@@ -1,6 +1,7 @@
package eventbus
import (
"sort"
"sync"
"testing"
"time"
@@ -213,7 +214,8 @@ func TestEventBus_GetEvents(t *testing.T) {
eb.Subscribe("event2", func(eventData int) {}, false, 0, nil)
events := eb.GetEvents()
sort.Strings(events)
assert.Equal(2, len(events))
assert.EqualValues([]string{"event1", "event2"}, events)
assert.Equal([]string{"event1", "event2"}, events)
}

View File

@@ -3,7 +3,6 @@ package netutil
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
@@ -27,8 +26,8 @@ func TestHttpGet(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestHttpPost(t *testing.T) {
@@ -49,8 +48,8 @@ func TestHttpPost(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestHttpPostFormData(t *testing.T) {
@@ -69,8 +68,8 @@ func TestHttpPostFormData(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestHttpPut(t *testing.T) {
@@ -92,8 +91,8 @@ func TestHttpPut(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestHttpPatch(t *testing.T) {
@@ -115,8 +114,8 @@ func TestHttpPatch(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestHttpDelete(t *testing.T) {
@@ -127,8 +126,8 @@ func TestHttpDelete(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestConvertMapToQueryString(t *testing.T) {
@@ -229,8 +228,8 @@ func TestHttpClent_Post(t *testing.T) {
return
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
defer resp.Body.Close()
t.Log("response status:", resp.StatusCode)
}
func TestStructToUrlValues(t *testing.T) {

View File

@@ -37,16 +37,17 @@ func CamelCase(s string) string {
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
// Play: https://go.dev/play/p/2OAjgbmAqHZ
func Capitalize(s string) string {
result := make([]rune, len(s))
for i, v := range s {
if i == 0 {
result[i] = unicode.ToUpper(v)
} else {
result[i] = unicode.ToLower(v)
}
if s == "" {
return s
}
return string(result)
runes := []rune(s)
runes[0] = unicode.ToUpper(runes[0])
for i := 1; i < len(runes); i++ {
runes[i] = unicode.ToLower(runes[i])
}
return string(runes)
}
// UpperFirst converts the first character of string to upper case.
@@ -127,49 +128,57 @@ func UpperSnakeCase(s string) string {
// Before returns the substring of the source string up to the first occurrence of the specified string.
// Play: https://go.dev/play/p/JAWTZDS4F5w
func Before(s, char string) string {
i := strings.Index(s, char)
if s == "" || char == "" || i == -1 {
if char == "" {
return s
}
return s[0:i]
if i := strings.Index(s, char); i >= 0 {
return s[:i]
}
return s
}
// BeforeLast returns the substring of the source string up to the last occurrence of the specified string.
// Play: https://go.dev/play/p/pJfXXAoG_Te
func BeforeLast(s, char string) string {
i := strings.LastIndex(s, char)
if s == "" || char == "" || i == -1 {
if char == "" {
return s
}
return s[0:i]
if i := strings.LastIndex(s, char); i >= 0 {
return s[:i]
}
return s
}
// After returns the substring after the first occurrence of a specified string in the source string.
// Play: https://go.dev/play/p/RbCOQqCDA7m
func After(s, char string) string {
i := strings.Index(s, char)
if s == "" || char == "" || i == -1 {
if char == "" {
return s
}
return s[i+len(char):]
if i := strings.Index(s, char); i >= 0 {
return s[i+len(char):]
}
return s
}
// AfterLast returns the substring after the last occurrence of a specified string in the source string.
// Play: https://go.dev/play/p/1TegARrb8Yn
func AfterLast(s, char string) string {
i := strings.LastIndex(s, char)
if s == "" || char == "" || i == -1 {
if char == "" {
return s
}
return s[i+len(char):]
if i := strings.LastIndex(s, char); i >= 0 {
return s[i+len(char):]
}
return s
}
// IsString check if the value data type is string or not.
@@ -213,20 +222,15 @@ func Wrap(str string, wrapWith string) string {
// Unwrap a given string from anther string. will change source string.
// Play: https://go.dev/play/p/Ec2q4BzCpG-
func Unwrap(str string, wrapToken string) string {
if str == "" || wrapToken == "" {
if wrapToken == "" || !strings.HasPrefix(str, wrapToken) || !strings.HasSuffix(str, wrapToken) {
return str
}
firstIndex := strings.Index(str, wrapToken)
lastIndex := strings.LastIndex(str, wrapToken)
if firstIndex == 0 && lastIndex > 0 && lastIndex <= len(str)-1 {
if len(wrapToken) <= lastIndex {
str = str[len(wrapToken):lastIndex]
}
if len(str) < 2*len(wrapToken) {
return str
}
return str
return str[len(wrapToken) : len(str)-len(wrapToken)]
}
// SplitEx split a given string which can control the result slice contains empty string or not.
@@ -286,22 +290,21 @@ func Substring(s string, offset int, length uint) string {
size := len(rs)
if offset < 0 {
offset = size + offset
if offset < 0 {
offset = 0
}
offset += size
}
if offset < 0 {
offset = 0
}
if offset > size {
return ""
}
if length > uint(size)-uint(offset) {
length = uint(size - offset)
end := offset + int(length)
if end > size {
end = size
}
str := string(rs[offset : offset+int(length)])
return strings.Replace(str, "\x00", "", -1)
return strings.ReplaceAll(string(rs[offset:end]), "\x00", "")
}
// SplitWords splits a string into words, word only contains alphabetic characters.

View File

@@ -1,6 +1,7 @@
package strutil
import (
"strings"
"unicode"
)
@@ -111,31 +112,27 @@ func padAtPosition(str string, length int, padStr string, position int) string {
padStr = " "
}
length = length - len(str)
startPadLen := 0
totalPad := length - len(str)
startPad := 0
if position == 0 {
startPadLen = length / 2
startPad = totalPad / 2
} else if position == 1 {
startPadLen = length
startPad = totalPad
} else if position == 2 {
startPad = 0
}
endPadLen := length - startPadLen
endPad := totalPad - startPad
charLen := len(padStr)
leftPad := ""
cur := 0
for cur < startPadLen {
leftPad += string(padStr[cur%charLen])
cur++
repeatPad := func(n int) string {
repeated := strings.Repeat(padStr, (n+len(padStr)-1)/len(padStr))
return repeated[:n]
}
cur = 0
rightPad := ""
for cur < endPadLen {
rightPad += string(padStr[cur%charLen])
cur++
}
left := repeatPad(startPad)
right := repeatPad(endPad)
return leftPad + str + rightPad
return left + str + right
}
// isLetter checks r is a letter but not CJK character.