Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
902a0ce860 | ||
|
|
576d1bfe2b | ||
|
|
4e084cc4b5 | ||
|
|
ce853c6b87 |
@@ -1,11 +1,13 @@
|
|||||||
package entgo
|
package entgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"entgo.io/ent/dialect/sql"
|
entSql "entgo.io/ent/dialect/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type entClientInterface interface {
|
type entClientInterface interface {
|
||||||
@@ -14,10 +16,10 @@ type entClientInterface interface {
|
|||||||
|
|
||||||
type EntClient[T entClientInterface] struct {
|
type EntClient[T entClientInterface] struct {
|
||||||
db T
|
db T
|
||||||
drv *sql.Driver
|
drv *entSql.Driver
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEntClient[T entClientInterface](db T, drv *sql.Driver) *EntClient[T] {
|
func NewEntClient[T entClientInterface](db T, drv *entSql.Driver) *EntClient[T] {
|
||||||
return &EntClient[T]{
|
return &EntClient[T]{
|
||||||
db: db,
|
db: db,
|
||||||
drv: drv,
|
drv: drv,
|
||||||
@@ -28,17 +30,29 @@ func (c *EntClient[T]) Client() T {
|
|||||||
return c.db
|
return c.db
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *EntClient[T]) Driver() *sql.Driver {
|
func (c *EntClient[T]) Driver() *entSql.Driver {
|
||||||
return c.drv
|
return c.drv
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *EntClient[T]) Close() {
|
func (c *EntClient[T]) DB() *sql.DB {
|
||||||
_ = c.db.Close()
|
return c.drv.DB()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EntClient[T]) Close() error {
|
||||||
|
return c.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EntClient[T]) Query(ctx context.Context, query string, args, v any) error {
|
||||||
|
return c.Driver().Query(ctx, query, args, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *EntClient[T]) Exec(ctx context.Context, query string, args, v any) error {
|
||||||
|
return c.Driver().Exec(ctx, query, args, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDriver 创建数据库驱动
|
// CreateDriver 创建数据库驱动
|
||||||
func CreateDriver(driverName, dsn string, maxIdleConnections, maxOpenConnections int, connMaxLifetime time.Duration) (*sql.Driver, error) {
|
func CreateDriver(driverName, dsn string, maxIdleConnections, maxOpenConnections int, connMaxLifetime time.Duration) (*entSql.Driver, error) {
|
||||||
drv, err := sql.Open(driverName, dsn)
|
drv, err := entSql.Open(driverName, dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New(fmt.Sprintf("failed opening connection to db: %v", err))
|
return nil, errors.New(fmt.Sprintf("failed opening connection to db: %v", err))
|
||||||
}
|
}
|
||||||
|
|||||||
48
gorm/go.mod
Normal file
48
gorm/go.mod
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
module github.com/tx7do/go-utils/gorm
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
toolchain go1.22.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
gorm.io/driver/clickhouse v0.6.0
|
||||||
|
gorm.io/driver/mysql v1.5.6
|
||||||
|
gorm.io/driver/postgres v1.5.7
|
||||||
|
gorm.io/driver/sqlite v1.5.5
|
||||||
|
gorm.io/driver/sqlserver v1.5.3
|
||||||
|
gorm.io/gorm v1.25.10
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/ClickHouse/ch-go v0.58.2 // indirect
|
||||||
|
github.com/ClickHouse/clickhouse-go/v2 v2.15.0 // indirect
|
||||||
|
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||||
|
github.com/go-faster/city v1.0.1 // indirect
|
||||||
|
github.com/go-faster/errors v0.6.1 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
|
github.com/google/uuid v1.3.1 // indirect
|
||||||
|
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/klauspost/compress v1.16.7 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||||
|
github.com/microsoft/go-mssqldb v1.6.0 // indirect
|
||||||
|
github.com/paulmach/orb v0.10.0 // indirect
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.18 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/segmentio/asm v1.2.0 // indirect
|
||||||
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.19.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||||
|
golang.org/x/crypto v0.14.0 // indirect
|
||||||
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
|
golang.org/x/text v0.13.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
replace github.com/tx7do/go-utils => ../
|
||||||
2926
gorm/go.sum
Normal file
2926
gorm/go.sum
Normal file
File diff suppressed because it is too large
Load Diff
77
gorm/gorm_client.go
Normal file
77
gorm/gorm_client.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package gorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"gorm.io/driver/clickhouse"
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
|
"gorm.io/driver/sqlserver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
*gorm.DB
|
||||||
|
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(driverName, dsn string, enableMigrate bool, gormCfg *gorm.Config) *Client {
|
||||||
|
c := &Client{}
|
||||||
|
|
||||||
|
if gormCfg == nil {
|
||||||
|
gormCfg = &gorm.Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.err = c.createGormClient(driverName, dsn, enableMigrate, gormCfg)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Error() error {
|
||||||
|
return c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// createGormClient 创建GORM的客户端
|
||||||
|
func (c *Client) createGormClient(driverName, dsn string, enableMigrate bool, gormCfg *gorm.Config) error {
|
||||||
|
var driver gorm.Dialector
|
||||||
|
switch driverName {
|
||||||
|
default:
|
||||||
|
fallthrough
|
||||||
|
case "mysql":
|
||||||
|
driver = mysql.Open(dsn)
|
||||||
|
break
|
||||||
|
case "postgres":
|
||||||
|
driver = postgres.Open(dsn)
|
||||||
|
break
|
||||||
|
case "clickhouse":
|
||||||
|
driver = clickhouse.Open(dsn)
|
||||||
|
break
|
||||||
|
case "sqlite":
|
||||||
|
driver = sqlite.Open(dsn)
|
||||||
|
break
|
||||||
|
case "sqlserver":
|
||||||
|
driver = sqlserver.Open(dsn)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gorm.Open(driver, gormCfg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed opening connection to db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 运行数据库迁移工具
|
||||||
|
if enableMigrate {
|
||||||
|
if err = client.AutoMigrate(
|
||||||
|
getMigrateModels()...,
|
||||||
|
); err != nil {
|
||||||
|
return fmt.Errorf("failed creating schema resources: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.DB = client
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
13
gorm/migrates.go
Normal file
13
gorm/migrates.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package gorm
|
||||||
|
|
||||||
|
var migrateModels []interface{}
|
||||||
|
|
||||||
|
// RegisterMigrateModel 注册用于数据库迁移的数据库模型
|
||||||
|
func RegisterMigrateModel(model interface{}) {
|
||||||
|
migrateModels = append(migrateModels, &model)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMigrateModels 获取用于数据库迁移的数据库模型
|
||||||
|
func getMigrateModels() []interface{} {
|
||||||
|
return migrateModels
|
||||||
|
}
|
||||||
134
math/gaussian.go
Normal file
134
math/gaussian.go
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// prop
|
||||||
|
//mean: the mean (μ) of the distribution
|
||||||
|
//variance: the variance (σ^2) of the distribution
|
||||||
|
//standardDeviation: the standard deviation (σ) of the distribution
|
||||||
|
|
||||||
|
// combination
|
||||||
|
|
||||||
|
type Gaussian struct {
|
||||||
|
mean float64
|
||||||
|
variance float64
|
||||||
|
standardDeviation float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGaussian(mean, variance float64) *Gaussian {
|
||||||
|
if variance <= 0.0 {
|
||||||
|
panic("error")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Gaussian{
|
||||||
|
mean: mean,
|
||||||
|
variance: variance,
|
||||||
|
standardDeviation: math.Sqrt(float64(variance)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erfc Complementary error function
|
||||||
|
// From Numerical Recipes in C 2e p221
|
||||||
|
func Erfc(x float64) float64 {
|
||||||
|
z := math.Abs(x)
|
||||||
|
t := 1 / (1 + z/2)
|
||||||
|
r := t * math.Exp(-z*z-1.26551223+t*(1.00002368+
|
||||||
|
t*(0.37409196+t*(0.09678418+t*(-0.18628806+
|
||||||
|
t*(0.27886807+t*(-1.13520398+t*(1.48851587+
|
||||||
|
t*(-0.82215223+t*0.17087277)))))))))
|
||||||
|
if x >= 0 {
|
||||||
|
return r
|
||||||
|
} else {
|
||||||
|
return 2 - r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ierfc Inverse complementary error function
|
||||||
|
// From Numerical Recipes 3e p265
|
||||||
|
func Ierfc(x float64) float64 {
|
||||||
|
if x >= 2 {
|
||||||
|
return -100
|
||||||
|
}
|
||||||
|
if x <= 0 {
|
||||||
|
return 100
|
||||||
|
}
|
||||||
|
var xx float64
|
||||||
|
if x < 1 {
|
||||||
|
xx = x
|
||||||
|
} else {
|
||||||
|
xx = 2 - x
|
||||||
|
}
|
||||||
|
t := math.Sqrt(-2 * math.Log(xx/2))
|
||||||
|
r := -0.70711 * ((2.30753+t*0.27061)/
|
||||||
|
(1+t*(0.99229+t*0.04481)) - t)
|
||||||
|
|
||||||
|
for j := 0; j < 2; j++ {
|
||||||
|
e := Erfc(r) - xx
|
||||||
|
r += e / (1.12837916709551257*math.Exp(-(r*r)) - r*e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if x < 1 {
|
||||||
|
return r
|
||||||
|
} else {
|
||||||
|
return -r
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromPrecisionMean Construct a new distribution from the precision and precisionmean
|
||||||
|
func fromPrecisionMean(precision, precisionmean float64) *Gaussian {
|
||||||
|
return NewGaussian(precisionmean/precision, 1/precision)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// PROB
|
||||||
|
|
||||||
|
// Pdf pdf(x): the probability density function, which describes the probability
|
||||||
|
// of a random variable taking on the value x
|
||||||
|
func (g *Gaussian) Pdf(x float64) float64 {
|
||||||
|
m := g.standardDeviation * math.Sqrt(2*math.Pi)
|
||||||
|
e := math.Exp(-math.Pow(x-g.mean, 2) / (2 * g.variance))
|
||||||
|
return e / m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cdf cdf(x): the cumulative distribution function,
|
||||||
|
// which describes the probability of a random
|
||||||
|
// variable falling in the interval (−∞, x]
|
||||||
|
func (g *Gaussian) Cdf(x float64) float64 {
|
||||||
|
return 0.5 * Erfc(-(x-g.mean)/(g.standardDeviation*math.Sqrt(2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ppf ppf(x): the percent point function, the inverse of cdf
|
||||||
|
func (g *Gaussian) Ppf(x float64) float64 {
|
||||||
|
return g.mean - g.standardDeviation*math.Sqrt(2)*Ierfc(2*x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add add(d): returns the result of adding this and the given distribution
|
||||||
|
func (g *Gaussian) Add(d *Gaussian) *Gaussian {
|
||||||
|
return NewGaussian(g.mean+d.mean, g.variance+d.variance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub sub(d): returns the result of subtracting this and the given distribution
|
||||||
|
func (g *Gaussian) Sub(d *Gaussian) *Gaussian {
|
||||||
|
return NewGaussian(g.mean-d.mean, g.variance+d.variance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale scale(c): returns the result of scaling this distribution by the given constant
|
||||||
|
func (g *Gaussian) Scale(c float64) *Gaussian {
|
||||||
|
return NewGaussian(g.mean*c, g.variance*c*c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mul mul(d): returns the product distribution of this and the given distribution. If a constant is passed in the distribution is scaled.
|
||||||
|
func (g *Gaussian) Mul(d *Gaussian) *Gaussian {
|
||||||
|
precision := 1 / g.variance
|
||||||
|
dprecision := 1 / d.variance
|
||||||
|
return fromPrecisionMean(precision+dprecision, precision*g.mean+dprecision*d.mean)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Div div(d): returns the quotient distribution of this and the given distribution. If a constant is passed in the distribution is scaled by 1/d.
|
||||||
|
func (g *Gaussian) Div(d *Gaussian) *Gaussian {
|
||||||
|
precision := 1 / g.variance
|
||||||
|
dprecision := 1 / d.variance
|
||||||
|
return fromPrecisionMean(precision-dprecision, precision*g.mean-dprecision*d.mean)
|
||||||
|
}
|
||||||
47
math/gaussian_test.go
Normal file
47
math/gaussian_test.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGaussian(t *testing.T) {
|
||||||
|
g := NewGaussian(3.0, 1)
|
||||||
|
|
||||||
|
fmt.Printf("g: %#v\n", g)
|
||||||
|
fmt.Printf("pdf: %f\n", g.Pdf(5))
|
||||||
|
fmt.Printf("cdf: %f\n", g.Cdf(2))
|
||||||
|
fmt.Printf("ppf: %f\n", g.Ppf(5))
|
||||||
|
|
||||||
|
d := NewGaussian(0, 1)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Pdf(-2), 0.053991)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Pdf(-1), 0.241971)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Pdf(0), 0.398942)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Pdf(1), 0.241971)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Pdf(2), 0.053991)
|
||||||
|
|
||||||
|
fmt.Printf("cdf: %f, %f\n", d.Cdf(-1.28155), 0.1)
|
||||||
|
fmt.Printf("cdf: %f, %f\n", d.Cdf(-0.67499), 0.25)
|
||||||
|
fmt.Printf("cdf: %f, %f\n", d.Cdf(0), 0.5)
|
||||||
|
fmt.Printf("cdf: %f, %f\n", d.Cdf(0.67499), 0.75)
|
||||||
|
fmt.Printf("cdf: %f, %f\n", d.Cdf(1.28155), 0.9)
|
||||||
|
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Ppf(0.1), -1.28155)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Ppf(0.25), -0.67499)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Ppf(0.5), 0.0)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Ppf(0.75), 0.67449)
|
||||||
|
fmt.Printf("ppf: %f, %f\n", d.Ppf(0.9), 1.28155)
|
||||||
|
|
||||||
|
d = d.Mul(NewGaussian(0, 1))
|
||||||
|
fmt.Printf("Mul: %#v\n", d)
|
||||||
|
fmt.Printf("%#v\n%#v", NewGaussian(1, 1).Scale(2), NewGaussian(2, 4))
|
||||||
|
|
||||||
|
d = NewGaussian(1, 1).Div(NewGaussian(1, 2))
|
||||||
|
fmt.Printf("div\n")
|
||||||
|
fmt.Printf("%#v\n%#v\n", d, NewGaussian(1, 2))
|
||||||
|
fmt.Printf("%#v\n%#v\n", NewGaussian(1, 1).Scale(1/(1.0/2.0)), NewGaussian(2, 4))
|
||||||
|
|
||||||
|
fmt.Printf("ADD:\n%#v\n%#v\n", NewGaussian(1, 1).Add(NewGaussian(1, 2)), NewGaussian(2, 3))
|
||||||
|
fmt.Printf("SUB:\n%#v\n%#v\n", NewGaussian(1, 1).Sub(NewGaussian(1, 2)), NewGaussian(0, 3))
|
||||||
|
fmt.Printf("SCALE:\n%#v\n%#v\n", NewGaussian(1, 1).Scale(2), NewGaussian(2, 4))
|
||||||
|
}
|
||||||
44
math/math.go
Normal file
44
math/math.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sign 符号函数(Sign function,简称sgn)是一个逻辑函数,用以判断实数的正负号。为避免和英文读音相似的正弦函数(sine)混淆,它亦称为Signum function。
|
||||||
|
func Sign[T int | int8 | int16 | int32 | int64 | float32 | float64](x T) T {
|
||||||
|
switch {
|
||||||
|
case x < 0: // x < 0 : -1
|
||||||
|
return -1
|
||||||
|
case x > 0: // x > 0 : +1
|
||||||
|
return +1
|
||||||
|
default: // x == 0 : 0
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mean 计算给定数据的平均值
|
||||||
|
func Mean(num []float64) float64 {
|
||||||
|
var count = len(num)
|
||||||
|
var sum float64 = 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
sum += num[i]
|
||||||
|
}
|
||||||
|
return sum / float64(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variance 使用平均值计算给定数据的方差
|
||||||
|
func Variance(mean float64, num []float64) float64 {
|
||||||
|
var count = len(num)
|
||||||
|
var variance float64 = 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
variance += math.Pow(num[i]-mean, 2)
|
||||||
|
}
|
||||||
|
return variance / float64(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StandardDeviation 使用方差计算给定数据的标准偏差
|
||||||
|
func StandardDeviation(num []float64) float64 {
|
||||||
|
var mean = Mean(num)
|
||||||
|
var variance = Variance(mean, num)
|
||||||
|
return math.Sqrt(variance)
|
||||||
|
}
|
||||||
30
math/math_test.go
Normal file
30
math/math_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSign(t *testing.T) {
|
||||||
|
assert.True(t, Sign(2) == 1)
|
||||||
|
assert.True(t, Sign(-2) == -1)
|
||||||
|
assert.True(t, Sign(0) == 0)
|
||||||
|
|
||||||
|
assert.True(t, Sign(int64(2)) == 1)
|
||||||
|
assert.True(t, Sign(int64(-2)) == -1)
|
||||||
|
assert.True(t, Sign(int64(0)) == 0)
|
||||||
|
|
||||||
|
assert.True(t, Sign(float32(2)) == 1)
|
||||||
|
assert.True(t, Sign(float32(-2)) == -1)
|
||||||
|
assert.True(t, Sign(float32(0)) == 0)
|
||||||
|
|
||||||
|
assert.True(t, Sign(float64(2)) == 1)
|
||||||
|
assert.True(t, Sign(float64(-2)) == -1)
|
||||||
|
assert.True(t, Sign(float64(0)) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStandardDeviation(t *testing.T) {
|
||||||
|
assert.Equal(t, StandardDeviation([]float64{3, 5, 9, 1, 8, 6, 58, 9, 4, 10}), 15.8117045254457)
|
||||||
|
assert.Equal(t, StandardDeviation([]float64{1, 3, 5, 7, 9, 11, 2, 4, 6, 8}), 3.0397368307141326)
|
||||||
|
}
|
||||||
6
tag.bat
6
tag.bat
@@ -1,6 +1,8 @@
|
|||||||
git tag v1.1.9
|
git tag v1.1.11
|
||||||
git tag bank_card/v1.1.1
|
git tag bank_card/v1.1.1
|
||||||
git tag entgo/v1.1.12
|
|
||||||
git tag geoip/v1.1.1
|
git tag geoip/v1.1.1
|
||||||
|
|
||||||
|
git tag entgo/v1.1.13
|
||||||
|
git tag gorm/v1.1.0
|
||||||
|
|
||||||
git push origin --tags
|
git push origin --tags
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package util
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
"github.com/tx7do/go-utils/trans"
|
"github.com/tx7do/go-utils/trans"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -114,3 +116,19 @@ func TimeToDateString(tm *time.Time) *string {
|
|||||||
}
|
}
|
||||||
return trans.String(tm.Format(DateLayout))
|
return trans.String(tm.Format(DateLayout))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TimestamppbToTime timestamppb.Timestamp -> time.Time
|
||||||
|
func TimestamppbToTime(tm *timestamppb.Timestamp) *time.Time {
|
||||||
|
if tm != nil {
|
||||||
|
return trans.Ptr(tm.AsTime())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeToTimestamppb time.Time -> timestamppb.Timestamp
|
||||||
|
func TimeToTimestamppb(tm *time.Time) *timestamppb.Timestamp {
|
||||||
|
if tm != nil {
|
||||||
|
return timestamppb.New(*tm)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user