parent
be8fb94c81
commit
6f77f08746
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 13 KiB |
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: Test
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
||||
- name: Benchmark
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -bench=. -benchmem
|
@ -0,0 +1,7 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gomod.sh
|
@ -0,0 +1,25 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang Dorm</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang Dorm
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/dorm?status.svg)](https://pkg.go.dev/go.dtapp.net/dorm)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/dorm/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/dorm)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/dorm)](https://goreportcard.com/report/go.dtapp.net/dorm)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/dorm)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```shell
|
||||
go get -v -u go.dtapp.net/dorm
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/dorm"
|
||||
)
|
||||
```
|
@ -0,0 +1,51 @@
|
||||
package dorm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type ConfigMongoClient struct {
|
||||
Dns string // 地址
|
||||
}
|
||||
|
||||
type MongoClient struct {
|
||||
Db *mongo.Client // 驱动
|
||||
config *ConfigMongoClient // 配置
|
||||
}
|
||||
|
||||
func NewMongoClient(config *ConfigMongoClient) (*MongoClient, error) {
|
||||
|
||||
c := &MongoClient{}
|
||||
c.config = config
|
||||
|
||||
// 连接到MongoDB
|
||||
db, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(c.config.Dns))
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("连接失败:%v", err))
|
||||
}
|
||||
|
||||
// 检查连接
|
||||
err = db.Ping(context.TODO(), nil)
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("检查连接失败:%v", err))
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *MongoClient) GetDb() *mongo.Client {
|
||||
return c.Db
|
||||
}
|
||||
|
||||
// Close 关闭
|
||||
func (c *MongoClient) Close() error {
|
||||
err := c.Db.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("关闭失败:%v", err))
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package dorm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ConfigRedisClient struct {
|
||||
Addr string // 地址
|
||||
Password string // 密码
|
||||
DB int // 数据库
|
||||
PoolSize int // 连接池大小
|
||||
}
|
||||
|
||||
type RedisClient struct {
|
||||
Db *redis.Client // 驱动
|
||||
config *ConfigRedisClient // 配置
|
||||
}
|
||||
|
||||
func NewRedisClient(config *ConfigRedisClient) (*RedisClient, error) {
|
||||
|
||||
c := &RedisClient{}
|
||||
c.config = config
|
||||
if c.config.PoolSize == 0 {
|
||||
c.config.PoolSize = 100
|
||||
}
|
||||
|
||||
c.Db = redis.NewClient(&redis.Options{
|
||||
Addr: c.config.Addr, // 地址
|
||||
Password: c.config.Password, // 密码
|
||||
DB: c.config.DB, // 数据库
|
||||
PoolSize: c.config.PoolSize, // 连接池大小
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err := c.Db.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("连接失败:%v", err))
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *RedisClient) GetDb() *redis.Client {
|
||||
return c.Db
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package dorm
|
||||
|
||||
type Iterator struct {
|
||||
data []interface{}
|
||||
index int
|
||||
}
|
||||
|
||||
// NewIterator 构造函数
|
||||
func NewIterator(data []interface{}) *Iterator {
|
||||
return &Iterator{data: data}
|
||||
}
|
||||
|
||||
// HasNext 是否有下一个
|
||||
func (i *Iterator) HasNext() bool {
|
||||
if i.data == nil || len(i.data) == 0 {
|
||||
return false
|
||||
}
|
||||
return i.index < len(i.data)
|
||||
}
|
||||
|
||||
// Next 循环下一个
|
||||
func (i *Iterator) Next() (Ret interface{}) {
|
||||
Ret = i.data[i.index]
|
||||
i.index = i.index + 1
|
||||
return
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package dorm
|
||||
|
||||
import "time"
|
||||
|
||||
type empty struct{}
|
||||
|
||||
const (
|
||||
AttrExpr = "expr" // 过期时间
|
||||
AttrNx = "nx" // 设置Nx
|
||||
)
|
||||
|
||||
type OperationAttr struct {
|
||||
Name string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type OperationAttrs []*OperationAttr
|
||||
|
||||
func (a OperationAttrs) Find(name string) interface{} {
|
||||
for _, attr := range a {
|
||||
if attr.Name == name {
|
||||
return attr.Value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithExpire 过期时间
|
||||
func WithExpire(t time.Duration) *OperationAttr {
|
||||
return &OperationAttr{Name: AttrExpr, Value: t}
|
||||
}
|
||||
|
||||
func WithNX() *OperationAttr {
|
||||
return &OperationAttr{Name: AttrNx, Value: empty{}}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package dorm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
SerializerJson = "json"
|
||||
SerializerString = "string"
|
||||
)
|
||||
|
||||
type JsonGttFunc func() interface{}
|
||||
|
||||
type DBGttFunc func() string
|
||||
|
||||
// SimpleCache 缓存
|
||||
type SimpleCache struct {
|
||||
Operation *StringOperation // 操作类
|
||||
Expire time.Duration // 过去时间
|
||||
DBGetter DBGttFunc // 缓存不存在的操作 DB
|
||||
JsonGetter JsonGttFunc // 缓存不存在的操作 JSON
|
||||
Serializer string // 序列化方式
|
||||
}
|
||||
|
||||
// NewSimpleCache 构造函数
|
||||
func (c *RedisClient) NewSimpleCache(operation *StringOperation, expire time.Duration, serializer string) *SimpleCache {
|
||||
return &SimpleCache{
|
||||
Operation: operation, // 操作类
|
||||
Expire: expire, // 过去时间
|
||||
Serializer: serializer, // 缓存不存在的操作 DB
|
||||
}
|
||||
}
|
||||
|
||||
// SetCache 设置缓存
|
||||
func (c *SimpleCache) SetCache(key string, value interface{}) {
|
||||
c.Operation.Set(key, value, WithExpire(c.Expire)).Unwrap()
|
||||
}
|
||||
|
||||
// GetCache 获取缓存
|
||||
func (c *SimpleCache) GetCache(key string) (ret interface{}) {
|
||||
if c.Serializer == SerializerJson {
|
||||
f := func() string {
|
||||
obj := c.JsonGetter()
|
||||
b, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
ret = c.Operation.Get(key).UnwrapOrElse(f)
|
||||
c.SetCache(key, ret)
|
||||
} else if c.Serializer == SerializerString {
|
||||
f := func() string {
|
||||
return c.DBGetter()
|
||||
}
|
||||
ret = c.Operation.Get(key).UnwrapOrElse(f)
|
||||
c.SetCache(key, ret)
|
||||
}
|
||||
return
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package dorm
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DBGttInterfaceFunc func() interface{}
|
||||
|
||||
// SimpleInterfaceCache 缓存
|
||||
type SimpleInterfaceCache struct {
|
||||
Operation *SimpleOperation // 操作类
|
||||
Expire time.Duration // 过期时间
|
||||
DBGetter DBGttInterfaceFunc // 缓存不存在的操作 DB
|
||||
}
|
||||
|
||||
// NewSimpleInterfaceCache 构造函数
|
||||
func (c *RedisClient) NewSimpleInterfaceCache(operation *SimpleOperation, expire time.Duration) *SimpleInterfaceCache {
|
||||
return &SimpleInterfaceCache{
|
||||
Operation: operation, // 操作类
|
||||
Expire: expire, // 过期时间
|
||||
}
|
||||
}
|
||||
|
||||
// SetCache 设置缓存
|
||||
func (c *SimpleInterfaceCache) SetCache(key string, value interface{}) {
|
||||
c.Operation.Set(key, value, WithExpire(c.Expire)).Unwrap()
|
||||
}
|
||||
|
||||
// GetCache 获取缓存
|
||||
func (c *SimpleInterfaceCache) GetCache(key string) (ret interface{}) {
|
||||
f := func() interface{} {
|
||||
return c.DBGetter()
|
||||
}
|
||||
ret = c.Operation.Get(key).UnwrapOrElse(f)
|
||||
c.SetCache(key, ret)
|
||||
log.Println(ret)
|
||||
return ret
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package dorm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DBGttJsonFunc func() interface{}
|
||||
|
||||
// SimpleJsonCache 缓存
|
||||
type SimpleJsonCache struct {
|
||||
Operation *StringOperation // 操作类
|
||||
Expire time.Duration // 过期时间
|
||||
DBGetter DBGttJsonFunc // 缓存不存在的操作 DB
|
||||
}
|
||||
|
||||
// NewSimpleJsonCache 构造函数
|
||||
func (c *RedisClient) NewSimpleJsonCache(operation *StringOperation, expire time.Duration) *SimpleJsonCache {
|
||||
return &SimpleJsonCache{
|
||||
Operation: operation, // 操作类
|
||||
Expire: expire, // 过期时间
|
||||
}
|
||||
}
|
||||
|
||||
// SetCache 设置缓存
|
||||
func (c *SimpleJsonCache) SetCache(key string, value interface{}) {
|
||||
c.Operation.Set(key, value, WithExpire(c.Expire)).Unwrap()
|
||||
}
|
||||
|
||||
// GetCache 获取缓存
|
||||
func (c *SimpleJsonCache) GetCache(key string) (ret interface{}) {
|
||||
f := func() string {
|
||||
obj := c.DBGetter()
|
||||
b, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
ret = c.Operation.Get(key).UnwrapOrElse(f)
|
||||
c.SetCache(key, ret)
|
||||
return
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package dorm
|
||||
|
||||
type SimpleResult struct {
|
||||
Result interface{}
|
||||
Err error
|
||||
}
|
||||
|
||||
// NewSimpleResult 构造函数
|
||||
func NewSimpleResult(result interface{}, err error) *SimpleResult {
|
||||
return &SimpleResult{Result: result, Err: err}
|
||||
}
|
||||
|
||||
// Unwrap 空值情况下返回错误
|
||||
func (r *SimpleResult) Unwrap() interface{} {
|
||||
if r.Err != nil {
|
||||
panic(r.Err)
|
||||
}
|
||||
return r.Result
|
||||
}
|
||||
|
||||
// UnwrapOr 空值情况下设置返回默认值
|
||||
func (r *SimpleResult) UnwrapOr(defaults interface{}) interface{} {
|
||||
if r.Err != nil {
|
||||
return defaults
|
||||
}
|
||||
return r.Result
|
||||
}
|
||||
|
||||
// UnwrapOrElse 空值情况下设置返回其他
|
||||
func (r *SimpleResult) UnwrapOrElse(f func() interface{}) interface{} {
|
||||
if r.Err != nil {
|
||||
return f()
|
||||
}
|
||||
return r.Result
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package dorm
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type DBGttStringFunc func() string
|
||||
|
||||
// SimpleStringCache 缓存
|
||||
type SimpleStringCache struct {
|
||||
Operation *StringOperation // 操作类
|
||||
Expire time.Duration // 过期时间
|
||||
DBGetter DBGttStringFunc // 缓存不存在的操作 DB
|
||||
}
|
||||
|
||||
// NewSimpleStringCache 构造函数
|
||||
func (c *RedisClient) NewSimpleStringCache(operation *StringOperation, expire time.Duration) *SimpleStringCache {
|
||||
return &SimpleStringCache{
|
||||
Operation: operation, // 操作类
|
||||
Expire: expire, // 过期时间
|
||||
}
|
||||
}
|
||||
|
||||
// SetCache 设置缓存
|
||||
func (c *SimpleStringCache) SetCache(key string, value string) {
|
||||
c.Operation.Set(key, value, WithExpire(c.Expire)).Unwrap()
|
||||
}
|
||||
|
||||
// GetCache 获取缓存
|
||||
func (c *SimpleStringCache) GetCache(key string) (ret string) {
|
||||
f := func() string {
|
||||
return c.DBGetter()
|
||||
}
|
||||
ret = c.Operation.Get(key).UnwrapOrElse(f)
|
||||
c.SetCache(key, ret)
|
||||
return
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package dorm
|
||||
|
||||
type SliceResult struct {
|
||||
Result []interface{}
|
||||
Err error
|
||||
}
|
||||
|
||||
// NewSliceResult 构造函数
|
||||
func NewSliceResult(result []interface{}, err error) *SliceResult {
|
||||
return &SliceResult{Result: result, Err: err}
|
||||
}
|
||||
|
||||
// Unwrap 空值情况下返回错误
|
||||
func (r *SliceResult) Unwrap() []interface{} {
|
||||
if r.Err != nil {
|
||||
panic(r.Err)
|
||||
}
|
||||
return r.Result
|
||||
}
|
||||
|
||||
// UnwrapOr 空值情况下设置返回默认值
|
||||
func (r *SliceResult) UnwrapOr(defaults []interface{}) []interface{} {
|
||||
if r.Err != nil {
|
||||
return defaults
|
||||
}
|
||||
return r.Result
|
||||
}
|
||||
|
||||
func (r *SliceResult) Iter() *Iterator {
|
||||
return NewIterator(r.Result)
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package dorm
|
||||
|
||||
type StringResult struct {
|
||||
Result string // 结果
|
||||
Err error // 错误
|
||||
}
|
||||
|
||||
// NewStringResult 构造函数
|
||||
func NewStringResult(result string, err error) *StringResult {
|
||||
return &StringResult{
|
||||
Result: result,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Unwrap 空值情况下返回错误
|
||||
func (r *StringResult) Unwrap() string {
|
||||
if r.Err != nil {
|
||||
panic(r.Err)
|
||||
}
|
||||
return r.Result
|
||||
}
|
||||
|
||||
// UnwrapOr 空值情况下设置返回默认值
|
||||
func (r *StringResult) UnwrapOr(defaults string) string {
|
||||
if r.Err != nil {
|
||||
return defaults
|
||||
}
|
||||
return r.Result
|
||||
}
|
||||
|
||||
// UnwrapOrElse 空值情况下设置返回其他
|
||||
func (r *StringResult) UnwrapOrElse(f func() string) string {
|
||||
if r.Err != nil {
|
||||
return f()
|
||||
}
|
||||
return r.Result
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package dorm
|
||||
|
||||
const Version = "1.0.5"
|
@ -0,0 +1,17 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: Test
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
||||
- name: Benchmark
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -bench=. -benchmem
|
@ -0,0 +1,8 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gomod.sh
|
||||
/vendor/
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 茂名聚合科技有限公司
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,25 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang Request</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang 请求组件
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/gorequest?status.svg)](https://pkg.go.dev/go.dtapp.net/gorequest)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/gorequest/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/gorequest)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/gorequest)](https://goreportcard.com/report/go.dtapp.net/gorequest)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/gorequest)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```go
|
||||
go get -v -u go.dtapp.net/gorequest
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/gorequest"
|
||||
)
|
||||
```
|
@ -0,0 +1,58 @@
|
||||
package gorequest
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Headers 头部信息
|
||||
type Headers map[string]string
|
||||
|
||||
// NewHeaders 新建头部信息
|
||||
func NewHeaders() Headers {
|
||||
P := make(Headers)
|
||||
return P
|
||||
}
|
||||
|
||||
// NewNewHeadersWith 头部信息使用
|
||||
func NewNewHeadersWith(headers ...Headers) Headers {
|
||||
p := make(Headers)
|
||||
for _, v := range headers {
|
||||
p.SetHeaders(v)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Set 设置头部信息
|
||||
func (p Headers) Set(key, value string) {
|
||||
p[key] = value
|
||||
}
|
||||
|
||||
// SetHeaders 批量设置头部信息
|
||||
func (p Headers) SetHeaders(headers Headers) {
|
||||
for key, value := range headers {
|
||||
p[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// GetQuery 获取头部信息
|
||||
func (p Headers) GetQuery() string {
|
||||
u := url.Values{}
|
||||
for k, v := range p {
|
||||
u.Set(k, v)
|
||||
}
|
||||
return u.Encode()
|
||||
}
|
||||
|
||||
// DeepCopy 深度复制
|
||||
func (p *Headers) DeepCopy() map[string]string {
|
||||
targetMap := make(map[string]string)
|
||||
|
||||
// 从原始复制到目标
|
||||
for key, value := range *p {
|
||||
targetMap[key] = value
|
||||
}
|
||||
|
||||
// 重新申请一个新的map
|
||||
*p = map[string]string{}
|
||||
return targetMap
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package gorequest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"go.dtapp.net/gostring"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Params 参数
|
||||
type Params map[string]interface{}
|
||||
|
||||
// NewParams 新建参数
|
||||
func NewParams() Params {
|
||||
P := make(Params)
|
||||
return P
|
||||
}
|
||||
|
||||
// NewParamsWith 参数使用
|
||||
func NewParamsWith(params ...Params) Params {
|
||||
p := make(Params)
|
||||
for _, v := range params {
|
||||
p.SetParams(v)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Set 设置参数
|
||||
func (p Params) Set(key string, value interface{}) {
|
||||
p[key] = value
|
||||
}
|
||||
|
||||
// SetParams 批量设置参数
|
||||
func (p Params) SetParams(params Params) {
|
||||
for key, value := range params {
|
||||
p[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// GetParamsString 获取参数字符串
|
||||
func GetParamsString(src interface{}) string {
|
||||
switch src.(type) {
|
||||
case string:
|
||||
return src.(string)
|
||||
case int, int8, int32, int64:
|
||||
case uint8, uint16, uint32, uint64:
|
||||
case float32, float64:
|
||||
return gostring.ToString(src)
|
||||
}
|
||||
data, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// DeepCopy 深度复制
|
||||
func (p *Params) DeepCopy() map[string]interface{} {
|
||||
targetMap := make(map[string]interface{})
|
||||
|
||||
// 从原始复制到目标
|
||||
for key, value := range *p {
|
||||
targetMap[key] = value
|
||||
}
|
||||
|
||||
// 重新申请一个新的map
|
||||
*p = map[string]interface{}{}
|
||||
return targetMap
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package gorequest
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ResponseUrlParse 返回参数
|
||||
type ResponseUrlParse struct {
|
||||
Uri string `json:"uri"` // URI
|
||||
Urn string `json:"urn"` // URN
|
||||
Url string `json:"url"` // URL
|
||||
Scheme string `json:"scheme"` // 协议
|
||||
Host string `json:"host"` // 主机
|
||||
Hostname string `json:"hostname"` // 主机名
|
||||
Port string `json:"port"` // 端口
|
||||
Path string `json:"path"` // 路径
|
||||
RawQuery string `json:"raw_query"` // 参数 ?
|
||||
Fragment string `json:"fragment"` // 片段 #
|
||||
}
|
||||
|
||||
// UriParse 解析URl
|
||||
func UriParse(input string) (resp ResponseUrlParse) {
|
||||
parse, err := url.Parse(input)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp.Uri = input
|
||||
resp.Urn = parse.Host + parse.Path
|
||||
resp.Url = parse.Scheme + "://" + parse.Host + parse.Path
|
||||
resp.Scheme = parse.Scheme
|
||||
resp.Host = parse.Host
|
||||
resp.Hostname = parse.Hostname()
|
||||
resp.Port = parse.Port()
|
||||
resp.Path = parse.Path
|
||||
resp.RawQuery = parse.RawQuery
|
||||
resp.Fragment = parse.Fragment
|
||||
return
|
||||
}
|
||||
|
||||
// UriFilterExcludeQueryString 过滤掉url中的参数
|
||||
func UriFilterExcludeQueryString(uri string) string {
|
||||
URL, _ := url.Parse(uri)
|
||||
clearUri := strings.ReplaceAll(uri, URL.RawQuery, "")
|
||||
clearUri = strings.TrimRight(clearUri, "?")
|
||||
return strings.TrimRight(clearUri, "/")
|
||||
}
|
||||
|
||||
// LenCode 编码
|
||||
func LenCode(s string) string {
|
||||
escape := url.QueryEscape(s)
|
||||
return escape
|
||||
}
|
||||
|
||||
// DeCode 解码
|
||||
func DeCode(s string) string {
|
||||
unescape, _ := url.QueryUnescape(s)
|
||||
return unescape
|
||||
}
|
||||
|
||||
// ParseQuery 获取URL参数 https://studygolang.com/articles/2876
|
||||
func ParseQuery(s string) map[string][]string {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
urlParam := u.RawQuery
|
||||
m, _ := url.ParseQuery(urlParam)
|
||||
return m
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package gorequest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetRandomUserAgent 获取随机UA
|
||||
func GetRandomUserAgent() string {
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
return userAgentList[r.Intn(len(userAgentList))]
|
||||
}
|
||||
|
||||
var userAgentList = []string{
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0", // Firefox 2022-02-14
|
||||
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko", // IE 2022-02-14
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36 HeyTapBrowser/40.7.35.1", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36 OnePlusBrowser/30.5.0.8", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a1) Gecko/20060814 Firefox/51.0", // Firefox 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15", // Safari 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15", // Safari 2022-04-18
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Edg/98.0.1108.51", // Edge 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44", // Chrome 2022-04-18
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", // Chrome 2022-04-18
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0", // Firefox 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0", // Firefox 2022-04-18
|
||||
}
|
||||
|
||||
// GetRandomUserAgentSystem 获取系统随机UA
|
||||
func GetRandomUserAgentSystem() string {
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
return userAgentListLinux[r.Intn(len(userAgentListLinux))]
|
||||
case "windows":
|
||||
return userAgentListWindows[r.Intn(len(userAgentListWindows))]
|
||||
default:
|
||||
return userAgentListMac[r.Intn(len(userAgentListMac))]
|
||||
}
|
||||
}
|
||||
|
||||
var userAgentListWindows = []string{
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0", // Firefox 2022-02-14
|
||||
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko", // IE 2022-02-14
|
||||
}
|
||||
|
||||
var userAgentListLinux = []string{
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36 HeyTapBrowser/40.7.35.1", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36 OnePlusBrowser/30.5.0.8", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9a1) Gecko/20060814 Firefox/51.0", // Firefox 2022-02-14
|
||||
}
|
||||
|
||||
var userAgentListMac = []string{
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15", // Safari 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15", // Safari 2022-04-18
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36 Edg/98.0.1108.51", // Edge 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44", // Chrome 2022-04-18
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", // Chrome 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36", // Chrome 2022-04-18
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0", // Firefox 2022-02-14
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0", // Firefox 2022-04-18
|
||||
}
|
||||
|
||||
func DtaUa() string {
|
||||
str := runtime.Version()
|
||||
content := str[2 : len(str)-0]
|
||||
return fmt.Sprintf("Go-dta-request/%s/%v", Version, content)
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package gorequest
|
||||
|
||||
const Version = "1.0.20"
|
@ -0,0 +1,47 @@
|
||||
package gorequest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// MarshalXML 结构体转xml
|
||||
func (p Params) MarshalXML() (reader io.Reader, err error) {
|
||||
buffer := bytes.NewBuffer(make([]byte, 0))
|
||||
|
||||
if _, err = io.WriteString(buffer, "<xml>"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range p {
|
||||
switch {
|
||||
case k == "detail":
|
||||
if _, err = io.WriteString(buffer, "<detail><![CDATA["); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = io.WriteString(buffer, fmt.Sprintf("%v", v)); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = io.WriteString(buffer, "]]></detail>"); err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
if _, err = io.WriteString(buffer, "<"+k+">"); err != nil {
|
||||
return
|
||||
}
|
||||
if err = xml.EscapeText(buffer, []byte(fmt.Sprintf("%v", v))); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = io.WriteString(buffer, "</"+k+">"); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = io.WriteString(buffer, "</xml>"); err != nil {
|
||||
return
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: test-golang
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
@ -0,0 +1,7 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
*.log
|
||||
gitmod.sh
|
@ -0,0 +1,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- master
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 茂名聚合科技有限公司
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,25 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang String</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang 字符串组件
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/gostring?status.svg)](https://pkg.go.dev/go.dtapp.net/gostring)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/gostring/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/gostring)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/gostring)](https://goreportcard.com/report/go.dtapp.net/gostring)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/gostring)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```go
|
||||
go get -v -u go.dtapp.net/gostring
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/gostring"
|
||||
)
|
||||
```
|
@ -0,0 +1,151 @@
|
||||
package gostring
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const Version = "1.0.3"
|
||||
|
||||
// ToString 转换成string
|
||||
func ToString(value interface{}) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// ToFloat64 string到float64
|
||||
func ToFloat64(s string) float64 {
|
||||
i, _ := strconv.ParseFloat(s, 64)
|
||||
return i
|
||||
}
|
||||
|
||||
// ToInt string到int
|
||||
func ToInt(s string) int {
|
||||
i, _ := strconv.Atoi(s)
|
||||
return i
|
||||
}
|
||||
|
||||
// ToInt64 string到int64
|
||||
func ToInt64(s string) int64 {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err == nil {
|
||||
return i
|
||||
}
|
||||
return int64(ToFloat64(s))
|
||||
}
|
||||
|
||||
// ToUint string到uint64
|
||||
func ToUint(s string) uint {
|
||||
i, err := strconv.ParseUint(s, 10, 64)
|
||||
if err == nil {
|
||||
return uint(i)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// ToUint64 string到uint64
|
||||
func ToUint64(s string) uint64 {
|
||||
i, err := strconv.ParseUint(s, 10, 64)
|
||||
if err == nil {
|
||||
return i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Replace 字符串替换
|
||||
func Replace(str, old, new string) string {
|
||||
return strings.Replace(str, old, new, -1)
|
||||
}
|
||||
|
||||
func HmacSha256Hex(key, strToSign string) string {
|
||||
hasHer := hmac.New(sha256.New, []byte(key))
|
||||
hasHer.Write([]byte(strToSign))
|
||||
return hex.EncodeToString(hasHer.Sum(nil))
|
||||
}
|
||||
|
||||
// Space 去除空格
|
||||
func Space(str string) string {
|
||||
return strings.Replace(str, " ", "", -1)
|
||||
}
|
||||
|
||||
// LineBreak 去除换行符
|
||||
func LineBreak(str string) string {
|
||||
return strings.Replace(str, "\n", "", -1)
|
||||
}
|
||||
|
||||
// SpaceAndLineBreak 去除空格和去除换行符
|
||||
func SpaceAndLineBreak(str string) string {
|
||||
return LineBreak(Space(str))
|
||||
}
|
||||
|
||||
// TrimLastChar 删除字符串中的最后一个
|
||||
func TrimLastChar(s string) string {
|
||||
r, size := utf8.DecodeLastRuneInString(s)
|
||||
if r == utf8.RuneError && (size == 0 || size == 1) {
|
||||
size = 0
|
||||
}
|
||||
return s[:len(s)-size]
|
||||
}
|
||||
|
||||
// Split 字符串分隔
|
||||
func Split(s string, sep string) []string {
|
||||
return strings.Split(s, sep)
|
||||
}
|
||||
|
||||
// Contains 判断字符串是否包含某个字符
|
||||
func Contains(s, substr string) bool {
|
||||
return strings.Contains(s, substr)
|
||||
}
|
||||
|
||||
func NumericalToString(value interface{}) (string, bool) {
|
||||
var val string
|
||||
|
||||
switch value.(type) {
|
||||
default:
|
||||
return "0", false
|
||||
case int:
|
||||
intVal, _ := value.(int)
|
||||
val = strconv.FormatInt(int64(intVal), 10)
|
||||
case int8:
|
||||
intVal, _ := value.(int8)
|
||||
val = strconv.FormatInt(int64(intVal), 10)
|
||||
case int16:
|
||||
intVal, _ := value.(int16)
|
||||
val = strconv.FormatInt(int64(intVal), 10)
|
||||
case int32:
|
||||
intVal, _ := value.(int32)
|
||||
val = strconv.FormatInt(int64(intVal), 10)
|
||||
case int64:
|
||||
intVal, _ := value.(int64)
|
||||
val = strconv.FormatInt(int64(intVal), 10)
|
||||
case uint:
|
||||
intVal, _ := value.(uint)
|
||||
val = strconv.FormatUint(uint64(intVal), 10)
|
||||
case uint8:
|
||||
intVal, _ := value.(uint8)
|
||||
val = strconv.FormatUint(uint64(intVal), 10)
|
||||
case uint16:
|
||||
intVal, _ := value.(uint16)
|
||||
val = strconv.FormatUint(uint64(intVal), 10)
|
||||
case uint32:
|
||||
intVal, _ := value.(uint32)
|
||||
val = strconv.FormatUint(uint64(intVal), 10)
|
||||
case uint64:
|
||||
intVal, _ := value.(uint64)
|
||||
val = strconv.FormatUint(intVal, 10)
|
||||
case float32:
|
||||
floatVal, _ := value.(float32)
|
||||
val = strconv.FormatFloat(float64(floatVal), 'f', -1, 32)
|
||||
case float64:
|
||||
floatVal, _ := value.(float64)
|
||||
val = strconv.FormatFloat(floatVal, 'f', -1, 64)
|
||||
}
|
||||
return val, true
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: clone
|
||||
|
||||
steps:
|
||||
- name: test-golang
|
||||
image: golang:1.18
|
||||
commands:
|
||||
- go env -w GO111MODULE=on
|
||||
- go env -w GOPROXY=https://goproxy.cn,direct
|
||||
- go test -v ./...
|
@ -0,0 +1,7 @@
|
||||
.env
|
||||
.git
|
||||
.svn
|
||||
.idea
|
||||
.vscode
|
||||
.log
|
||||
gomod.sh
|
@ -0,0 +1,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- master
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 茂名聚合科技有限公司
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,25 @@
|
||||
<h1>
|
||||
<a href="https://www.dtapp.net/">Golang Time</a>
|
||||
</h1>
|
||||
|
||||
📦 Golang 时间组件
|
||||
|
||||
[comment]: <> (go)
|
||||
[![godoc](https://pkg.go.dev/badge/go.dtapp.net/gotime?status.svg)](https://pkg.go.dev/go.dtapp.net/gotime)
|
||||
[![goproxy.cn](https://goproxy.cn/stats/go.dtapp.net/gotime/badges/download-count.svg)](https://goproxy.cn/stats/go.dtapp.net/gotime)
|
||||
[![goreportcard.com](https://goreportcard.com/badge/go.dtapp.net/gotime)](https://goreportcard.com/report/go.dtapp.net/gotime)
|
||||
[![deps.dev](https://img.shields.io/badge/deps-go-red.svg)](https://deps.dev/go/go.dtapp.net/gotime)
|
||||
|
||||
#### 安装使用
|
||||
|
||||
```go
|
||||
go get -v -u go.dtapp.net/gotime
|
||||
```
|
||||
|
||||
#### 导入
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.dtapp.net/gotime"
|
||||
)
|
||||
```
|
@ -0,0 +1,15 @@
|
||||
package gotime
|
||||
|
||||
import "time"
|
||||
|
||||
// Tomorrow 明天
|
||||
func Tomorrow() Pro {
|
||||
p := NewPro()
|
||||
location, err := time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
p.Time = time.Now().Add(time.Hour*8).AddDate(0, 0, +1)
|
||||
} else {
|
||||
p.Time = time.Now().In(location).AddDate(0, 0, +1)
|
||||
}
|
||||
return p
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package gotime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const Version = "1.0.2"
|
||||
|
||||
// 时间格式化常量
|
||||
const (
|
||||
RFC3339Format = time.RFC3339
|
||||
Iso8601Format = "2006-01-02T15:04:05-07:00"
|
||||
CookieFormat = "Monday, 02-Jan-2006 15:04:05 MST"
|
||||
RFC1036Format = "Mon, 02 Jan 06 15:04:05 -0700"
|
||||
RFC7231Format = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||
DayDateTimeFormat = "Mon, Jan 2, 2006 3:04 PM"
|
||||
DateTimeFormat = "2006-01-02 15:04:05"
|
||||
DateFormat = "2006-01-02"
|
||||
TimeFormat = "15:04:05"
|
||||
ShortDateTimeFormat = "20060102150405"
|
||||
ShortDateFormat = "20060102"
|
||||
ShortTimeFormat = "150405"
|
||||
)
|
||||
|
||||
// Pro 结构体
|
||||
type Pro struct {
|
||||
Time time.Time
|
||||
loc *time.Location
|
||||
Error error
|
||||
}
|
||||
|
||||
// NewPro 初始化结构体
|
||||
func NewPro() Pro {
|
||||
return Pro{
|
||||
Time: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
// BeforeSeconds 获取n秒前的时间
|
||||
func (p Pro) BeforeSeconds(seconds int) Pro {
|
||||
st, _ := time.ParseDuration(fmt.Sprintf("-%ds", seconds))
|
||||
p.Time = p.Time.Add(st)
|
||||
return p
|
||||
}
|
||||
|
||||
// AfterSeconds 获取n秒后的时间
|
||||
func (p Pro) AfterSeconds(seconds int) Pro {
|
||||
st, _ := time.ParseDuration(fmt.Sprintf("+%ds", seconds))
|
||||
p.Time = p.Time.Add(st)
|
||||
return p
|
||||
}
|
||||
|
||||
// BeforeMinute 获取n分钟前的时间
|
||||
func (p Pro) BeforeMinute(seconds int) Pro {
|
||||
st, _ := time.ParseDuration(fmt.Sprintf("-%dm", seconds))
|
||||
p.Time = p.Time.Add(st)
|
||||
return p
|
||||
}
|
||||
|
||||
// AfterMinute 获取n分钟后的时间
|
||||
func (p Pro) AfterMinute(seconds int) Pro {
|
||||
st, _ := time.ParseDuration(fmt.Sprintf("+%dm", seconds))
|
||||
p.Time = p.Time.Add(st)
|
||||
return p
|
||||
}
|
||||
|
||||
// BeforeHour 获取n小时前的时间
|
||||
func (p Pro) BeforeHour(hour int) Pro {
|
||||
st, _ := time.ParseDuration(fmt.Sprintf("-%dh", hour))
|
||||
p.Time = p.Time.Add(st)
|
||||
return p
|
||||
}
|
||||
|
||||
// AfterHour 获取n小时后的时间
|
||||
func (p Pro) AfterHour(hour int) Pro {
|
||||
st, _ := time.ParseDuration(fmt.Sprintf("+%dh", hour))
|
||||
p.Time = p.Time.Add(st)
|
||||
return p
|
||||
}
|
||||
|
||||
// BeforeDay 获取n天前的时间
|
||||
func (p Pro) BeforeDay(day int) Pro {
|
||||
p.Time = p.Time.AddDate(0, 0, -day)
|
||||
return p
|
||||
}
|
||||
|
||||
// AfterDay 获取n天后的时间
|
||||
func (p Pro) AfterDay(day int) Pro {
|
||||
p.Time = p.Time.AddDate(0, 0, day)
|
||||
return p
|
||||
}
|
||||
|
||||
// SetFormat 格式化
|
||||
func (p Pro) SetFormat(layout string) string {
|
||||
return p.Time.Format(layout)
|
||||
}
|
||||
|
||||
// Month 获取当前月
|
||||
func (p Pro) Month() int {
|
||||
return p.MonthOfYear()
|
||||
}
|
||||
|
||||
// MonthOfYear 获取本年的第几月
|
||||
func (p Pro) MonthOfYear() int {
|
||||
return int(p.Time.In(p.loc).Month())
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package gotime
|
||||
|
||||
import "time"
|
||||
|
||||
// Gt 是否大于
|
||||
func (p Pro) Gt(t2 time.Time) bool {
|
||||
return p.Time.After(t2)
|
||||
}
|
||||
|
||||
// Lt 是否小于
|
||||
func (p Pro) Lt(t2 time.Time) bool {
|
||||
return p.Time.Before(t2)
|
||||
}
|
||||
|
||||
// Eq 是否等于
|
||||
func (p Pro) Eq(t2 time.Time) bool {
|
||||
return p.Time.Equal(t2)
|
||||
}
|
||||
|
||||
// Ne 是否不等于
|
||||
func (p Pro) Ne(t2 time.Time) bool {
|
||||
return !p.Eq(t2)
|
||||
}
|
||||
|
||||
// Gte 是否大于等于
|
||||
func (p Pro) Gte(t2 time.Time) bool {
|
||||
return p.Gt(t2) || p.Eq(t2)
|
||||
}
|
||||
|
||||
// Lte 是否小于等于
|
||||
func (p Pro) Lte(t2 time.Time) bool {
|
||||
return p.Lt(t2) || p.Eq(t2)
|
||||
}
|
||||
|
||||
// Between 是否在两个时间之间(不包括这两个时间)
|
||||
func (p Pro) Between(start time.Time, end time.Time) bool {
|
||||
if p.Gt(start) && p.Lt(end) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BetweenIncludedStart 是否在两个时间之间(包括开始时间)
|
||||
func (p Pro) BetweenIncludedStart(start time.Time, end time.Time) bool {
|
||||
if p.Gte(start) && p.Lt(end) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BetweenIncludedEnd 是否在两个时间之间(包括结束时间)
|
||||
func (p Pro) BetweenIncludedEnd(start time.Time, end time.Time) bool {
|
||||
if p.Gt(start) && p.Lte(end) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BetweenIncludedBoth 是否在两个时间之间(包括这两个时间)
|
||||
func (p Pro) BetweenIncludedBoth(start time.Time, end time.Time) bool {
|
||||
if p.Gte(start) && p.Lte(end) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package gotime
|
||||
|
||||
import "time"
|
||||
|
||||
// DiffInHour 相差多少小时
|
||||
func (p Pro) DiffInHour(t2 time.Time) (hour int64) {
|
||||
t2.Before(p.Time)
|
||||
diff := p.Time.Unix() - t2.Unix()
|
||||
hour = diff / 3600
|
||||
return hour
|
||||
}
|
||||
|
||||
// DiffInHourWithAbs 相差多少小时(绝对值)
|
||||
func (p Pro) DiffInHourWithAbs(t2 time.Time) (hour int64) {
|
||||
p.Time.Before(t2)
|
||||
diff := t2.Unix() - p.Time.Unix()
|
||||
hour = diff / 3600
|
||||
if hour > 0 {
|
||||
return hour
|
||||
}
|
||||
t2.Before(p.Time)
|
||||
diff = p.Time.Unix() - t2.Unix()
|
||||
hour = diff / 3600
|
||||
return hour
|
||||
}
|
||||
|
||||
// DiffInMinutes 相差多少分钟
|
||||
func (p Pro) DiffInMinutes(t2 time.Time) (hour int64) {
|
||||
t2.Before(p.Time)
|
||||
diff := p.Time.Unix() - t2.Unix()
|
||||
hour = diff / 60
|
||||
return hour
|
||||
}
|
||||
|
||||
// DiffInMinutesWithAbs 相差多少分钟(绝对值)
|
||||
func (p Pro) DiffInMinutesWithAbs(t2 time.Time) (hour int64) {
|
||||
p.Time.Before(t2)
|
||||
diff := t2.Unix() - p.Time.Unix()
|
||||
hour = diff / 60
|
||||
if hour > 0 {
|
||||
return hour
|
||||
}
|
||||
t2.Before(p.Time)
|
||||
diff = p.Time.Unix() - t2.Unix()
|
||||
hour = diff / 60
|
||||
return hour
|
||||
}
|
||||
|
||||
// DiffInSecond 相差多少秒
|
||||
func (p Pro) DiffInSecond(t2 time.Time) (hour int64) {
|
||||
t2.Before(p.Time)
|
||||
diff := p.Time.Unix() - t2.Unix()
|
||||
hour = diff
|
||||
return hour
|
||||
}
|
||||
|
||||
// DiffInSecondWithAbs 相差多少秒(绝对值)
|
||||
func (p Pro) DiffInSecondWithAbs(t2 time.Time) (hour int64) {
|
||||
p.Time.Before(t2)
|
||||
diff := t2.Unix() - p.Time.Unix()
|
||||
hour = diff
|
||||
if hour > 0 {
|
||||
return hour
|
||||
}
|
||||
t2.Before(p.Time)
|
||||
diff = p.Time.Unix() - t2.Unix()
|
||||
hour = diff
|
||||
return hour
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package gotime
|
||||
|
||||
import "fmt"
|
||||
|
||||
// invalidTimezoneError 无效的时区错误
|
||||
var invalidTimezoneError = func(timezone string) error {
|
||||
return fmt.Errorf("invalid timezone %q, please see the file %q for all valid timezones", timezone, "$GOROOT/lib/time/zoneinfo.zip")
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package gotime
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 通过时区获取 Location 实例
|
||||
func getLocationByTimezone(timezone string) (*time.Location, error) {
|
||||
loc, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
err = invalidTimezoneError(timezone)
|
||||
}
|
||||
return loc, err
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package gotime
|
||||
|
||||
// Bson mongoDB
|
||||
func (p Pro) Bson() string {
|
||||
return p.Now().String()
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
package gotime
|
||||
|
||||
import "time"
|
||||
|
||||
// 数字常量
|
||||
const (
|
||||
YearsPerMillennium = 1000 // 每千年1000年
|
||||
YearsPerCentury = 100 // 每世纪100年
|
||||
YearsPerDecade = 10 // 每十年10年
|
||||
QuartersPerYear = 4 // 每年4季度
|
||||
MonthsPerYear = 12 // 每年12月
|
||||
MonthsPerQuarter = 3 // 每季度3月
|
||||
WeeksPerNormalYear = 52 // 每常规年52周
|
||||
weeksPerLongYear = 53 // 每长年53周
|
||||
WeeksPerMonth = 4 // 每月4周
|
||||
DaysPerLeapYear = 366 // 每闰年366天
|
||||
DaysPerNormalYear = 365 // 每常规年365天
|
||||
DaysPerWeek = 7 // 每周7天
|
||||
HoursPerWeek = 168 // 每周168小时
|
||||
HoursPerDay = 24 // 每天24小时
|
||||
MinutesPerDay = 1440 // 每天1440分钟
|
||||
MinutesPerHour = 60 // 每小时60分钟
|
||||
SecondsPerWeek = 604800 // 每周604800秒
|
||||
SecondsPerDay = 86400 // 每天86400秒
|
||||
SecondsPerHour = 3600 // 每小时3600秒
|
||||
SecondsPerMinute = 60 // 每分钟60秒
|
||||
MillisecondsPerSecond = 1000 // 每秒1000毫秒
|
||||
MicrosecondsPerMillisecond = 1000 // 每毫秒1000微秒
|
||||
MicrosecondsPerSecond = 1000000 // 每秒1000000微秒
|
||||
)
|
||||
|
||||
// StartOfCentury 本世纪开始时间
|
||||
func (p Pro) StartOfCentury() Pro {
|
||||
p.Time = time.Date(p.Time.Year()/YearsPerCentury*YearsPerCentury, 1, 1, 0, 0, 0, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// EndOfCentury 本世纪结束时间
|
||||
func (p Pro) EndOfCentury() Pro {
|
||||
p.Time = time.Date(p.Time.Year()/YearsPerCentury*YearsPerCentury+99, 12, 31, 23, 59, 59, 999999999, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// StartOfDecade 本年代开始时间
|
||||
func (p Pro) StartOfDecade() Pro {
|
||||
p.Time = time.Date(p.Time.Year()/YearsPerDecade*YearsPerDecade, 1, 1, 0, 0, 0, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// EndOfDecade 本年代结束时间
|
||||
func (p Pro) EndOfDecade() Pro {
|
||||
p.Time = time.Date(p.Time.Year()/YearsPerDecade*YearsPerDecade+9, 12, 31, 23, 59, 59, 999999999, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// StartOfYear 本年开始时间
|
||||
func (p Pro) StartOfYear() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), 1, 1, 0, 0, 0, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// EndOfYear 本年结束时间
|
||||
func (p Pro) EndOfYear() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), 12, 31, 23, 59, 59, 999999999, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// Quarter 获取当前季度
|
||||
func (p Pro) Quarter() (quarter int) {
|
||||
switch {
|
||||
case p.Time.Month() >= 10:
|
||||
quarter = 4
|
||||
case p.Time.Month() >= 7:
|
||||
quarter = 3
|
||||
case p.Time.Month() >= 4:
|
||||
quarter = 2
|
||||
case p.Time.Month() >= 1:
|
||||
quarter = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// StartOfQuarter 本季度开始时间
|
||||
func (p Pro) StartOfQuarter() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), time.Month(3*p.Quarter()-2), 1, 0, 0, 0, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// EndOfQuarter 本季度结束时间
|
||||
func (p Pro) EndOfQuarter() Pro {
|
||||
quarter, day := p.Quarter(), 30
|
||||
switch quarter {
|
||||
case 1, 4:
|
||||
day = 31
|
||||
case 2, 3:
|
||||
day = 30
|
||||
}
|
||||
p.Time = time.Date(p.Time.Year(), time.Month(3*quarter), day, 23, 59, 59, 999999999, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// StartOfMonth 本月开始时间
|
||||
func (p Pro) StartOfMonth() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), time.Month(p.Month()), 1, 0, 0, 0, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// EndOfMonth 本月结束时间
|
||||
func (p Pro) EndOfMonth() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), time.Month(p.Month()), 1, 23, 59, 59, 999999999, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// StartOfDay 本日开始时间
|
||||
func (p Pro) StartOfDay() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), p.Time.Month(), p.Time.Day(), 0, 0, 0, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
||||
|
||||
// EndOfDay 本日结束时间
|
||||
func (p Pro) EndOfDay() Pro {
|
||||
p.Time = time.Date(p.Time.Year(), p.Time.Month(), p.Time.Day(), 23, 59, 59, 0, p.Time.Location())
|
||||
return p
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package gotime
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Yesterday 昨天
|
||||
func Yesterday() Pro {
|
||||
p := NewPro()
|
||||
location, err := time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
p.Time = time.Now().Add(time.Hour*8).AddDate(0, 0, -1)
|
||||
} else {
|
||||
p.Time = time.Now().In(location).AddDate(0, 0, -1)
|
||||
}
|
||||
return p
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue