代码拉取完成,页面将自动刷新
package util
import (
"bytes"
"errors"
"fmt"
"reflect"
"strings"
"unicode"
"unicode/utf8"
gonanoid "github.com/matoous/go-nanoid/v2"
"github.com/valyala/fasthttp"
)
// SubStrStr 从字符串最后一次出现的位置开始截取到末尾
func SubStrStr(s, substr string) string {
if substr == "" {
return s
}
idx := strings.LastIndex(s, substr)
if idx == -1 {
return ""
}
return s[idx+len(substr):]
}
// NanoidAlphabet 使用自定义字母表生成随机字符串
func NanoidAlphabet(l int, alphabets ...string) string {
if l == 0 {
return ""
}
var builder strings.Builder
for _, alphabet := range alphabets {
builder.WriteString(alphabet)
}
alphabet := builder.String()
if alphabet == "" {
alphabet = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"
}
return gonanoid.MustGenerate(alphabet, l)
}
// Nanoid 生成指定长度的随机字符串
func Nanoid(l int) string {
if l == 0 {
panic("Nanoid: length must be greater than 0")
}
return gonanoid.Must(l)
}
// NanoidAlphabetType 使用类型化字母表生成随机字符串
// alphabetType: "number,upperCase,lowerCase" 组合
func NanoidAlphabetType(alphabetType string, l int) string {
if alphabetType == "" || l == 0 {
panic("NanoidAlphabetType: invalid parameters")
}
var builder strings.Builder
for _, typ := range strings.Split(alphabetType, ",") {
switch typ {
case "number":
builder.WriteString("0123456789")
case "lowerCase":
builder.WriteString("qwertyuiopasdfghjklzxcvbnm")
case "upperCase":
builder.WriteString("QWERTYUIOPASDFGHJKLZXCVBNM")
}
}
alphabet := builder.String()
if alphabet == "" {
panic("NanoidAlphabetType: no valid alphabet types specified")
}
return gonanoid.MustGenerate(alphabet, l)
}
// EndPadString 向后补充字符串到指定长度
func EndPadString(text, pad string, size int) string {
if len(text) >= size {
return text
}
return text + strings.Repeat(pad, size-len(text))
}
// StartPadString 向前补充字符串到指定长度
func StartPadString(text, pad string, size int) string {
if text == "" || len(text) >= size {
return text
}
if pad == "" {
pad = "0"
}
return strings.Repeat(pad, size-len(text)) + text
}
// EndPadByte 向后补充字节到指定长度
func EndPadByte(data []byte, pad string, size int) []byte {
if len(data) >= size {
return data
}
if pad == "" {
pad = "0"
}
padBytes := []byte(pad)
result := make([]byte, size)
copy(result, data)
for i := len(data); i < size; i++ {
result[i] = padBytes[i%len(padBytes)]
}
return result
}
// GetClientIp 获取客户端真实 IP 地址
func GetClientIp(c *fasthttp.RequestCtx) string {
// 优先检查 X-Forwarded-For
if xff := c.Request.Header.Peek("X-Forwarded-For"); len(xff) > 0 {
if idx := bytes.IndexByte(xff, ','); idx >= 0 {
return string(bytes.TrimSpace(xff[:idx]))
}
return string(xff)
}
// 检查 X-Real-IP
if xri := c.Request.Header.Peek("X-Real-IP"); len(xri) > 0 {
return string(xri)
}
return c.RemoteIP().String()
}
// Length 获取字符串的字符数(非字节数)
func Length(strs ...string) int {
if len(strs) == 0 {
return 0
}
totalLen := 0
for _, s := range strs {
totalLen += utf8.RuneCountInString(s)
}
return totalLen
}
// Ternary 三元运算符
func Ternary[T any](condition bool, trueVal, falseVal T) T {
if condition {
return trueVal
}
return falseVal
}
// FirstNonZero 返回第一个非零值
func FirstNonZero[T comparable](values ...T) T {
var zero T
for _, v := range values {
if v != zero {
return v
}
}
return zero
}
// FirstNonZeroByAny 返回第一个非空值
func FirstNonZeroByAny(values ...any) any {
for _, v := range values {
if !IsEmpty2(v) {
return v
}
}
if len(values) > 0 {
return values[len(values)-1]
}
return nil
}
// DynamicUpdateStructField 动态修改结构体字段值
func DynamicUpdateStructField(s any, fieldName string, newValue interface{}) error {
v := reflect.ValueOf(s)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return errors.New("expected a pointer to struct")
}
v = v.Elem()
field := v.FieldByName(fieldName)
if !field.IsValid() {
return fmt.Errorf("field %s not found", fieldName)
}
if !field.CanSet() {
return fmt.Errorf("field %s cannot be set", fieldName)
}
newVal := reflect.ValueOf(newValue)
if field.Type() != newVal.Type() {
return fmt.Errorf("type mismatch: expected %s, got %s", field.Type(), newVal.Type())
}
field.Set(newVal)
return nil
}
// DynamicGetStructField 获取结构体字段值(支持点号分隔的路径)
func DynamicGetStructField(s any, fieldPath string, capitalizeFirst bool) (any, error) {
if s == nil || fieldPath == "" {
return nil, errors.New("parameters cannot be nil/empty")
}
fieldNames := strings.Split(strings.Trim(fieldPath, "."), ".")
return DynamicGetStructFieldByList(s, fieldNames, capitalizeFirst)
}
// DynamicGetStructFieldByList 按字段列表递归获取值
func DynamicGetStructFieldByList(s any, fieldNames []string, capitalizeFirst bool) (any, error) {
if s == nil || len(fieldNames) == 0 {
return nil, errors.New("parameters cannot be nil/empty")
}
v := reflect.ValueOf(s)
if v.Kind() == reflect.Ptr {
v = v.Elem()
return DynamicGetStructFieldByList(v.Interface(), fieldNames, capitalizeFirst)
}
fieldName := fieldNames[0]
var field reflect.Value
switch v.Kind() {
case reflect.Struct:
if capitalizeFirst {
r := []rune(fieldName)
r[0] = unicode.ToUpper(r[0])
fieldName = string(r)
}
field = v.FieldByName(fieldName)
case reflect.Map:
field = v.MapIndex(reflect.ValueOf(fieldName))
default:
return nil, fmt.Errorf("unsupported type: %s", v.Kind())
}
if !field.IsValid() {
return nil, fmt.Errorf("field %s not found", fieldName)
}
if len(fieldNames) == 1 {
return field.Interface(), nil
}
return DynamicGetStructFieldByList(field.Interface(), fieldNames[1:], capitalizeFirst)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。