目录
1.将大数组分片处理
场景:比如sql语法中,使用 IN(?) 条件时,IN的数组中元素个数过多,会导致预编译数超限,此时就需要分块处理
// 1.将大数组分片处理
func SplitArr() {
taskIds := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
block, yushu, blockCnt := 0, 0, 3 // 分区块数,余数,每个区元素数
if len(taskIds)%blockCnt == 0 {
block = len(taskIds) / blockCnt
yushu = 0
} else {
block = len(taskIds)/blockCnt + 1
yushu = len(taskIds) % blockCnt
}
subTaskIds := make([]int, 0)
for i := 0; i < block; i++ {
if i == block-1 { // 最后一块
subTaskIds = taskIds[i*blockCnt : i*blockCnt+yushu]
} else {
subTaskIds = taskIds[i*blockCnt : (i+1)*blockCnt]
}
// 处理 subTaskIds 数组
fmt.Printf("the %v subTaskIds: %v\n", i, subTaskIds)
}
}
/*
输出:
the 0 subTaskIds: [0 1 2]
the 1 subTaskIds: [3 4 5]
the 2 subTaskIds: [6 7 8]
the 3 subTaskIds: [9]
*/
// 2.方法2:封装为切割任意interface类型切片的函数方法
// CutSlice 按照指定长度切割切片
func CutSlice(slice interface{}, n int) [][]interface{} {
var s [][]interface{}
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
return nil
}
if v.Len() == 0 {
return nil
}
if v.Len() <= n {
value := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
value[i] = v.Index(i).Interface()
}
s = append(s, value)
return s
}
s = make([][]interface{}, int(math.Ceil(float64(v.Len())/float64(n))))
x := n
index := 0
for i := 0; i < v.Len(); i++ {
if i == x {
index++
x += n
}
if s[index] == nil {
s[index] = make([]interface{}, 0)
}
s[index] = append(s[index], v.Index(i).Interface())
}
return s
}
2.用于insert时的sql拼接
package main
import (
"fmt"
"math"
"reflect"
"strings"
)
// UserInfo
type UserInfo struct {
Name string
Age int
}
// CombineSql1 利用CutSlice将待插入数组分片,避免一次瞬时插入导致db压力过大;利用strings.Join()进行字符拼接
func CombineSql1(dataArr []*UserInfo) (err error) {
strSql := "INSERT INTO test_table(`name`, `age`) VALUES"
blockCnt := 1000 // 以1000为一组分片insert
for _, iSubDataArr := range CutSlice(dataArr, blockCnt) {
values := make([]string, 0, blockCnt)
params := make([]interface{}, 0, blockCnt)
for i := 0; i < len(iSubDataArr); i++ {
data := iSubDataArr[i].(*UserInfo)
values = append(values, "(?,?)")
params = append(params, data.Name, data.Age)
}
strSubSql := strSql + strings.Join(values, ",")
fmt.Printf("strSubSql: %v params: %v\n", strSubSql, params)
// 执行sql...
}
return
}
// CutSlice 按照指定长度切割切片
func CutSlice(slice interface{}, n int) [][]interface{} {
var s [][]interface{}
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
return nil
}
if v.Len() == 0 {
return nil
}
if v.Len() <= n {
value := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
value[i] = v.Index(i).Interface()
}
s = append(s, value)
return s
}
s = make([][]interface{}, int(math.Ceil(float64(v.Len())/float64(n))))
x := n
index := 0
for i := 0; i < v.Len(); i++ {
if i == x {
index++
x += n
}
if s[index] == nil {
s[index] = make([]interface{}, 0)
}
s[index] = append(s[index], v.Index(i).Interface())
}
return s
}
// CombineSql2 用于insert时的sql拼接(利用 "+" 字符拼接,此方法未分片仅用于sql拼接)
func CombineSql2(list []*UserInfo) (err error) {
strSql := "INSERT INTO test_table(`name`, `age`) VALUES"
params := make([]interface{}, 0)
for i := 0; i < len(list); i++ {
strSql += "(?,?)"
if i < len(list)-1 {
strSql += "," // 循环拼接逗号
}
params = append(params, list[i].Name, list[i].Age)
}
fmt.Println("sql: ", strSql, " params:", params)
// 执行sql...
return
}
func main() {
list := []*UserInfo{
{"user1", 1},
{"user2", 2},
{"user3", 3},
}
CombineSql1(list) // 方法1
CombineSql2(list) // 方法2
return
}
sql拼接结果示例:
3.字符串转md5
// 3.字符串转md5
func MD5(s string) string {
ret := md5.Sum([]byte(s))
return hex.EncodeToString(ret[:])
}
4.利用gzip包,压缩字符内容
// 压缩内容,by gzip 方式,data用json.Marshal()编码
func CompressTogzip(data []byte) string {
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
defer gz.Close()
gz.Write(data)
gz.Flush()
return base64.StdEncoding.EncodeToString(buf.Bytes())
}
// 解压缩内容,by gzip 方式
func UnCompressTogzip(str string) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(str)
if err != nil {
return nil, err
}
buf2 := bytes.NewBuffer(data)
gz, err := gzip.NewReader(buf2)
if err != nil {
return nil, err
}
defer gz.Close()
p, err := ioutil.ReadAll(gz)
if err != nil && err != io.ErrUnexpectedEOF {
return nil, err
}
return p, nil
}
5.切换当前工作目录
func SwitchWorkDir() {
os.Chdir("/usr/local") // 先切换当前工作目录
dir, err1 := exec.Command("pwd").Output()
if err1 != nil {
fmt.Println("exec.Command err: ", err1)
return
}
fmt.Println("dir: ", string(dir))
return
}
func main() {
SwitchWorkDir()
}
6.遍历指定文件夹,获取所有文件名(folder为指定路径,默认可为当前目录 ".")
func GetFiles(folder string){
files, _ := ioutil.ReadDir(folder)
fmt.Println("files length = ", len(files))
for _,file := range files{
if file.IsDir(){
GetFiles(folder + "/" + file.Name())
}else{
fmt.Println(folder + "/" + file.Name())
}
}
}
7.读取配置文件path
binPath, _ := filepath.Abs(filepath.Dir(os.Args[0]))
rootPath := filepath.Dir(binPath)
fmt.Printf("%s/conf/%s/config.yaml", rootPath, os.Getenv("ENV"))
8.切随机生成uuid
// import "github.com/gofrs/uuid"
// 随机生成uuid
func UUID() (string, error) {
str, err := uuid.NewV4()
if err != nil {
return "", err
}
return str.String(), nil
}