字符串

> 按字节数截断字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package util

import "unicode/utf8"

const Hellip = "…"

func SubStrContainSuffix(str string, maxBytes int, suffix string) string {
if len(str) <= maxBytes {
return str
}
maxBytesNotContainSuffix := maxBytes - len(suffix)
return SubStringByByte(str, maxBytesNotContainSuffix) + suffix
}

func SubStringByByte(str string, maxBytes int) string {
if len(str) <= maxBytes {
return str
}
byteCount := 0
for i := 0; i < len(str); {
_, size := utf8.DecodeRuneInString(str[i:])
if byteCount+size > maxBytes {
return str[:i]
}
byteCount += size
i += size
}
return str
}




时间

> 低版本go语言获取毫秒数

time.Now() 能够获取当前时间,而 UnixMilli() 方法可得到当前时间的毫秒级时间戳。UnixMilli() 方法是在 Go 1.17 版本引入的。

1
2
3
4
// 获取当前时间
now := time.Now()
// 获取毫秒级时间戳
millisecond := now.UnixMilli()

低版本可以这么玩:

1
2
3
4
// 获取当前时间
now := time.Now()
// 获取毫秒级时间戳
millisecond := now.UnixNano() / int64(time.Millisecond)

PS:go语言中的时间定义

1
2
3
4
5
6
7
8
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)




> 时间戳转格式化时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (
"fmt"
"time"
)

// TimestampToDateTime 将秒级时间戳转换为指定格式的时间字符串(东八区)
// 参数:timestamp - 秒级时间戳(如 1712058764 对应 2024-04-02 19:52:44)
// 返回:格式化后的时间字符串(示例:"2024-04-02 19:52:44")
func TimestampToDateTime(timestamp int64) string {
// 将时间戳转换为 time.Time 对象(UTC 时间)
t := time.Unix(timestamp, 0)

// 转换为东八区时间(UTC+8)
// 若需其他时区,修改 "Asia/Shanghai" 为对应时区(如 "America/New_York")
loc, _ := time.LoadLocation("Asia/Shanghai")
tInLocal := t.In(loc)

// 格式化为目标字符串(Go 的时间格式化参考模板:2006-01-02 15:04:05)
return tInLocal.Format("2006-01-02 15:04:05")
}

func main() {
// 测试用例:2024-04-02 19:52:44 对应的秒级时间戳
testTimestamp := int64(1712058764)
result := TimestampToDateTime(testTimestamp)
fmt.Printf("时间戳 %d 转换结果: %s\n", testTimestamp, result)
// 输出:时间戳 1712058764 转换结果: 2024-04-02 19:52:44
}





panic

> 在函数外部recover panic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package util

import "log"

type panicHandler func(err interface{})

type optionPanicHandler func(*optionPanicHandlerParams)

type optionPanicHandlerParams struct {
panicHandler panicHandler
}

func WithPanicHandler(panicHandler panicHandler) optionPanicHandler {
return func(optParams *optionPanicHandlerParams) {
optParams.panicHandler = panicHandler
}
}

func WithRecover(f func(), opts ...optionPanicHandler) {
defer func() {
if err := recover(); err != nil {
optParams := &optionPanicHandlerParams{}
for _, opt := range opts {
opt(optParams)
}
if optParams.panicHandler == nil {
optParams.panicHandler = defaultPanicHandler
}
optParams.panicHandler(err)
}
}()

f()
}

func defaultPanicHandler(err interface{}) {
log.Printf("panic: %v", err)
}

例1:

1
go util.WithRecover(func() { f2s.recordFileUpload(language, fileContent) })

例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
util.WithRecover(func() {
switch method {
case Get:
handlerFunc = enforceGet(handlerFunc)
case Post:
handlerFunc = enforcePost(handlerFunc)
default:
log.Printf("invalid method: %s", method)
}
handlerFunc(w, r, nil)
}, util.WithPanicHandler(func(err interface{}) {
panicHandler(err, method, realPath)
}))

func panicHandler(err interface{}, method string, realPath string) {
log.Printf("panic: %v, method: %s, realPath: %s", err, method, realPath)
}