Compare commits

..

21 Commits

Author SHA1 Message Date
14d2d747f6 add minus of start parameter support for gstr.Substr, like the substr function in PHP (#2297)
* Make the substr like the substr in PHP

Make the substr like the substr in PHP

* Update gstr_z_unit_test.go

* Update gstr_z_unit_test.go

* Make the SubStrRune like the mb_substr in PHP

Make the SubStrRune like the mb_substr in PHP

* Update gstr_z_unit_test.go

* Update gstr_z_unit_test.go

* Update gins_z_unit_view_test.go

* Update gview_z_unit_test.go
2022-11-16 10:10:59 +08:00
73dc8c9c4b fix cache issue in Count/Value functions for gdb.Model (#2300)
* add Tag* functions to retreive most commonly used tag value from struct field for package gstructs; use description tag as default value if brief is empty for gcmd.Argument

* fix cache issue in Count/Value functions for gdb.Model

* add more ut case for package gdb

* version updates
2022-11-16 10:04:49 +08:00
576f1a798c add Tag* functions to retreive most commonly used tag value from struct field for package gstructs; use description tag as default value if brief is empty for gcmd.Argument (#2299) 2022-11-15 17:05:34 +08:00
78fa2d2e3b fix: update szenius/set-timezone@v1.1 (#2293) 2022-11-14 19:58:17 +08:00
9402cc8c6a fix /* router supported for handler of package ghttp; fix json tag name issue when it contains , for package goai; add proxy example for http server (#2294)
* fix  router supported for handler of package ghttp; fix json tag name issue when it contains  for package goai

* add proxy example for http server
2022-11-14 19:57:39 +08:00
7d1a508ea9 improve ut case for package gcache/gpool (#2290)
* improve ut case for package gcache/gpool

* up
2022-11-12 10:49:48 +08:00
b84034b667 fix: gcache MustGetOrSetFunc error (#2291) 2022-11-10 20:34:48 +08:00
84b7cbd992 ci: action update (#2289) 2022-11-10 20:26:57 +08:00
bc8ca912ce fix: gcron check if the predefined patterns fail (#2288) 2022-11-10 19:59:09 +08:00
b61baa1efc add ut cases for package gconv part2 (#2282) 2022-11-10 19:58:03 +08:00
c4a5bc8584 style(test): Unify the indentation format of SQL strings in clickhouse_test (#2277)
style(test): Unify the indentation format of SQL strings
2022-11-10 19:57:15 +08:00
8c71d579b5 add command fix and up (#2280) 2022-11-10 19:56:12 +08:00
2e8d8f63ff fix IsSubDomain method error (#2283)
Co-authored-by: weiwei3 <weiwei3@37.com>
2022-11-10 19:47:43 +08:00
91b94878d3 fix used schema not change in nested transaction when used different schemas (#2279)
* fix used schema not change in nested transaction between different schemas

* up

Co-authored-by: houseme <housemecn@gmail.com>
2022-11-10 09:55:08 +08:00
b000aa3dfe add supervisor for package grpool (#2252)
* add supervisor for package grpool

* up
2022-11-08 19:00:16 +08:00
582c6eaef9 gtest model unit test (#2267) 2022-11-07 17:56:33 +08:00
4f4109cdb6 fix typo for comments (#2268)
* Modify comment syntax error

* Modify comment syntax error
2022-11-07 17:55:49 +08:00
9f12673631 add ut cases for package gconv (#2272)
* improve gconv.go code coverage

* improve gconv_convert.go code coverage

* improve gconv_float.go code coverage

* improve gconv_map.go code coverage

* improve gconv_maps.go code coverage

* improve gconv_maptomap.go code coverage

* improve gconv_maptomaps.go code coverage
2022-11-07 17:53:51 +08:00
d37b75442d feat: modify sql count value int64 (#2266) 2022-11-07 17:52:25 +08:00
ee58255418 move common used tag from packages to package gtag for maintainability (#2256)
* move common used tag from packages to package gtag for maintainability

* move common used tag from packages to package gtag for maintainability

Co-authored-by: houseme <housemecn@gmail.com>
2022-11-07 17:51:37 +08:00
033ba588c9 fix redis ci yaml (#2269) 2022-11-05 10:23:52 +08:00
96 changed files with 2249 additions and 865 deletions

View File

@ -29,6 +29,14 @@ for file in `find . -name go.mod`; do
fi
fi
# package cmd/gf needs golang >= v1.18
if [ "gf" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.18"; then
echo "ignore example as go version: $(go version)"
continue 1
fi
fi
cd $dirpath
go mod tidy
go build ./...

View File

@ -133,13 +133,14 @@ jobs:
goarch: [ "386", "amd64" ]
steps:
# TODO: szenius/set-timezone update to node16
- name: Setup Timezone
uses: szenius/set-timezone@v1.0
uses: szenius/set-timezone@v1.1
with:
timezoneLinux: "Asia/Shanghai"
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Start Apollo Containers
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build
@ -154,7 +155,7 @@ jobs:
uses: medyagh/setup-minikube@master
- name: Setup Golang ${{ matrix.go-version }}
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
@ -186,7 +187,7 @@ jobs:
run: docker-compose -f ".github/workflows/nacos/docker-compose.yml" down
- name: Report Coverage
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v3
with:
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}

View File

@ -3,7 +3,7 @@ version: "2"
services:
redis-master:
container_name: redis-master
image: "loads/redis:7.0"
image: "loads/redis:7.0-sentinel"
environment:
- REDIS_REPLICATION_MODE=master
- REDIS_PASSWORD=111111
@ -12,7 +12,7 @@ services:
redis-slave1:
container_name: redis-slave1
image: "loads/redis:7.0"
image: "loads/redis:7.0-sentinel"
environment:
- REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master
@ -27,7 +27,7 @@ services:
redis-slave2:
container_name: redis-slave2
image: "loads/redis:7.0"
image: "loads/redis:7.0-sentinel"
environment:
- REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master

View File

@ -275,9 +275,8 @@ linters-settings:
# Apply the rewrite rules to the source before reformatting.
# https://pkg.go.dev/cmd/gofmt
# Default: []
rewrite-rules:
rewrite-rules: [ ]
# - pattern: 'interface{}'
# replacement: 'any'
# - pattern: 'a[b:len(a)]'
# replacement: 'a[b:]'

View File

@ -1,15 +1,53 @@
module github.com/gogf/gf/cmd/gf/v2
go 1.16
go 1.18
require (
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.1.0
github.com/gogf/gf/v2 v2.1.0
github.com/gogf/gf/v2 v2.2.2
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/tools v0.1.11
golang.org/x/tools v0.2.0
)
require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/denisenkom/go-mssqldb v0.11.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/glebarez/go-sqlite v1.17.3 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/lib/pq v1.10.4 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.16.8 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.1.1 // indirect
modernc.org/sqlite v1.17.3 // indirect
)
replace (

View File

@ -1,5 +1,6 @@
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -99,7 +100,6 @@ github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMT
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
@ -110,23 +110,22 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -146,29 +145,28 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -192,8 +190,9 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=

View File

@ -0,0 +1,99 @@
package cmd
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
)
var (
Fix = cFix{}
)
type cFix struct {
g.Meta `name:"fix" brief:"auto fixing codes after upgrading to new GoFrame version" usage:"gf fix" `
}
type cFixInput struct {
g.Meta `name:"fix"`
}
type cFixOutput struct{}
type cFixItem struct {
Version string
Func func(version string) error
}
func (c cFix) Index(ctx context.Context, in cFixInput) (out *cFixOutput, err error) {
mlog.Print(`start auto fixing...`)
defer mlog.Print(`done!`)
err = c.doFix()
return
}
func (c cFix) doFix() (err error) {
version, err := c.getVersion()
if err != nil {
mlog.Fatal(err)
}
if version == "" {
mlog.Print(`no GoFrame usage found, exit fixing`)
return
}
mlog.Debugf(`current GoFrame version found "%s"`, version)
var items = []cFixItem{
{Version: "v2.3", Func: c.doFixV23},
}
for _, item := range items {
if gstr.CompareVersionGo(version, item.Version) < 0 {
mlog.Debugf(
`current GoFrame version "%s" is lesser than "%s", nothing to do`,
version, item.Version,
)
continue
}
if err = item.Func(version); err != nil {
return
}
}
return
}
// doFixV23 fixes code when upgrading to GoFrame v2.3.
func (c cFix) doFixV23(version string) error {
replaceFunc := func(path, content string) string {
content = gstr.Replace(content, "*gdb.TX", "gdb.TX")
return content
}
return gfile.ReplaceDirFunc(replaceFunc, ".", "*.go", true)
}
func (c cFix) getVersion() (string, error) {
var (
err error
path = "go.mod"
version string
)
if !gfile.Exists(path) {
return "", gerror.Newf(`"%s" not found in current working directory`, path)
}
err = gfile.ReadLines(path, func(line string) error {
array := gstr.SplitAndTrim(line, " ")
if len(array) > 0 {
if array[0] == gfPackage {
version = array[1]
}
}
return nil
})
if err != nil {
mlog.Fatal(err)
}
return version, nil
}

View File

@ -0,0 +1,121 @@
package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
)
var (
Up = cUp{}
)
type cUp struct {
g.Meta `name:"up" brief:"upgrade GoFrame version/tool to latest one in current project" eg:"{cUpEg}" `
}
const (
gfPackage = `github.com/gogf/gf/v2`
cUpEg = `
gf up
gf up -a
gf up -c
gf up -f -c
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cUpEg`: cUpEg,
})
}
type cUpInput struct {
g.Meta `name:"up" config:"gfcli.up"`
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
Fix bool `name:"fix" short:"f" brief:"auto fix codes" orphan:"true"`
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool (not supported yet)" orphan:"true"`
}
type cUpOutput struct{}
func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error) {
defer mlog.Print(`done!`)
if in.All {
in.Cli = true
in.Fix = true
}
if err = c.doUpgradeVersion(ctx); err != nil {
return nil, err
}
if in.Fix {
if err = c.doAutoFixing(ctx); err != nil {
return nil, err
}
}
//if in.Cli {
// if err = c.doUpgradeCLI(ctx); err != nil {
// return nil, err
// }
//}
return
}
func (c cUp) doUpgradeVersion(ctx context.Context) (err error) {
mlog.Print(`start upgrading version...`)
var (
dir = gfile.Pwd()
temp string
path = gfile.Join(dir, "go.mod")
)
for {
if gfile.Exists(path) {
var packages []string
err = gfile.ReadLines(path, func(line string) error {
line = gstr.Trim(line)
if gstr.HasPrefix(line, gfPackage) {
pkg := gstr.Explode(" ", line)[0]
packages = append(packages, pkg)
}
return nil
})
if err != nil {
return
}
for _, pkg := range packages {
mlog.Printf(`upgrading %s`, pkg)
command := fmt.Sprintf(`go get -u %s@latest`, pkg)
if err = gproc.ShellRun(ctx, command); err != nil {
return
}
}
return
}
temp = gfile.Dir(dir)
if temp == "" || temp == dir {
return
}
dir = temp
path = gfile.Join(dir, "go.mod")
}
}
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
mlog.Print(`start upgrading cli...`)
return
}
func (c cUp) doAutoFixing(ctx context.Context) (err error) {
mlog.Print(`start auto fixing...`)
err = cFix{}.doFix()
return
}

View File

@ -53,7 +53,9 @@ func main() {
panic(err)
}
err = command.AddObject(
cmd.Up,
cmd.Env,
cmd.Fix,
cmd.Run,
cmd.Gen,
cmd.Tpl,

View File

@ -53,7 +53,7 @@ func NewArraySize(size int, cap int, safe ...bool) *Array {
}
}
// NewArrayRange creates and returns a array by a range from `start` to `end`
// NewArrayRange creates and returns an array by a range from `start` to `end`
// with step value `step`.
func NewArrayRange(start, end, step int, safe ...bool) *Array {
if step == 0 {

View File

@ -45,7 +45,7 @@ func NewIntArraySize(size int, cap int, safe ...bool) *IntArray {
}
}
// NewIntArrayRange creates and returns a array by a range from `start` to `end`
// NewIntArrayRange creates and returns an array by a range from `start` to `end`
// with step value `step`.
func NewIntArrayRange(start, end, step int, safe ...bool) *IntArray {
if step == 0 {

View File

@ -55,7 +55,7 @@ func NewSortedArraySize(cap int, comparator func(a, b interface{}) int, safe ...
}
}
// NewSortedArrayRange creates and returns a array by a range from `start` to `end`
// NewSortedArrayRange creates and returns an array by a range from `start` to `end`
// with step value `step`.
func NewSortedArrayRange(start, end, step int, comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
if step == 0 {

View File

@ -56,7 +56,7 @@ func NewSortedIntArraySize(cap int, safe ...bool) *SortedIntArray {
}
}
// NewSortedIntArrayRange creates and returns a array by a range from `start` to `end`
// NewSortedIntArrayRange creates and returns an array by a range from `start` to `end`
// with step value `step`.
func NewSortedIntArrayRange(start, end, step int, safe ...bool) *SortedIntArray {
if step == 0 {

View File

@ -179,6 +179,6 @@ func ExamplePool_Close() {
// wait for pool close
time.Sleep(time.Second * 1)
// Output:
// May Output:
// Close The Pool
}

View File

@ -184,7 +184,7 @@ func (set *Set) Clear() {
set.mu.Unlock()
}
// Slice returns the a of items of the set as slice.
// Slice returns the an of items of the set as slice.
func (set *Set) Slice() []interface{} {
set.mu.RLock()
var (

View File

@ -165,7 +165,7 @@ func (set *IntSet) Clear() {
set.mu.Unlock()
}
// Slice returns the a of items of the set as slice.
// Slice returns the an of items of the set as slice.
func (set *IntSet) Slice() []int {
set.mu.RLock()
var (

View File

@ -178,7 +178,7 @@ func (set *StrSet) Clear() {
set.mu.Unlock()
}
// Slice returns the a of items of the set as slice.
// Slice returns the an of items of the set as slice.
func (set *StrSet) Slice() []string {
set.mu.RLock()
var (

View File

@ -313,7 +313,7 @@ func ExampleIntSet_Size() {
// 4
}
// Slice returns the a of items of the set as slice.
// Slice returns the an of items of the set as slice.
func ExampleIntSet_Slice() {
s1 := gset.NewIntSet()
s1.Add([]int{1, 2, 3, 4}...)

View File

@ -325,7 +325,7 @@ func ExampleStrSet_Size() {
// 4
}
// Slice returns the a of items of the set as slice.
// Slice returns the an of items of the set as slice.
func ExampleStrSet_Slice() {
s1 := gset.NewStrSet(true)
s1.Add([]string{"a", "b", "c", "d"}...)

View File

@ -9,4 +9,62 @@ require (
k8s.io/client-go v0.25.2
)
require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.70.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)
replace github.com/gogf/gf/v2 => ../../../

View File

@ -13,18 +13,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -43,31 +31,15 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -77,9 +49,6 @@ github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -87,31 +56,22 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
@ -121,7 +81,6 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@ -132,13 +91,10 @@ github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@ -146,8 +102,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -161,15 +115,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -179,21 +129,14 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -201,27 +144,14 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -256,17 +186,13 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@ -280,25 +206,16 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@ -308,39 +225,29 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -363,8 +270,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@ -373,11 +278,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -408,20 +309,9 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -429,16 +319,6 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -450,9 +330,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -483,36 +361,15 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -523,10 +380,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -568,7 +422,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -576,22 +429,9 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -612,18 +452,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -655,39 +483,13 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -700,20 +502,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -726,7 +514,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -741,7 +528,6 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -765,14 +551,11 @@ k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs=
k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA=
k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo=
k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -25,6 +25,7 @@ import (
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
"github.com/google/uuid"
"github.com/shopspring/decimal"
@ -49,7 +50,7 @@ const (
filterTypePattern = `(?i)^UPDATE|DELETE`
replaceSchemaPattern = `@(.+?)/([\w\.\-]+)+`
needParsedSqlInCtx gctx.StrKey = "NeedParsedSql"
OrmTagForStruct = "orm"
OrmTagForStruct = gtag.ORM
driverName = "clickhouse"
)

View File

@ -25,99 +25,99 @@ import (
const (
sqlVisitsDDL = `
CREATE TABLE IF NOT EXISTS visits (
id UInt64,
duration Float64,
url String,
created DateTime
) ENGINE = MergeTree()
PRIMARY KEY id
ORDER BY id
CREATE TABLE IF NOT EXISTS visits (
id UInt64,
duration Float64,
url String,
created DateTime
) ENGINE = MergeTree()
PRIMARY KEY id
ORDER BY id
`
dimSqlDDL = `
CREATE TABLE IF NOT EXISTS dim (
"code" String COMMENT '编码',
"translation" String COMMENT '译文',
"superior" UInt64 COMMENT '上级ID',
"row_number" UInt16 COMMENT '行号',
"is_active" UInt8 COMMENT '是否激活',
"is_preset" UInt8 COMMENT '是否预置',
"category" String COMMENT '类别',
"tree_path" Array(String) COMMENT '树路径',
"id" UInt64 COMMENT '代理主键ID',
"scd" UInt64 COMMENT '缓慢变化维ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位',
"created_by" UInt64 COMMENT '创建者ID',
"created_at" DateTime64(3,'Asia/Shanghai') COMMENT '创建时间',
"updated_by" UInt64 COMMENT '最后修改者ID',
"updated_at" DateTime64(3,'Asia/Shanghai') COMMENT '最后修改时间',
"updated_tick" UInt16 COMMENT '累计修改次数'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("id","scd")
COMMENT '会计准则';
CREATE TABLE IF NOT EXISTS dim (
"code" String COMMENT '编码',
"translation" String COMMENT '译文',
"superior" UInt64 COMMENT '上级ID',
"row_number" UInt16 COMMENT '行号',
"is_active" UInt8 COMMENT '是否激活',
"is_preset" UInt8 COMMENT '是否预置',
"category" String COMMENT '类别',
"tree_path" Array(String) COMMENT '树路径',
"id" UInt64 COMMENT '代理主键ID',
"scd" UInt64 COMMENT '缓慢变化维ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位',
"created_by" UInt64 COMMENT '创建者ID',
"created_at" DateTime64(3,'Asia/Shanghai') COMMENT '创建时间',
"updated_by" UInt64 COMMENT '最后修改者ID',
"updated_at" DateTime64(3,'Asia/Shanghai') COMMENT '最后修改时间',
"updated_tick" UInt16 COMMENT '累计修改次数'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("id","scd")
COMMENT '会计准则';
`
dimSqlDML = `
insert into dim (code, translation, superior, row_number, is_active, is_preset, category, tree_path, id, scd, version, sign, created_by, created_at, updated_by, updated_at, updated_tick)
values ('CN', '{"zh_CN":"中国大陆会计准则","en_US":"Chinese mainland accounting legislation"}', 0, 1, 1, 1, 1, '[''CN'']', 607972403489804288, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0),
('HK', '{"zh_CN":"中国香港会计准则","en_US":"Chinese Hong Kong accounting legislation"}', 0, 2, 1, 1, 1, '[''HK'']', 607972558544834566, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0);
insert into dim (code, translation, superior, row_number, is_active, is_preset, category, tree_path, id, scd, version, sign, created_by, created_at, updated_by, updated_at, updated_tick)
values ('CN', '{"zh_CN":"中国大陆会计准则","en_US":"Chinese mainland accounting legislation"}', 0, 1, 1, 1, 1, '[''CN'']', 607972403489804288, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0),
('HK', '{"zh_CN":"中国香港会计准则","en_US":"Chinese Hong Kong accounting legislation"}', 0, 2, 1, 1, 1, '[''HK'']', 607972558544834566, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0);
`
factSqlDDL = `
CREATE TABLE IF NOT EXISTS fact (
"adjustment_level" UInt64 COMMENT '调整层ID',
"data_version" UInt64 COMMENT '数据版本ID',
"accounting_legislation" UInt64 COMMENT '会计准则ID',
"fiscal_year" UInt16 COMMENT '会计年度',
"fiscal_period" UInt8 COMMENT '会计期间',
"fiscal_year_period" UInt32 COMMENT '会计年度期间',
"legal_entity" UInt64 COMMENT '法人主体ID',
"cost_center" UInt64 COMMENT '成本中心ID',
"legal_entity_partner" UInt64 COMMENT '内部关联方ID',
"financial_posting" UInt64 COMMENT '凭证头ID',
"line" UInt16 COMMENT '行号',
"general_ledger_account" UInt64 COMMENT '总账科目ID',
"debit" Decimal64(9) COMMENT '借方金额',
"credit" Decimal64(9) COMMENT '贷方金额',
"transaction_currency" UInt64 COMMENT '交易币种ID',
"debit_tc" Decimal64(9) COMMENT '借方金额(交易币种)',
"credit_tc" Decimal64(9) COMMENT '贷方金额(交易币种)',
"posting_date" Date32 COMMENT '过账日期',
"gc_year" UInt16 COMMENT '公历年',
"gc_quarter" UInt8 COMMENT '公历季',
"gc_month" UInt8 COMMENT '公历月',
"gc_week" UInt8 COMMENT '公历周',
"raw_info" String COMMENT '源信息',
"summary" String COMMENT '摘要',
"id" UInt64 COMMENT '代理主键ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period","financial_posting","line")
PARTITION BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period")
COMMENT '数据主表';
CREATE TABLE IF NOT EXISTS fact (
"adjustment_level" UInt64 COMMENT '调整层ID',
"data_version" UInt64 COMMENT '数据版本ID',
"accounting_legislation" UInt64 COMMENT '会计准则ID',
"fiscal_year" UInt16 COMMENT '会计年度',
"fiscal_period" UInt8 COMMENT '会计期间',
"fiscal_year_period" UInt32 COMMENT '会计年度期间',
"legal_entity" UInt64 COMMENT '法人主体ID',
"cost_center" UInt64 COMMENT '成本中心ID',
"legal_entity_partner" UInt64 COMMENT '内部关联方ID',
"financial_posting" UInt64 COMMENT '凭证头ID',
"line" UInt16 COMMENT '行号',
"general_ledger_account" UInt64 COMMENT '总账科目ID',
"debit" Decimal64(9) COMMENT '借方金额',
"credit" Decimal64(9) COMMENT '贷方金额',
"transaction_currency" UInt64 COMMENT '交易币种ID',
"debit_tc" Decimal64(9) COMMENT '借方金额(交易币种)',
"credit_tc" Decimal64(9) COMMENT '贷方金额(交易币种)',
"posting_date" Date32 COMMENT '过账日期',
"gc_year" UInt16 COMMENT '公历年',
"gc_quarter" UInt8 COMMENT '公历季',
"gc_month" UInt8 COMMENT '公历月',
"gc_week" UInt8 COMMENT '公历周',
"raw_info" String COMMENT '源信息',
"summary" String COMMENT '摘要',
"id" UInt64 COMMENT '代理主键ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period","financial_posting","line")
PARTITION BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period")
COMMENT '数据主表';
`
factSqlDML = `
insert into fact (adjustment_level, data_version, accounting_legislation, fiscal_year, fiscal_period, fiscal_year_period, legal_entity, cost_center, legal_entity_partner, financial_posting, line, general_ledger_account, debit, credit, transaction_currency, debit_tc, credit_tc, posting_date, gc_year, gc_quarter, gc_month, gc_week, raw_info, summary, id, version, sign)
values (607970943242866688, 607973669943119880, 607972403489804288, 2022, 3, 202203, 607974511316307985, 0, 607976190010986520, 607996702456025136, 1, 607985607569838111, 8674.39, 0, 607974898261823505, 8674.39, 0, '2022-03-05', 2022, 1, 3, 11, '{}', '摘要', 607992882741121073, 0, 0),
(607970943242866688, 607973669943119880, 607972403489804288, 2022, 4, 202204, 607974511316307985, 0, 607976190010986520, 607993586419503145, 1, 607985607569838111, 9999.88, 0, 607974898261823505, 9999.88, 0, '2022-04-10', 2022, 2, 4, 18, '{}', '摘要', 607996939140599857, 0, 0);
insert into fact (adjustment_level, data_version, accounting_legislation, fiscal_year, fiscal_period, fiscal_year_period, legal_entity, cost_center, legal_entity_partner, financial_posting, line, general_ledger_account, debit, credit, transaction_currency, debit_tc, credit_tc, posting_date, gc_year, gc_quarter, gc_month, gc_week, raw_info, summary, id, version, sign)
values (607970943242866688, 607973669943119880, 607972403489804288, 2022, 3, 202203, 607974511316307985, 0, 607976190010986520, 607996702456025136, 1, 607985607569838111, 8674.39, 0, 607974898261823505, 8674.39, 0, '2022-03-05', 2022, 1, 3, 11, '{}', '摘要', 607992882741121073, 0, 0),
(607970943242866688, 607973669943119880, 607972403489804288, 2022, 4, 202204, 607974511316307985, 0, 607976190010986520, 607993586419503145, 1, 607985607569838111, 9999.88, 0, 607974898261823505, 9999.88, 0, '2022-04-10', 2022, 2, 4, 18, '{}', '摘要', 607996939140599857, 0, 0);
`
expmSqlDDL = `
CREATE TABLE IF NOT EXISTS data_type (
Col1 UInt8 COMMENT '列1'
, Col2 Nullable(String) COMMENT '列2'
, Col3 FixedString(3) COMMENT '列3'
, Col4 String COMMENT '列4'
, Col5 Map(String, UInt8) COMMENT '列5'
, Col6 Array(String) COMMENT '列6'
, Col7 Tuple(String, UInt8, Array(Map(String, String))) COMMENT '列7'
, Col8 DateTime COMMENT '列8'
, Col9 UUID COMMENT '列9'
, Col10 DateTime COMMENT '列10'
, Col11 Decimal(9, 2) COMMENT '列11'
, Col12 Decimal(9, 2) COMMENT '列12'
) ENGINE = MergeTree()
PRIMARY KEY Col4
ORDER BY Col4
CREATE TABLE IF NOT EXISTS data_type (
Col1 UInt8 COMMENT '列1'
, Col2 Nullable(String) COMMENT '列2'
, Col3 FixedString(3) COMMENT '列3'
, Col4 String COMMENT '列4'
, Col5 Map(String, UInt8) COMMENT '列5'
, Col6 Array(String) COMMENT '列6'
, Col7 Tuple(String, UInt8, Array(Map(String, String))) COMMENT '列7'
, Col8 DateTime COMMENT '列8'
, Col9 UUID COMMENT '列9'
, Col10 DateTime COMMENT '列10'
, Col11 Decimal(9, 2) COMMENT '列11'
, Col12 Decimal(9, 2) COMMENT '列12'
) ENGINE = MergeTree()
PRIMARY KEY Col4
ORDER BY Col4
`
)

View File

@ -731,16 +731,157 @@ func Test_Model_Count(t *testing.T) {
t.AssertNil(err)
t.Assert(count, TableSize)
})
// gtest.C(t, func(t *gtest.T) {
// count, err := db.Model(table).Fields("id myid").Where("id>8").Count()
// t.AssertNil(err)
// t.Assert(count, 2)
// })
// gtest.C(t, func(t *gtest.T) {
// count, err := db.Model(table).As("u1").LeftJoin(table, "u2", "u2.id=u1.id").Fields("u2.id u2id").Where("u1.id>8").Count()
// t.AssertNil(err)
// t.Assert(count, 2)
// })
}
func Test_Model_Value_WithCache(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
value, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Value()
t.AssertNil(err)
t.Assert(value.Int(), 0)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.Model(table).Data(g.MapStrAny{
"id": 1,
"passport": fmt.Sprintf(`passport_%d`, 1),
"password": fmt.Sprintf(`password_%d`, 1),
"nickname": fmt.Sprintf(`nickname_%d`, 1),
}).Insert()
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
gtest.C(t, func(t *gtest.T) {
value, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Value()
t.AssertNil(err)
t.Assert(value.Int(), 1)
})
}
func Test_Model_Count_WithCache(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, 0)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.Model(table).Data(g.MapStrAny{
"id": 1,
"passport": fmt.Sprintf(`passport_%d`, 1),
"password": fmt.Sprintf(`password_%d`, 1),
"nickname": fmt.Sprintf(`nickname_%d`, 1),
}).Insert()
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, 1)
})
}
func Test_Model_Count_All_WithCache(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, 0)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.Model(table).Data(g.MapStrAny{
"id": 1,
"passport": fmt.Sprintf(`passport_%d`, 1),
"password": fmt.Sprintf(`password_%d`, 1),
"nickname": fmt.Sprintf(`nickname_%d`, 1),
}).Insert()
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, 1)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.Model(table).Data(g.MapStrAny{
"id": 2,
"passport": fmt.Sprintf(`passport_%d`, 2),
"password": fmt.Sprintf(`password_%d`, 2),
"nickname": fmt.Sprintf(`nickname_%d`, 2),
}).Insert()
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, 1)
})
}
func Test_Model_CountColumn_WithCache(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).CountColumn("id")
t.AssertNil(err)
t.Assert(count, 0)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.Model(table).Data(g.MapStrAny{
"id": 1,
"passport": fmt.Sprintf(`passport_%d`, 1),
"password": fmt.Sprintf(`password_%d`, 1),
"nickname": fmt.Sprintf(`nickname_%d`, 1),
}).Insert()
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).CountColumn("id")
t.AssertNil(err)
t.Assert(count, 1)
})
}
func Test_Model_Select(t *testing.T) {

View File

@ -7,4 +7,30 @@ require (
github.com/sijms/go-ora/v2 v2.4.20
)
require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
replace github.com/gogf/gf/v2 => ../../../

View File

@ -52,7 +52,7 @@ func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
}, nil
}
// Open creates and returns a underlying sql.DB object for sqlite.
// Open creates and returns an underlying sql.DB object for sqlite.
// https://github.com/glebarez/go-sqlite
func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) {
var (

View File

@ -118,7 +118,7 @@ type DB interface {
GetOne(ctx context.Context, sql string, args ...interface{}) (Record, error) // See Core.GetOne.
GetValue(ctx context.Context, sql string, args ...interface{}) (Value, error) // See Core.GetValue.
GetArray(ctx context.Context, sql string, args ...interface{}) ([]Value, error) // See Core.GetArray.
GetCount(ctx context.Context, sql string, args ...interface{}) (int, error) // See Core.GetCount.
GetCount(ctx context.Context, sql string, args ...interface{}) (int64, error) // See Core.GetCount.
GetScan(ctx context.Context, objPointer interface{}, sql string, args ...interface{}) error // See Core.GetScan.
Union(unions ...*Model) *Model // See Core.Union.
UnionAll(unions ...*Model) *Model // See Core.UnionAll.
@ -289,20 +289,23 @@ type CatchSQLManager struct {
DoCommit bool
}
type queryType int
const (
defaultModelSafe = false
defaultCharset = `utf8`
defaultProtocol = `tcp`
queryTypeNormal = 0
queryTypeCount = 1
unionTypeNormal = 0
unionTypeAll = 1
defaultMaxIdleConnCount = 10 // Max idle connection count in pool.
defaultMaxOpenConnCount = 0 // Max open connection count in pool. Default is no limit.
defaultMaxConnLifeTime = 30 * time.Second // Max lifetime for per connection in pool in seconds.
ctxTimeoutTypeExec = iota
ctxTimeoutTypeQuery
ctxTimeoutTypePrepare
defaultModelSafe = false
defaultCharset = `utf8`
defaultProtocol = `tcp`
queryTypeNormal queryType = 0
queryTypeCount queryType = 1
queryTypeValue queryType = 2
unionTypeNormal = 0
unionTypeAll = 1
defaultMaxIdleConnCount = 10 // Max idle connection count in pool.
defaultMaxOpenConnCount = 0 // Max open connection count in pool. Default is no limit.
defaultMaxConnLifeTime = 30 * time.Second // Max lifetime for per connection in pool in seconds.
ctxTimeoutTypeExec = 0
ctxTimeoutTypeQuery = 1
ctxTimeoutTypePrepare = 2
cachePrefixTableFields = `TableFields:`
cachePrefixSelectCache = `SelectCache:`
commandEnvKeyForDryRun = "gf.gdb.dryrun"

View File

@ -23,6 +23,7 @@ import (
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gutil"
)
// GetCore returns the underlying *Core object.
@ -124,25 +125,13 @@ func (c *Core) Close(ctx context.Context) (err error) {
// Master creates and returns a connection from master node if master-slave configured.
// It returns the default connection if master-slave not configured.
func (c *Core) Master(schema ...string) (*sql.DB, error) {
useSchema := ""
if len(schema) > 0 && schema[0] != "" {
useSchema = schema[0]
} else {
useSchema = c.schema
}
return c.getSqlDb(true, useSchema)
return c.getSqlDb(true, gutil.GetOrDefaultStr(c.schema, schema...))
}
// Slave creates and returns a connection from slave node if master-slave configured.
// It returns the default connection if master-slave not configured.
func (c *Core) Slave(schema ...string) (*sql.DB, error) {
useSchema := ""
if len(schema) > 0 && schema[0] != "" {
useSchema = schema[0]
} else {
useSchema = c.schema
}
return c.getSqlDb(false, useSchema)
return c.getSqlDb(false, gutil.GetOrDefaultStr(c.schema, schema...))
}
// GetAll queries and returns data records from database.
@ -241,7 +230,7 @@ func (c *Core) GetValue(ctx context.Context, sql string, args ...interface{}) (V
}
// GetCount queries and returns the count from database.
func (c *Core) GetCount(ctx context.Context, sql string, args ...interface{}) (int, error) {
func (c *Core) GetCount(ctx context.Context, sql string, args ...interface{}) (int64, error) {
// If the query fields do not contain function "COUNT",
// it replaces the sql string and adds the "COUNT" function to the fields.
if !gregex.IsMatchString(`(?i)SELECT\s+COUNT\(.+\)\s+FROM`, sql) {
@ -251,7 +240,7 @@ func (c *Core) GetCount(ctx context.Context, sql string, args ...interface{}) (i
if err != nil {
return 0, err
}
return value.Int(), nil
return value.Int64(), nil
}
// Union does "(SELECT xxx FROM xxx) UNION (SELECT xxx FROM xxx) ..." statement.

View File

@ -210,7 +210,14 @@ func (c *Core) SetMaxConnLifeTime(d time.Duration) {
func (c *Core) GetConfig() *ConfigNode {
internalData := c.GetInternalCtxDataFromCtx(c.db.GetCtx())
if internalData != nil && internalData.ConfigNode != nil {
return internalData.ConfigNode
// Note:
// It so here checks and returns the config from current DB,
// if different schemas between current DB and config.Name from context,
// for example, in nested transaction scenario, the context is passed all through the logic procedure,
// but the config.Name from context may be still the original one from the first transaction object.
if c.config.Name == internalData.ConfigNode.Name {
return internalData.ConfigNode
}
}
return c.config
}

View File

@ -43,7 +43,8 @@ func (c *Core) InjectInternalCtxData(ctx context.Context) context.Context {
return ctx
}
return context.WithValue(ctx, internalCtxDataKeyInCtx, &internalCtxData{
DB: c.db,
DB: c.db,
ConfigNode: c.config,
})
}

View File

@ -382,7 +382,7 @@ func (tx *TX) GetValue(sql string, args ...interface{}) (Value, error) {
}
// GetCount queries and returns the count from database.
func (tx *TX) GetCount(sql string, args ...interface{}) (int, error) {
func (tx *TX) GetCount(sql string, args ...interface{}) (int64, error) {
if !gregex.IsMatchString(`(?i)SELECT\s+COUNT\(.+\)\s+FROM`, sql) {
sql, _ = gregex.ReplaceString(`(?i)(SELECT)\s+(.+)\s+(FROM)`, `$1 COUNT($2) $3`, sql)
}
@ -390,7 +390,7 @@ func (tx *TX) GetCount(sql string, args ...interface{}) (int, error) {
if err != nil {
return 0, err
}
return value.Int(), nil
return value.Int64(), nil
}
// Insert does "INSERT INTO ..." statement for the table.

View File

@ -397,7 +397,7 @@ func (c *Core) RowsToResult(ctx context.Context, rows *sql.Rows) (Result, error)
record := Record{}
for i, value := range values {
if value == nil {
// Do not use `gvar.New(nil)` here as it creates an initialized object
// DO NOT use `gvar.New(nil)` here as it creates an initialized object
// which will cause struct converting issue.
record[columnNames[i]] = nil
} else {

View File

@ -85,18 +85,19 @@ func (m *Model) getSelectResultFromCache(ctx context.Context, sql string, args .
if cacheItem, ok = v.Val().(*selectCacheItem); ok {
// In-memory cache.
return cacheItem.Result, nil
} else {
// Other cache, it needs conversion.
if err = json.UnmarshalUseNumber(v.Bytes(), &cacheItem); err != nil {
return nil, err
}
return cacheItem.Result, nil
}
// Other cache, it needs conversion.
if err = json.UnmarshalUseNumber(v.Bytes(), &cacheItem); err != nil {
return nil, err
}
return cacheItem.Result, nil
}
return
}
func (m *Model) saveSelectResultToCache(ctx context.Context, result Result, sql string, args ...interface{}) (err error) {
func (m *Model) saveSelectResultToCache(
ctx context.Context, queryType queryType, result Result, sql string, args ...interface{},
) (err error) {
if !m.cacheEnabled || m.tx != nil {
return
}
@ -108,22 +109,38 @@ func (m *Model) saveSelectResultToCache(ctx context.Context, result Result, sql
if _, errCache := cacheObj.Remove(ctx, cacheKey); errCache != nil {
intlog.Errorf(ctx, `%+v`, errCache)
}
} else {
// In case of Cache Penetration.
if result.IsEmpty() && m.cacheOption.Force {
result = Result{}
}
var cacheItem = &selectCacheItem{
Result: result,
}
if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil {
cacheItem.FirstResultColumn = internalData.FirstResultColumn
}
if errCache := cacheObj.Set(ctx, cacheKey, cacheItem, m.cacheOption.Duration); errCache != nil {
intlog.Errorf(ctx, `%+v`, errCache)
return
}
// Special handler for Value/Count operations result.
if len(result) > 0 {
switch queryType {
case queryTypeValue, queryTypeCount:
if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil {
if result[0][internalData.FirstResultColumn].IsEmpty() {
result = nil
}
}
}
}
return nil
// In case of Cache Penetration.
if result.IsEmpty() {
if m.cacheOption.Force {
result = Result{}
} else {
result = nil
}
}
var cacheItem = &selectCacheItem{
Result: result,
}
if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil {
cacheItem.FirstResultColumn = internalData.FirstResultColumn
}
if errCache := cacheObj.Set(ctx, cacheKey, cacheItem, m.cacheOption.Duration); errCache != nil {
intlog.Errorf(ctx, `%+v`, errCache)
}
return
}
func (m *Model) makeSelectCacheKey(sql string, args ...interface{}) string {

View File

@ -12,7 +12,6 @@ import (
"reflect"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/reflection"
@ -31,75 +30,6 @@ func (m *Model) All(where ...interface{}) (Result, error) {
return m.doGetAll(ctx, false, where...)
}
// doGetAll does "SELECT FROM ..." statement for the model.
// It retrieves the records from table and returns the result as slice type.
// It returns nil if there's no record retrieved with the given conditions from table.
//
// The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
// The optional parameter `where` is the same as the parameter of Model.Where function,
// see Model.Where.
func (m *Model) doGetAll(ctx context.Context, limit1 bool, where ...interface{}) (Result, error) {
if len(where) > 0 {
return m.Where(where[0], where[1:]...).All()
}
sqlWithHolder, holderArgs := m.getFormattedSqlAndArgs(ctx, queryTypeNormal, limit1)
return m.doGetAllBySql(ctx, queryTypeNormal, sqlWithHolder, holderArgs...)
}
// getFieldsFiltered checks the fields and fieldsEx attributes, filters and returns the fields that will
// really be committed to underlying database driver.
func (m *Model) getFieldsFiltered() string {
if m.fieldsEx == "" {
// No filtering, containing special chars.
if gstr.ContainsAny(m.fields, "()") {
return m.fields
}
// No filtering.
if !gstr.ContainsAny(m.fields, ". ") {
return m.db.GetCore().QuoteString(m.fields)
}
return m.fields
}
var (
fieldsArray []string
fieldsExSet = gset.NewStrSetFrom(gstr.SplitAndTrim(m.fieldsEx, ","))
)
if m.fields != "*" {
// Filter custom fields with fieldEx.
fieldsArray = make([]string, 0, 8)
for _, v := range gstr.SplitAndTrim(m.fields, ",") {
fieldsArray = append(fieldsArray, v[gstr.PosR(v, "-")+1:])
}
} else {
if gstr.Contains(m.tables, " ") {
panic("function FieldsEx supports only single table operations")
}
// Filter table fields with fieldEx.
tableFields, err := m.TableFields(m.tablesInit)
if err != nil {
panic(err)
}
if len(tableFields) == 0 {
panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
}
fieldsArray = make([]string, len(tableFields))
for k, v := range tableFields {
fieldsArray[v.Index] = k
}
}
newFields := ""
for _, k := range fieldsArray {
if fieldsExSet.Contains(k) {
continue
}
if len(newFields) > 0 {
newFields += ","
}
newFields += m.db.GetCore().QuoteWord(k)
}
return newFields
}
// Chunk iterates the query result with given `size` and `handler` function.
func (m *Model) Chunk(size int, handler ChunkHandler) {
page := m.start
@ -147,45 +77,6 @@ func (m *Model) One(where ...interface{}) (Record, error) {
return nil, nil
}
// Value retrieves a specified record value from table and returns the result as interface type.
// It returns nil if there's no record found with the given conditions from table.
//
// If the optional parameter `fieldsAndWhere` is given, the fieldsAndWhere[0] is the selected fields
// and fieldsAndWhere[1:] is treated as where condition fields.
// Also see Model.Fields and Model.Where functions.
func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) {
var ctx = m.GetCtx()
if len(fieldsAndWhere) > 0 {
if len(fieldsAndWhere) > 2 {
return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1], fieldsAndWhere[2:]...).Value()
} else if len(fieldsAndWhere) == 2 {
return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1]).Value()
} else {
return m.Fields(gconv.String(fieldsAndWhere[0])).Value()
}
}
var (
all Result
err error
)
if all, err = m.doGetAll(ctx, true); err != nil {
return nil, err
}
if len(all) == 0 {
return gvar.New(nil), nil
}
if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil {
record := all[0]
if v, ok := record[internalData.FirstResultColumn]; ok {
return v, nil
}
}
return nil, gerror.NewCode(
gcode.CodeInternalError,
`query value error: the internal context data is missing. there's internal issue should be fixed`,
)
}
// Array queries and returns data values as slice from database.
// Note that if there are multiple columns in the result, it returns just one column values randomly.
//
@ -375,6 +266,45 @@ func (m *Model) ScanList(structSlicePointer interface{}, bindToAttrName string,
})
}
// Value retrieves a specified record value from table and returns the result as interface type.
// It returns nil if there's no record found with the given conditions from table.
//
// If the optional parameter `fieldsAndWhere` is given, the fieldsAndWhere[0] is the selected fields
// and fieldsAndWhere[1:] is treated as where condition fields.
// Also see Model.Fields and Model.Where functions.
func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) {
var ctx = m.GetCtx()
if len(fieldsAndWhere) > 0 {
if len(fieldsAndWhere) > 2 {
return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1], fieldsAndWhere[2:]...).Value()
} else if len(fieldsAndWhere) == 2 {
return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1]).Value()
} else {
return m.Fields(gconv.String(fieldsAndWhere[0])).Value()
}
}
var (
sqlWithHolder, holderArgs = m.getFormattedSqlAndArgs(ctx, queryTypeValue, true)
all, err = m.doGetAllBySql(ctx, queryTypeValue, sqlWithHolder, holderArgs...)
)
if err != nil {
return nil, err
}
if len(all) > 0 {
if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil {
record := all[0]
if v, ok := record[internalData.FirstResultColumn]; ok {
return v, nil
}
}
return nil, gerror.NewCode(
gcode.CodeInternalError,
`query value error: the internal context data is missing. there's internal issue should be fixed`,
)
}
return nil, nil
}
// Count does "SELECT COUNT(x) FROM ..." statement for the model.
// The optional parameter `where` is the same as the parameter of Model.Where function,
// see Model.Where.
@ -526,8 +456,23 @@ func (m *Model) Having(having interface{}, args ...interface{}) *Model {
return model
}
// doGetAll does "SELECT FROM ..." statement for the model.
// It retrieves the records from table and returns the result as slice type.
// It returns nil if there's no record retrieved with the given conditions from table.
//
// The parameter `limit1` specifies whether limits querying only one record if m.limit is not set.
// The optional parameter `where` is the same as the parameter of Model.Where function,
// see Model.Where.
func (m *Model) doGetAll(ctx context.Context, limit1 bool, where ...interface{}) (Result, error) {
if len(where) > 0 {
return m.Where(where[0], where[1:]...).All()
}
sqlWithHolder, holderArgs := m.getFormattedSqlAndArgs(ctx, queryTypeNormal, limit1)
return m.doGetAllBySql(ctx, queryTypeNormal, sqlWithHolder, holderArgs...)
}
// doGetAllBySql does the select statement on the database.
func (m *Model) doGetAllBySql(ctx context.Context, queryType int, sql string, args ...interface{}) (result Result, err error) {
func (m *Model) doGetAllBySql(ctx context.Context, queryType queryType, sql string, args ...interface{}) (result Result, err error) {
if result, err = m.getSelectResultFromCache(ctx, sql, args...); err != nil || result != nil {
return
}
@ -548,11 +493,11 @@ func (m *Model) doGetAllBySql(ctx context.Context, queryType int, sql string, ar
return
}
err = m.saveSelectResultToCache(ctx, result, sql, args...)
err = m.saveSelectResultToCache(ctx, queryType, result, sql, args...)
return
}
func (m *Model) getFormattedSqlAndArgs(ctx context.Context, queryType int, limit1 bool) (sqlWithHolder string, holderArgs []interface{}) {
func (m *Model) getFormattedSqlAndArgs(ctx context.Context, queryType queryType, limit1 bool) (sqlWithHolder string, holderArgs []interface{}) {
switch queryType {
case queryTypeCount:
queryFields := "COUNT(1)"
@ -604,6 +549,60 @@ func (m *Model) getAutoPrefix() string {
return autoPrefix
}
// getFieldsFiltered checks the fields and fieldsEx attributes, filters and returns the fields that will
// really be committed to underlying database driver.
func (m *Model) getFieldsFiltered() string {
if m.fieldsEx == "" {
// No filtering, containing special chars.
if gstr.ContainsAny(m.fields, "()") {
return m.fields
}
// No filtering.
if !gstr.ContainsAny(m.fields, ". ") {
return m.db.GetCore().QuoteString(m.fields)
}
return m.fields
}
var (
fieldsArray []string
fieldsExSet = gset.NewStrSetFrom(gstr.SplitAndTrim(m.fieldsEx, ","))
)
if m.fields != "*" {
// Filter custom fields with fieldEx.
fieldsArray = make([]string, 0, 8)
for _, v := range gstr.SplitAndTrim(m.fields, ",") {
fieldsArray = append(fieldsArray, v[gstr.PosR(v, "-")+1:])
}
} else {
if gstr.Contains(m.tables, " ") {
panic("function FieldsEx supports only single table operations")
}
// Filter table fields with fieldEx.
tableFields, err := m.TableFields(m.tablesInit)
if err != nil {
panic(err)
}
if len(tableFields) == 0 {
panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
}
fieldsArray = make([]string, len(tableFields))
for k, v := range tableFields {
fieldsArray[v.Index] = k
}
}
newFields := ""
for _, k := range fieldsArray {
if fieldsExSet.Contains(k) {
continue
}
if len(newFields) > 0 {
newFields += ","
}
newFields += m.db.GetCore().QuoteWord(k)
}
return newFields
}
// formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
// Note that this function does not change any attribute value of the `m`.
//

View File

@ -16,7 +16,7 @@ import (
// IsEmpty checks and returns whether `r` is empty.
func (r Result) IsEmpty() bool {
return r.Len() == 0
return r == nil || r.Len() == 0
}
// Len returns the length of result list.

View File

@ -15,7 +15,7 @@ import (
)
// Encode escapes the string so it can be safely placed
// inside a URL query.
// inside an URL query.
func Encode(str string) string {
return url.QueryEscape(str)
}
@ -49,7 +49,7 @@ func BuildQuery(queryData url.Values) string {
return queryData.Encode()
}
// ParseURL Parse a URL and return its components.
// ParseURL Parse an URL and return its components.
// -1: all; 1: scheme; 2: host; 4: port; 8: user; 16: pass; 32: path; 64: query; 128: fragment.
// See http://php.net/manual/en/function.parse-url.php.
func ParseURL(str string, component int) (map[string]string, error) {

View File

@ -0,0 +1,50 @@
package main
import (
"net/http"
"net/http/httputil"
"net/url"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
const (
PortOfServer1 = 8198
PortOfServer2 = 8199
UpStream = "http://127.0.0.1:8198"
)
// StartServer1 starts Server1: A simple http server for demo.
func StartServer1() {
s := g.Server(1)
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.Write("response from server 1")
})
s.BindHandler("/user/1", func(r *ghttp.Request) {
r.Response.Write("user info from server 1")
})
s.SetPort(PortOfServer1)
s.Run()
}
// StartServer2 starts Server2:
// All requests to Server2 are directly redirected to Server1.
func StartServer2() {
s := g.Server(2)
u, _ := url.Parse(UpStream)
s.BindHandler("/*", func(r *ghttp.Request) {
proxy := httputil.NewSingleHostReverseProxy(u)
proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) {
writer.WriteHeader(http.StatusBadGateway)
}
proxy.ServeHTTP(r.Response.Writer.RawWriter(), r.Request)
})
s.SetPort(PortOfServer2)
s.Run()
}
func main() {
go StartServer1()
StartServer2()
}

View File

@ -22,7 +22,7 @@ func Test_View(t *testing.T) {
t.AssertNE(View(), nil)
b, e := View().ParseContent(context.TODO(), `{{"我是中国人" | substr 2 -1}}`, nil)
t.Assert(e, nil)
t.Assert(b, "中国")
t.Assert(b, "中国")
})
gtest.C(t, func(t *gtest.T) {
tpl := "t.tpl"
@ -32,7 +32,7 @@ func Test_View(t *testing.T) {
b, e := View().Parse(context.TODO(), "t.tpl", nil)
t.Assert(e, nil)
t.Assert(b, "中国")
t.Assert(b, "中国")
})
gtest.C(t, func(t *gtest.T) {
path := fmt.Sprintf(`%s/%d`, gfile.Temp(), gtime.TimestampNano())
@ -45,7 +45,7 @@ func Test_View(t *testing.T) {
b, e := View().Parse(context.TODO(), "t.tpl", nil)
t.Assert(e, nil)
t.Assert(b, "中国")
t.Assert(b, "中国")
})
}

View File

@ -48,7 +48,7 @@ func (c *Client) ConnectBytes(ctx context.Context, url string, data ...interface
return c.RequestBytes(ctx, http.MethodConnect, url, data...)
}
// OptionsBytes sends a OPTIONS request, retrieves and returns the result content as bytes.
// OptionsBytes sends an OPTIONS request, retrieves and returns the result content as bytes.
func (c *Client) OptionsBytes(ctx context.Context, url string, data ...interface{}) []byte {
return c.RequestBytes(ctx, http.MethodOptions, url, data...)
}

View File

@ -13,11 +13,11 @@ import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/goai"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
)
@ -41,21 +41,21 @@ import (
// DoRequestObj(ctx, req, &res)
func (c *Client) DoRequestObj(ctx context.Context, req, res interface{}) error {
var (
method = gmeta.Get(req, goai.TagNameMethod).String()
path = gmeta.Get(req, goai.TagNamePath).String()
method = gmeta.Get(req, gtag.Method).String()
path = gmeta.Get(req, gtag.Path).String()
)
if method == "" {
return gerror.NewCodef(
gcode.CodeInvalidParameter,
`no "%s" tag found in request object: %s`,
goai.TagNameMethod, reflect.TypeOf(req).String(),
gtag.Method, reflect.TypeOf(req).String(),
)
}
if path == "" {
return gerror.NewCodef(
gcode.CodeInvalidParameter,
`no "%s" tag found in request object: %s`,
goai.TagNamePath, reflect.TypeOf(req).String(),
gtag.Path, reflect.TypeOf(req).String(),
)
}
path = c.handlePathForObjRequest(path, req)

View File

@ -55,7 +55,7 @@ func (c *Client) ConnectVar(ctx context.Context, url string, data ...interface{}
return c.RequestVar(ctx, http.MethodConnect, url, data...)
}
// OptionsVar sends a OPTIONS request, retrieves and converts the result content to specified pointer.
// OptionsVar sends an OPTIONS request, retrieves and converts the result content to specified pointer.
// The parameter `pointer` can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, etc.
func (c *Client) OptionsVar(ctx context.Context, url string, data ...interface{}) *gvar.Var {
return c.RequestVar(ctx, http.MethodOptions, url, data...)

View File

@ -524,7 +524,7 @@ func ExampleClient_GetVar() {
// &{1 john}
}
// ExampleClient_SetProxy a example for `gclient.Client.SetProxy` method.
// ExampleClient_SetProxy an example for `gclient.Client.SetProxy` method.
// please prepare two proxy server before running this example.
// http proxy server listening on `127.0.0.1:1081`
// socks5 proxy server listening on `127.0.0.1:1080`

View File

@ -22,6 +22,7 @@ import (
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gsession"
"github.com/gogf/gf/v2/util/gtag"
)
type (
@ -127,19 +128,20 @@ const (
)
const (
supportedHttpMethods = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
defaultMethod = "ALL"
routeCacheDuration = time.Hour
ctxKeyForRequest = "gHttpRequestObject"
contentTypeXml = "text/xml"
contentTypeHtml = "text/html"
contentTypeJson = "application/json"
swaggerUIPackedPath = "/goframe/swaggerui"
responseTraceIDHeader = "Trace-ID"
specialMethodNameInit = "Init"
specialMethodNameShut = "Shut"
specialMethodNameIndex = "Index"
gracefulShutdownTimeout = 5 * time.Second
supportedHttpMethods = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
defaultMethod = "ALL"
routeCacheDuration = time.Hour
ctxKeyForRequest = "gHttpRequestObject"
contentTypeXml = "text/xml"
contentTypeHtml = "text/html"
contentTypeJson = "application/json"
swaggerUIPackedPath = "/goframe/swaggerui"
responseHeaderTraceID = "Trace-ID"
responseHeaderContentLength = "Content-Length"
specialMethodNameInit = "Init"
specialMethodNameShut = "Shut"
specialMethodNameIndex = "Index"
gracefulShutdownTimeout = 5 * time.Second
)
const (
@ -180,7 +182,7 @@ var (
gracefulEnabled = false
// defaultValueTags are the struct tag names for default value storing.
defaultValueTags = []string{"d", "default"}
defaultValueTags = []string{gtag.DefaultShort, gtag.Default}
)
var (

View File

@ -144,7 +144,7 @@ func (r *Response) ClearBuffer() {
// Flush outputs the buffer content to the client and clears the buffer.
func (r *Response) Flush() {
r.Header().Set(responseTraceIDHeader, gtrace.GetTraceID(r.Request.Context()))
r.Header().Set(responseHeaderTraceID, gtrace.GetTraceID(r.Request.Context()))
if r.Server.config.ServerAgent != "" {
r.Header().Set("Server", r.Server.config.ServerAgent)
}

View File

@ -16,11 +16,10 @@ import (
// ResponseWriter is the custom writer for http response.
type ResponseWriter struct {
Status int // HTTP status.
writer http.ResponseWriter // The underlying ResponseWriter.
buffer *bytes.Buffer // The output buffer.
hijacked bool // Mark this request is hijacked or not.
wroteHeader bool // Is header wrote or not, avoiding error: superfluous/multiple response.WriteHeader call.
Status int // HTTP status.
writer http.ResponseWriter // The underlying ResponseWriter.
buffer *bytes.Buffer // The output buffer.
hijacked bool // Mark this request is hijacked or not.
}
// RawWriter returns the underlying ResponseWriter.
@ -55,8 +54,7 @@ func (w *ResponseWriter) Flush() {
if w.hijacked {
return
}
if w.Status != 0 && !w.wroteHeader {
w.wroteHeader = true
if w.Status != 0 && !w.isHeaderWritten() {
w.writer.WriteHeader(w.Status)
}
// Default status text output.
@ -68,3 +66,11 @@ func (w *ResponseWriter) Flush() {
w.buffer.Reset()
}
}
// isHeaderWrote checks and returns whether the header is written.
func (w *ResponseWriter) isHeaderWritten() bool {
if _, ok := w.writer.Header()[responseHeaderContentLength]; ok {
return true
}
return false
}

View File

@ -276,7 +276,6 @@ func (s *Server) serveFile(r *Request, f *staticFile, allowIndex ...bool) {
}
} else {
info := f.File.FileInfo()
r.Response.wroteHeader = true
http.ServeContent(r.Response.Writer.RawWriter(), r.Request, info.Name(), info.ModTime(), f.File)
}
return
@ -301,7 +300,6 @@ func (s *Server) serveFile(r *Request, f *staticFile, allowIndex ...bool) {
r.Response.WriteStatus(http.StatusForbidden)
}
} else {
r.Response.wroteHeader = true
http.ServeContent(r.Response.Writer.RawWriter(), r.Request, info.Name(), info.ModTime(), file)
}
}

View File

@ -19,10 +19,10 @@ import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/consts"
"github.com/gogf/gf/v2/net/goai"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
)
var (
@ -96,13 +96,13 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
// Change the registered route according to meta info from its request structure.
if handler.Info.Type != nil && handler.Info.Type.NumIn() == 2 {
var objectReq = reflect.New(handler.Info.Type.In(1))
if v := gmeta.Get(objectReq, goai.TagNamePath); !v.IsEmpty() {
if v := gmeta.Get(objectReq, gtag.Path); !v.IsEmpty() {
uri = v.String()
}
if v := gmeta.Get(objectReq, goai.TagNameMethod); !v.IsEmpty() {
if v := gmeta.Get(objectReq, gtag.Method); !v.IsEmpty() {
method = v.String()
}
if v := gmeta.Get(objectReq, goai.TagNameDomain); !v.IsEmpty() {
if v := gmeta.Get(objectReq, gtag.Domain); !v.IsEmpty() {
domain = v.String()
}
}
@ -142,7 +142,6 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
pattern, handler.Source, duplicatedHandler.Source,
)
}
return
}
}
}
@ -245,14 +244,8 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) {
s.routesMap[routerKey] = make([]*HandlerItem, 0)
}
switch handler.Type {
case HandlerTypeHandler, HandlerTypeObject:
// Overwrite the route.
s.routesMap[routerKey] = []*HandlerItem{handler}
default:
// Append the route.
s.routesMap[routerKey] = append(s.routesMap[routerKey], handler)
}
// Append the route.
s.routesMap[routerKey] = append(s.routesMap[routerKey], handler)
}
// compareRouterPriority compares the priority between `newItem` and `oldItem`. It returns true

View File

@ -24,8 +24,8 @@ func Test_Params_Basic(t *testing.T) {
type User struct {
Id int
Name string
Pass1 string `params:"password1"`
Pass2 string `params:"password2"`
Pass1 string `p:"password1"`
Pass2 string `p:"password2"`
}
s := g.Server(guid.S())
// GET
@ -236,8 +236,8 @@ func Test_Params_Basic(t *testing.T) {
})
s.BindHandler("/struct-with-base", func(r *ghttp.Request) {
type Base struct {
Pass1 string `params:"password1"`
Pass2 string `params:"password2"`
Pass1 string `p:"password1"`
Pass2 string `p:"password2"`
}
type UserWithBase1 struct {
Id int

View File

@ -19,6 +19,7 @@ import (
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
)
// OpenApiV3 is the structure defined from:
@ -36,18 +37,6 @@ type OpenApiV3 struct {
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty"`
}
const (
HttpMethodGet = `GET`
HttpMethodPut = `PUT`
HttpMethodPost = `POST`
HttpMethodDelete = `DELETE`
HttpMethodConnect = `CONNECT`
HttpMethodHead = `HEAD`
HttpMethodOptions = `OPTIONS`
HttpMethodPatch = `PATCH`
HttpMethodTrace = `TRACE`
)
const (
TypeInteger = `integer`
TypeNumber = `number`
@ -72,15 +61,6 @@ const (
ParameterInCookie = `cookie`
)
const (
TagNamePath = `path`
TagNameMethod = `method`
TagNameMime = `mime`
TagNameConsumes = `consumes`
TagNameType = `type`
TagNameDomain = `domain`
)
const (
validationRuleKeyForRequired = `required`
validationRuleKeyForIn = `in:`
@ -90,18 +70,18 @@ var (
defaultReadContentTypes = []string{`application/json`}
defaultWriteContentTypes = []string{`application/json`}
shortTypeMapForTag = map[string]string{
"d": "Default",
"sum": "Summary",
"sm": "Summary",
"des": "Description",
"dc": "Description",
"eg": "Example",
"egs": "Examples",
"ed": "ExternalDocs",
gtag.DefaultShort: gtag.Default,
gtag.SummaryShort: gtag.Summary,
gtag.SummaryShort2: gtag.Summary,
gtag.DescriptionShort: gtag.Description,
gtag.DescriptionShort2: gtag.Description,
gtag.ExampleShort: gtag.Example,
gtag.ExamplesShort: gtag.Examples,
gtag.ExternalDocsShort: gtag.ExternalDocs,
}
)
// New creates and returns a OpenApiV3 implements object.
// New creates and returns an OpenApiV3 implements object.
func New() *OpenApiV3 {
oai := &OpenApiV3{}
oai.fillWithDefaultValue()
@ -231,7 +211,7 @@ func (oai *OpenApiV3) golangTypeToSchemaName(t reflect.Type) string {
return schemaName
}
func (oai *OpenApiV3) fileMapWithShortTags(m map[string]string) map[string]string {
func (oai *OpenApiV3) fillMapWithShortTags(m map[string]string) map[string]string {
for k, v := range shortTypeMapForTag {
if m[v] == "" && m[k] != "" {
m[v] = m[k]

View File

@ -30,7 +30,7 @@ type Operation struct {
}
func (oai *OpenApiV3) tagMapToOperation(tagMap map[string]string, operation *Operation) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, operation); err != nil {
return gerror.Wrap(err, `mapping struct tags to Operation failed`)
}

View File

@ -32,7 +32,7 @@ type Parameter struct {
}
func (oai *OpenApiV3) tagMapToParameter(tagMap map[string]string, parameter *Parameter) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, parameter); err != nil {
return gerror.Wrap(err, `mapping struct tags to Parameter failed`)
}

View File

@ -8,6 +8,7 @@ package goai
import (
"fmt"
"net/http"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/errors/gcode"
@ -15,6 +16,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/os/gstructs"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
)
// Parameters is specified by OpenAPI/Swagger 3.0 standard.
@ -28,13 +30,18 @@ type ParameterRef struct {
func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path, method string) (*ParameterRef, error) {
var (
tagMap = field.TagMap()
parameter = &Parameter{
Name: field.TagJsonName(),
XExtensions: make(XExtensions),
}
fieldName = field.Name()
)
if parameter.Name == "" {
parameter.Name = field.Name()
for _, tagName := range gconv.StructTagPriority {
if tagValue := field.Tag(tagName); tagValue != "" {
fieldName = tagValue
break
}
}
fieldName = gstr.SplitAndTrim(fieldName, ",")[0]
var parameter = &Parameter{
Name: fieldName,
XExtensions: make(XExtensions),
}
if len(tagMap) > 0 {
if err := oai.tagMapToParameter(tagMap, parameter); err != nil {
@ -48,7 +55,7 @@ func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path
} else {
// Default the parameter input to "query" if method is "GET/DELETE".
switch gstr.ToUpper(method) {
case HttpMethodGet, HttpMethodDelete:
case http.MethodGet, http.MethodDelete:
parameter.In = ParameterInQuery
default:

View File

@ -7,6 +7,7 @@
package goai
import (
"net/http"
"reflect"
"github.com/gogf/gf/v2/container/garray"
@ -17,6 +18,7 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
)
type Path struct {
@ -97,7 +99,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
)
// Path check.
if in.Path == "" {
in.Path = gmeta.Get(inputObject.Interface(), TagNamePath).String()
in.Path = gmeta.Get(inputObject.Interface(), gtag.Path).String()
if in.Prefix != "" {
in.Path = gstr.TrimRight(in.Prefix, "/") + "/" + gstr.TrimLeft(in.Path, "/")
}
@ -106,7 +108,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
return gerror.NewCodef(
gcode.CodeMissingParameter,
`missing necessary path parameter "%s" for input struct "%s", missing tag in attribute Meta?`,
TagNamePath, inputStructTypeName,
gtag.Path, inputStructTypeName,
)
}
@ -116,13 +118,13 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Method check.
if in.Method == "" {
in.Method = gmeta.Get(inputObject.Interface(), TagNameMethod).String()
in.Method = gmeta.Get(inputObject.Interface(), gtag.Method).String()
}
if in.Method == "" {
return gerror.NewCodef(
gcode.CodeMissingParameter,
`missing necessary method parameter "%s" for input struct "%s", missing tag in attribute Meta?`,
TagNameMethod, inputStructTypeName,
gtag.Method, inputStructTypeName,
)
}
@ -138,8 +140,8 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
return err
}
// Allowed request mime.
if mime = inputMetaMap[TagNameMime]; mime == "" {
mime = inputMetaMap[TagNameConsumes]
if mime = inputMetaMap[gtag.Mime]; mime == "" {
mime = inputMetaMap[gtag.Consumes]
}
}
@ -179,7 +181,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Supported mime types of request.
var (
contentTypes = oai.Config.ReadContentTypes
tagMimeValue = gmeta.Get(inputObject.Interface(), TagNameMime).String()
tagMimeValue = gmeta.Get(inputObject.Interface(), gtag.Mime).String()
)
if tagMimeValue != "" {
contentTypes = gstr.SplitAndTrim(tagMimeValue, ",")
@ -224,7 +226,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Supported mime types of response.
var (
contentTypes = oai.Config.ReadContentTypes
tagMimeValue = gmeta.Get(outputObject.Interface(), TagNameMime).String()
tagMimeValue = gmeta.Get(outputObject.Interface(), gtag.Mime).String()
refInput = getResponseSchemaRefInput{
BusinessStructName: outputStructTypeName,
CommonResponseObject: oai.Config.CommonResponse,
@ -256,35 +258,35 @@ func (oai *OpenApiV3) addPath(in addPathInput) error {
// Assign to certain operation attribute.
switch gstr.ToUpper(in.Method) {
case HttpMethodGet:
case http.MethodGet:
// GET operations cannot have a requestBody.
operation.RequestBody = nil
path.Get = &operation
case HttpMethodPut:
case http.MethodPut:
path.Put = &operation
case HttpMethodPost:
case http.MethodPost:
path.Post = &operation
case HttpMethodDelete:
case http.MethodDelete:
// DELETE operations cannot have a requestBody.
operation.RequestBody = nil
path.Delete = &operation
case HttpMethodConnect:
case http.MethodConnect:
// Nothing to do for Connect.
case HttpMethodHead:
case http.MethodHead:
path.Head = &operation
case HttpMethodOptions:
case http.MethodOptions:
path.Options = &operation
case HttpMethodPatch:
case http.MethodPatch:
path.Patch = &operation
case HttpMethodTrace:
case http.MethodTrace:
path.Trace = &operation
default:
@ -354,7 +356,7 @@ func (oai *OpenApiV3) doesStructHasNoFields(s interface{}) bool {
}
func (oai *OpenApiV3) tagMapToPath(tagMap map[string]string, path *Path) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, path); err != nil {
return gerror.Wrap(err, `mapping struct tags to Path failed`)
}

View File

@ -22,7 +22,7 @@ type Response struct {
}
func (oai *OpenApiV3) tagMapToResponse(tagMap map[string]string, response *Response) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, response); err != nil {
return gerror.Wrap(err, `mapping struct tags to Response failed`)
}

View File

@ -180,6 +180,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
break
}
}
fieldName = gstr.SplitAndTrim(fieldName, ",")[0]
schemaRef, err := oai.newSchemaRefWithGolangType(
structField.Type().Type,
structField.TagMap(),
@ -211,7 +212,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
}
func (oai *OpenApiV3) tagMapToSchema(tagMap map[string]string, schema *Schema) error {
var mergedTagMap = oai.fileMapWithShortTags(tagMap)
var mergedTagMap = oai.fillMapWithShortTags(tagMap)
if err := gconv.Struct(mergedTagMap, schema); err != nil {
return gerror.Wrap(err, `mapping struct tags to Schema failed`)
}

View File

@ -9,6 +9,7 @@ package goai_test
import (
"context"
"fmt"
"net/http"
"testing"
"github.com/gogf/gf/v2/frame/g"
@ -96,14 +97,14 @@ func TestOpenApiV3_Add(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPut,
Method: http.MethodPut,
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPost,
Method: http.MethodPost,
Object: f,
})
t.AssertNil(err)
@ -216,7 +217,7 @@ func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: path,
Method: goai.HttpMethodGet,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
@ -654,27 +655,27 @@ func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) {
func TestOpenApiV3_ShortTags(t *testing.T) {
type CommonReq struct {
AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"`
ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"`
AppId int64 `json:"appId" v:"required" in:"path" dc:"应用Id" sm:"应用Id Summary"`
ResourceId string `json:"resourceId" in:"query" dc:"资源Id" sm:"资源Id Summary"`
}
type SetSpecInfo struct {
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"`
Shards int32 `des:"shards 分片数" sum:"Shards Summary"`
Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"`
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" dc:"StorageType"`
Shards int32 `dc:"shards 分片数" sm:"Shards Summary"`
Params []string `dc:"默认参数(json 串-ClickHouseParams)" sm:"Params Summary"`
}
type CreateResourceReq struct {
CommonReq
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"`
Name string `des:"实例名称"`
Product string `des:"业务类型"`
Region string `v:"required" des:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"`
SetSlice []SetSpecInfo `v:"required" des:"配置Slice"`
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum"`
Name string `dc:"实例名称"`
Product string `dc:"业务类型"`
Region string `v:"required" dc:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" dc:"配置Map"`
SetSlice []SetSpecInfo `v:"required" dc:"配置Slice"`
}
type CreateResourceRes struct {
gmeta.Meta `des:"Demo Response Struct"`
FlowId int64 `des:"创建实例流程id"`
gmeta.Meta `dc:"Demo Response Struct"`
FlowId int64 `dc:"创建实例流程id"`
}
f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) {
@ -688,14 +689,14 @@ func TestOpenApiV3_ShortTags(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPut,
Method: http.MethodPut,
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: goai.HttpMethodPost,
Method: http.MethodPost,
Object: f,
})
t.AssertNil(err)
@ -728,7 +729,7 @@ func TestOpenApiV3_HtmlResponse(t *testing.T) {
)
err = oai.Add(goai.AddInput{
Path: "/test",
Method: goai.HttpMethodGet,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
@ -775,7 +776,7 @@ func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) {
err = oai.Add(goai.AddInput{
Path: "/test",
Method: goai.HttpMethodGet,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
@ -1000,3 +1001,48 @@ func Test_EmbeddedStructAttribute(t *testing.T) {
t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateResourceReq":{"properties":{"Name":{"description":"This is name.","format":"string","properties":{},"type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","properties":{},"type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
})
}
func Test_NameFromJsonTag(t *testing.T) {
// POST
gtest.C(t, func(t *gtest.T) {
type CreateReq struct {
gmeta.Meta `path:"/CreateReq" method:"POST"`
Name string `json:"nick_name, omitempty"`
}
var (
err error
oai = goai.New()
req = new(CreateReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
b, err := json.Marshal(oai)
t.AssertNil(err)
t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","properties":{},"type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
})
// GET
gtest.C(t, func(t *gtest.T) {
type CreateReq struct {
gmeta.Meta `path:"/CreateReq" method:"GET"`
Name string `json:"nick_name, omitempty" in:"header"`
}
var (
err error
oai = goai.New()
req = new(CreateReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
b, err := json.Marshal(oai)
t.AssertNil(err)
fmt.Println(string(b))
t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","properties":{},"type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
})
}

View File

@ -44,7 +44,7 @@ func NewConn(remoteAddress string, localAddress ...string) (*Conn, error) {
}
}
// NewConnByNetConn creates a UDP connection object with given *net.UDPConn object.
// NewConnByNetConn creates an UDP connection object with given *net.UDPConn object.
func NewConnByNetConn(udp *net.UDPConn) *Conn {
return &Conn{
UDPConn: udp,

View File

@ -40,7 +40,7 @@ var (
serverMapping = gmap.NewStrAnyMap(true)
)
// GetServer creates and returns a UDP server instance with given name.
// GetServer creates and returns an UDP server instance with given name.
func GetServer(name ...interface{}) *Server {
serverName := defaultServer
if len(name) > 0 && name[0] != "" {
@ -54,7 +54,7 @@ func GetServer(name ...interface{}) *Server {
return s
}
// NewServer creates and returns a UDP server.
// NewServer creates and returns an UDP server.
// The optional parameter `name` is used to specify its name, which can be used for
// GetServer function to retrieve its instance.
func NewServer(address string, handler func(*Conn), name ...string) *Server {

View File

@ -196,7 +196,7 @@ func MustGetOrSet(ctx context.Context, key interface{}, value interface{}, durat
// MustGetOrSetFunc acts like GetOrSetFunc, but it panics if any error occurs.
func MustGetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) *gvar.Var {
return defaultCache.MustGetOrSet(ctx, key, f, duration)
return defaultCache.MustGetOrSetFunc(ctx, key, f, duration)
}
// MustGetOrSetFuncLock acts like GetOrSetFuncLock, but it panics if any error occurs.

View File

@ -172,6 +172,7 @@ func TestCache_LRU(t *testing.T) {
v, _ := cache.Get(ctx, 6)
t.Assert(v, 6)
time.Sleep(4 * time.Second)
g.Log().Debugf(ctx, `items after lru: %+v`, cache.MustData(ctx))
n, _ = cache.Size(ctx)
t.Assert(n, 2)
v, _ = cache.Get(ctx, 6)

View File

@ -23,18 +23,11 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
"github.com/gogf/gf/v2/util/gvalid"
)
const (
tagNameDc = `dc` // description.
tagNameAd = `ad` // additional
tagNameEg = `eg` // examples.
tagNameArg = `arg`
tagNameRoot = `root`
)
var (
// defaultValueTags is the struct tag names for default value storing.
defaultValueTags = []string{"d", "default"}
@ -68,7 +61,7 @@ func NewFromObject(object interface{}) (rootCmd *Command, err error) {
// Sub command creating.
var (
nameSet = gset.NewStrSet()
rootCommandName = gmeta.Get(object, tagNameRoot).String()
rootCommandName = gmeta.Get(object, gtag.Root).String()
subCommands []*Command
)
if rootCommandName == "" {
@ -155,14 +148,26 @@ func newCommandFromObjectMeta(object interface{}, name string) (command *Command
}
command.Name = name
}
if command.Brief == "" {
for _, tag := range []string{gtag.Summary, gtag.SummaryShort, gtag.SummaryShort2} {
command.Brief = metaData[tag]
if command.Brief != "" {
break
}
}
}
if command.Description == "" {
command.Description = metaData[tagNameDc]
command.Description = metaData[gtag.DescriptionShort]
}
if command.Brief == "" && command.Description != "" {
command.Brief = command.Description
command.Description = ""
}
if command.Examples == "" {
command.Examples = metaData[tagNameEg]
command.Examples = metaData[gtag.ExampleShort]
}
if command.Additional == "" {
command.Additional = metaData[tagNameAd]
command.Additional = metaData[gtag.AdditionalShort]
}
return
}
@ -176,13 +181,13 @@ func newCommandFromMethod(
err = gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid command: %s.%s.%s defined as "%s", but "func(context.Context, Input)(Output, error)" is required`,
methodType.PkgPath(), reflect.TypeOf(object).Name(), methodType.Name(), methodType.String(),
methodType.PkgPath(), reflect.TypeOf(object).Name(), method.Name, methodType.String(),
)
} else {
err = gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid command: defined as "%s", but "func(context.Context, Input)(Output, error)" is required`,
methodType.String(),
`invalid command: %s.%s defined as "%s", but "func(context.Context, Input)(Output, error)" is required`,
reflect.TypeOf(object).Name(), method.Name, methodType.String(),
)
}
return
@ -190,16 +195,16 @@ func newCommandFromMethod(
if !methodType.In(0).Implements(reflect.TypeOf((*context.Context)(nil)).Elem()) {
err = gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid command: defined as "%s", but the first input parameter should be type of "context.Context"`,
methodType.String(),
`invalid command: %s.%s defined as "%s", but the first input parameter should be type of "context.Context"`,
reflect.TypeOf(object).Name(), method.Name, methodType.String(),
)
return
}
if !methodType.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
err = gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid command: defined as "%s", but the last output parameter should be type of "error"`,
methodType.String(),
`invalid command: %s.%s defined as "%s", but the last output parameter should be type of "error"`,
reflect.TypeOf(object).Name(), method.Name, methodType.String(),
)
return
}
@ -354,7 +359,10 @@ func newArgumentsFromInput(object interface{}) (args []Argument, err error) {
arg.Short, reflect.TypeOf(object).String(), field.Name(),
)
}
if v, ok := metaData[tagNameArg]; ok {
if arg.Brief == "" {
arg.Brief = field.TagDescription()
}
if v, ok := metaData[gtag.Arg]; ok {
arg.IsArg = gconv.Bool(v)
}
if nameSet.Contains(arg.Name) {

View File

@ -123,8 +123,9 @@ func newSchedule(pattern string) (*cronSchedule, error) {
pattern: pattern,
lastTimestamp: gtype.NewInt64(currentTimestamp),
}, nil
} else {
return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `invalid pattern: "%s"`, pattern)
}
return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `invalid pattern: "%s"`, pattern)
}
// Handle the common cron pattern, like:
// 0 0 0 1 1 2

View File

@ -73,6 +73,15 @@ func TestNext(t *testing.T) {
// Leap year
{"Mon Jul 9 23:35 2012", "0 0 0 29 Feb ?", "Mon Feb 29 00:00 2016"},
// Predefined pattern map.
{"Mon Jul 9 23:35 2012", "@yearly", "Sun Jan 1 00:00:00 2013"},
{"Mon Jul 9 23:35 2012", "@annually", "Sun Jan 1 00:00:00 2013"},
{"Mon Jul 9 23:35 2012", "@monthly", "Mon Aug 1 00:00:00 2012"},
{"Mon Jul 9 23:35 2012", "@weekly", "Sun Jul 15 00:00:00 2012"},
{"Mon Jul 9 23:35 2012", "@daily", "Tue Jul 10 00:00:00 2012"},
{"Mon Jul 9 23:35 2012", "@midnight", "Tue Jul 10 00:00:00 2012"},
{"Mon Jul 9 23:35 2012", "@hourly", "Tue Jul 10 00:00:00 2012"},
}
for _, c := range runs {

View File

@ -67,6 +67,22 @@ func TestCron_Basic(t *testing.T) {
t.AssertNE(entry1, nil)
t.Assert(entry2, nil)
})
// test @ error
gtest.C(t, func(t *gtest.T) {
cron := gcron.New()
defer cron.Close()
_, err := cron.Add(ctx, "@aaa", func(ctx context.Context) {}, "add")
t.AssertNE(err, nil)
})
// test @every error
gtest.C(t, func(t *gtest.T) {
cron := gcron.New()
defer cron.Close()
_, err := cron.Add(ctx, "@every xxx", func(ctx context.Context) {}, "add")
t.AssertNE(err, nil)
})
}
func TestCron_Remove(t *testing.T) {

View File

@ -176,7 +176,7 @@ func GetBytesByTwoOffsetsByPath(path string, start int64, end int64) []byte {
//
// Note that the parameter passed to callback function might be an empty value, and the last non-empty line
// will be passed to callback function `callback` even if it has no newline marker.
func ReadLines(file string, callback func(text string) error) error {
func ReadLines(file string, callback func(line string) error) error {
f, err := Open(file)
if err != nil {
return err

View File

@ -97,7 +97,7 @@ func ScanDirFile(path string, pattern string, recursive ...bool) ([]string, erro
// symbol to separate multiple patterns.
//
// The parameter `recursive` specifies whether scanning the `path` recursively, which
// means it scans its sub-files and appends the files path to result array if the sub-file
// means it scans its sub-files and appends the file paths to result array if the sub-file
// is also a folder. It is false in default.
//
// The parameter `handler` specifies the callback function handling each sub-file path of

View File

@ -9,11 +9,14 @@ package grpool
import (
"context"
"time"
"github.com/gogf/gf/v2/container/glist"
"github.com/gogf/gf/v2/container/gtype"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtimer"
"github.com/gogf/gf/v2/util/grand"
)
// Func is the pool function which contains context parameter.
@ -26,15 +29,20 @@ type RecoverFunc func(ctx context.Context, err error)
type Pool struct {
limit int // Max goroutine count limit.
count *gtype.Int // Current running goroutine count.
list *glist.List // Job list for asynchronous job adding purpose.
list *glist.List // List for asynchronous job adding purpose.
closed *gtype.Bool // Is pool closed or not.
}
type internalPoolItem struct {
type localPoolItem struct {
Ctx context.Context
Func Func
}
const (
minTimerDuration = 500 * time.Millisecond
maxTimerDuration = 1500 * time.Millisecond
)
// Default goroutine pool.
var (
pool = New()
@ -53,6 +61,8 @@ func New(limit ...int) *Pool {
if len(limit) > 0 && limit[0] > 0 {
p.limit = limit[0]
}
timerDuration := grand.D(minTimerDuration, maxTimerDuration)
gtimer.Add(context.Background(), timerDuration, p.supervisor)
return p
}
@ -66,8 +76,8 @@ func Add(ctx context.Context, f Func) error {
// The optional `recoverFunc` is called when any panic during executing of `userFunc`.
// If `recoverFunc` is not passed or given nil, it ignores the panic from `userFunc`.
// The job will be executed asynchronously.
func AddWithRecover(ctx context.Context, userFunc Func, recoverFunc ...RecoverFunc) error {
return pool.AddWithRecover(ctx, userFunc, recoverFunc...)
func AddWithRecover(ctx context.Context, userFunc Func, recoverFunc RecoverFunc) error {
return pool.AddWithRecover(ctx, userFunc, recoverFunc)
}
// Size returns current goroutine count of default goroutine pool.
@ -84,42 +94,68 @@ func Jobs() int {
// The job will be executed asynchronously.
func (p *Pool) Add(ctx context.Context, f Func) error {
for p.closed.Val() {
return gerror.NewCode(gcode.CodeInvalidOperation, "pool closed")
return gerror.NewCode(
gcode.CodeInvalidOperation,
"goroutine pool is already closed",
)
}
p.list.PushFront(&internalPoolItem{
p.list.PushFront(&localPoolItem{
Ctx: ctx,
Func: f,
})
// Check and fork new worker.
p.checkAndFork()
return nil
}
// checkAndFork checks and creates a new goroutine worker.
// Note that the worker dies if the job function panics and the job has no recover handling.
func (p *Pool) checkAndFork() {
// Check whether fork new goroutine or not.
var n int
for {
n = p.count.Val()
if p.limit != -1 && n >= p.limit {
// No need fork new goroutine.
return nil
return
}
if p.count.Cas(n, n+1) {
// Use CAS to guarantee atomicity.
break
}
}
p.fork()
return nil
// Create job function in goroutine.
go func() {
defer p.count.Add(-1)
var (
listItem interface{}
poolItem *localPoolItem
)
for !p.closed.Val() {
listItem = p.list.PopBack()
if listItem == nil {
return
}
poolItem = listItem.(*localPoolItem)
poolItem.Func(poolItem.Ctx)
}
}()
}
// AddWithRecover pushes a new job to the pool with specified recover function.
// The optional `recoverFunc` is called when any panic during executing of `userFunc`.
// If `recoverFunc` is not passed or given nil, it ignores the panic from `userFunc`.
// The job will be executed asynchronously.
func (p *Pool) AddWithRecover(ctx context.Context, userFunc Func, recoverFunc ...RecoverFunc) error {
func (p *Pool) AddWithRecover(ctx context.Context, userFunc Func, recoverFunc RecoverFunc) error {
return p.Add(ctx, func(ctx context.Context) {
defer func() {
if exception := recover(); exception != nil {
if len(recoverFunc) > 0 && recoverFunc[0] != nil {
if recoverFunc != nil {
if v, ok := exception.(error); ok && gerror.HasStack(v) {
recoverFunc[0](ctx, v)
recoverFunc(ctx, v)
} else {
recoverFunc[0](ctx, gerror.Newf(`%+v`, exception))
recoverFunc(ctx, gerror.Newf(`%+v`, exception))
}
}
}
@ -146,27 +182,6 @@ func (p *Pool) Jobs() int {
return p.list.Size()
}
// fork creates a new goroutine worker.
// Note that the worker dies if the job function panics.
func (p *Pool) fork() {
go func() {
defer p.count.Add(-1)
var (
listItem interface{}
poolItem *internalPoolItem
)
for !p.closed.Val() {
if listItem = p.list.PopBack(); listItem != nil {
poolItem = listItem.(*internalPoolItem)
poolItem.Func(poolItem.Ctx)
} else {
return
}
}
}()
}
// IsClosed returns if pool is closed.
func (p *Pool) IsClosed() bool {
return p.closed.Val()

View File

@ -0,0 +1,30 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package grpool
import (
"context"
"github.com/gogf/gf/v2/os/gtimer"
)
// supervisor checks the job list and fork new worker goroutine to handle the job
// if there are jobs but no workers in pool.
func (p *Pool) supervisor(ctx context.Context) {
if p.IsClosed() {
gtimer.Exit()
}
if p.list.Size() > 0 && p.count.Val() == 0 {
var number = p.list.Size()
if p.limit > 0 {
number = p.limit
}
for i := 0; i < number; i++ {
p.checkAndFork()
}
}
}

View File

@ -4,8 +4,6 @@
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
// go test *.go -bench=".*" -count=1
package grpool_test
import (
@ -22,19 +20,23 @@ import (
func Test_Basic(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
wg = sync.WaitGroup{}
array = garray.NewArray(true)
size = 100
)
wg.Add(size)
for i := 0; i < size; i++ {
grpool.Add(ctx, func(ctx context.Context) {
err = grpool.Add(ctx, func(ctx context.Context) {
array.Append(1)
wg.Done()
})
t.AssertNil(err)
}
wg.Wait()
time.Sleep(100 * time.Millisecond)
t.Assert(array.Len(), size)
t.Assert(grpool.Jobs(), 0)
t.Assert(grpool.Size(), 0)
@ -64,6 +66,7 @@ func Test_Limit1(t *testing.T) {
func Test_Limit2(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
wg = sync.WaitGroup{}
array = garray.NewArray(true)
size = 100
@ -71,10 +74,11 @@ func Test_Limit2(t *testing.T) {
)
wg.Add(size)
for i := 0; i < size; i++ {
pool.Add(ctx, func(ctx context.Context) {
err = pool.Add(ctx, func(ctx context.Context) {
defer wg.Done()
array.Append(1)
})
t.AssertNil(err)
}
wg.Wait()
t.Assert(array.Len(), size)
@ -111,18 +115,25 @@ func Test_Limit3(t *testing.T) {
func Test_AddWithRecover(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewArray(true)
grpool.AddWithRecover(ctx, func(ctx context.Context) {
var (
err error
array = garray.NewArray(true)
)
err = grpool.AddWithRecover(ctx, func(ctx context.Context) {
array.Append(1)
panic(1)
}, func(ctx context.Context, err error) {
array.Append(1)
})
grpool.AddWithRecover(ctx, func(ctx context.Context) {
t.AssertNil(err)
err = grpool.AddWithRecover(ctx, func(ctx context.Context) {
panic(1)
array.Append(1)
})
}, nil)
t.AssertNil(err)
time.Sleep(500 * time.Millisecond)
t.Assert(array.Len(), 2)
})
}

View File

@ -59,7 +59,7 @@ func New(path string, cache bool) *SPath {
return sp
}
// Get creates and returns a instance of searching manager for given path.
// Get creates and returns an instance of searching manager for given path.
// The parameter `cache` specifies whether using cache feature for this manager.
// If cache feature is enabled, it asynchronously and recursively scans the path
// and updates all sub files/folders to the cache using package gfsnotify.
@ -73,7 +73,7 @@ func Get(root string, cache bool) *SPath {
}
// Search searches file `name` under path `root`.
// The parameter `root` should be a absolute path. It will not automatically
// The parameter `root` should be an absolute path. It will not automatically
// convert `root` to absolute path for performance reason.
// The optional parameter `indexFiles` specifies the searching index files when the result is a directory.
// For example, if the result `filePath` is a directory, and `indexFiles` is [index.html, main.html], it will also
@ -84,7 +84,7 @@ func Search(root string, name string, indexFiles ...string) (filePath string, is
}
// SearchWithCache searches file `name` under path `root` with cache feature enabled.
// The parameter `root` should be a absolute path. It will not automatically
// The parameter `root` should be an absolute path. It will not automatically
// convert `root` to absolute path for performance reason.
// The optional parameter `indexFiles` specifies the searching index files when the result is a directory.
// For example, if the result `filePath` is a directory, and `indexFiles` is [index.html, main.html], it will also
@ -215,7 +215,7 @@ func (sp *SPath) Search(name string, indexFiles ...string) (filePath string, isD
}
// Remove deletes the `path` from cache files of the manager.
// The parameter `path` can be either a absolute path or just a relative file name.
// The parameter `path` can be either an absolute path or just a relative file name.
func (sp *SPath) Remove(path string) {
if sp.cache == nil {
return

View File

@ -8,16 +8,11 @@ package gstructs
import (
"reflect"
"strings"
"github.com/gogf/gf/v2/internal/utils"
"github.com/gogf/gf/v2/util/gtag"
)
const (
jsonTagName = `json`
)
// Tag returns the value associated with key in the tag string. If there is no
// such key in the tag, Tag returns the empty string.
func (f *Field) Tag(key string) string {
@ -28,14 +23,6 @@ func (f *Field) Tag(key string) string {
return s
}
// TagJsonName returns the `json` tag name string of the field.
func (f *Field) TagJsonName() string {
if jsonTag := f.Tag(jsonTagName); jsonTag != "" {
return strings.Split(jsonTag, ",")[0]
}
return ""
}
// TagLookup returns the value associated with key in the tag string.
// If the key is present in the tag the value (which may be empty)
// is returned. Otherwise, the returned value will be the empty string.

View File

@ -0,0 +1,90 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gstructs
import (
"strings"
"github.com/gogf/gf/v2/util/gtag"
)
// TagJsonName returns the `json` tag name string of the field.
func (f *Field) TagJsonName() string {
if jsonTag := f.Tag(gtag.Json); jsonTag != "" {
return strings.Split(jsonTag, ",")[0]
}
return ""
}
// TagDefault returns the most commonly used tag `default/d` value of the field.
func (f *Field) TagDefault() string {
v := f.Tag(gtag.Default)
if v == "" {
v = f.Tag(gtag.DefaultShort)
}
return v
}
// TagParam returns the most commonly used tag `param/p` value of the field.
func (f *Field) TagParam() string {
v := f.Tag(gtag.Param)
if v == "" {
v = f.Tag(gtag.ParamShort)
}
return v
}
// TagValid returns the most commonly used tag `valid/v` value of the field.
func (f *Field) TagValid() string {
v := f.Tag(gtag.Valid)
if v == "" {
v = f.Tag(gtag.ValidShort)
}
return v
}
// TagDescription returns the most commonly used tag `description/des/dc` value of the field.
func (f *Field) TagDescription() string {
v := f.Tag(gtag.Description)
if v == "" {
v = f.Tag(gtag.DescriptionShort)
}
if v == "" {
v = f.Tag(gtag.DescriptionShort2)
}
return v
}
// TagSummary returns the most commonly used tag `summary/sum/sm` value of the field.
func (f *Field) TagSummary() string {
v := f.Tag(gtag.Summary)
if v == "" {
v = f.Tag(gtag.SummaryShort)
}
if v == "" {
v = f.Tag(gtag.SummaryShort2)
}
return v
}
// TagAdditional returns the most commonly used tag `additional/ad` value of the field.
func (f *Field) TagAdditional() string {
v := f.Tag(gtag.Additional)
if v == "" {
v = f.Tag(gtag.AdditionalShort)
}
return v
}
// TagExample returns the most commonly used tag `example/eg` value of the field.
func (f *Field) TagExample() string {
v := f.Tag(gtag.Example)
if v == "" {
v = f.Tag(gtag.ExampleShort)
}
return v
}

View File

@ -381,3 +381,149 @@ func TestType_TagMap(t *testing.T) {
t.Assert(r[1].TagMap()["description"], `应用Id`)
})
}
func TestType_TagJsonName(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `json:"name,omitempty"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 1)
t.Assert(r[0].TagJsonName(), `name`)
})
}
func TestType_TagDefault(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `default:"john"`
Name2 string `d:"john"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0].TagDefault(), `john`)
t.Assert(r[1].TagDefault(), `john`)
})
}
func TestType_TagParam(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `param:"name"`
Name2 string `p:"name"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0].TagParam(), `name`)
t.Assert(r[1].TagParam(), `name`)
})
}
func TestType_TagValid(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `valid:"required"`
Name2 string `v:"required"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0].TagValid(), `required`)
t.Assert(r[1].TagValid(), `required`)
})
}
func TestType_TagDescription(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `description:"my name"`
Name2 string `des:"my name"`
Name3 string `dc:"my name"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 3)
t.Assert(r[0].TagDescription(), `my name`)
t.Assert(r[1].TagDescription(), `my name`)
t.Assert(r[2].TagDescription(), `my name`)
})
}
func TestType_TagSummary(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `summary:"my name"`
Name2 string `sum:"my name"`
Name3 string `sm:"my name"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 3)
t.Assert(r[0].TagSummary(), `my name`)
t.Assert(r[1].TagSummary(), `my name`)
t.Assert(r[2].TagSummary(), `my name`)
})
}
func TestType_TagAdditional(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `additional:"my name"`
Name2 string `ad:"my name"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0].TagAdditional(), `my name`)
t.Assert(r[1].TagAdditional(), `my name`)
})
}
func TestType_TagExample(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type A struct {
Name string `example:"john"`
Name2 string `eg:"john"`
}
r, err := gstructs.Fields(gstructs.FieldsInput{
Pointer: new(A),
RecursiveOption: 0,
})
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0].TagExample(), `john`)
t.Assert(r[1].TagExample(), `john`)
})
}

View File

@ -24,7 +24,7 @@ type priorityQueue struct {
nextPriority *gtype.Int64 // nextPriority stores the next priority value of the heap, which is used to check if necessary to call the Pop of heap by Timer.
}
// priorityQueueHeap is a heap manager, of which the underlying `array` is a array implementing a heap structure.
// priorityQueueHeap is a heap manager, of which the underlying `array` is an array implementing a heap structure.
type priorityQueueHeap struct {
array []priorityQueueItem
}

View File

@ -141,7 +141,7 @@ func Test_Func(t *testing.T) {
str = `{{"我是中国人" | substr 2 -1}};{{"我是中国人" | substr 2 2}}`
result, err = gview.ParseContent(context.TODO(), str, nil)
t.Assert(err != nil, false)
t.Assert(result, `中国;中国`)
t.Assert(result, `中国;中国`)
str = `{{"我是中国人" | strlimit 2 "..."}}`
result, err = gview.ParseContent(context.TODO(), str, nil)

View File

@ -7,6 +7,7 @@
package gtest_test
import (
"strconv"
"testing"
"github.com/gogf/gf/v2/test/gtest"
@ -17,7 +18,7 @@ func TestC(t *testing.T) {
t.Assert(1, 1)
t.AssertNE(1, 0)
t.AssertEQ(float32(123.456), float32(123.456))
t.AssertEQ(float64(123.456), float64(123.456))
t.AssertEQ(float32(123.456), float32(123.456))
})
}
@ -26,6 +27,123 @@ func TestCase(t *testing.T) {
t.Assert(1, 1)
t.AssertNE(1, 0)
t.AssertEQ(float32(123.456), float32(123.456))
t.AssertEQ(float64(123.456), float64(123.456))
t.AssertEQ(float32(123.456), float32(123.456))
})
}
func TestAssert(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
nilChan chan struct{}
)
t.Assert(1, 1)
t.Assert(nilChan, nil)
m1 := map[string]string{"k1": "v1", "k2": "v2"}
m2 := map[string]string{"k2": "v2", "k1": "v1"}
t.Assert(m1, m2)
})
}
func TestAssertEQ(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
nilChan chan struct{}
)
t.AssertEQ(nilChan, nil)
t.AssertEQ("0", "0")
t.AssertEQ(float32(123.456), float32(123.456))
m1 := map[string]string{"k1": "v1", "k2": "v2"}
m2 := map[string]string{"k2": "v2", "k1": "v1"}
t.AssertEQ(m1, m2)
})
}
func TestAssertNE(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
c = make(chan struct{}, 1)
)
t.AssertNE(nil, c)
t.AssertNE("0", "1")
t.AssertNE(float32(123.456), float32(123.4567))
m1 := map[string]string{"k1": "v1", "k2": "v2"}
m2 := map[string]string{"k2": "v1", "k1": "v2"}
t.AssertNE(m1, m2)
})
}
func TestAssertNQ(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNQ(1, "0")
t.AssertNQ(float32(123.456), float64(123.4567))
})
}
func TestAssertGT(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertGT("b", "a")
t.AssertGT(1, -1)
t.AssertGT(uint(1), uint(0))
t.AssertGT(float32(123.45678), float32(123.4567))
})
}
func TestAssertGE(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertGE("b", "a")
t.AssertGE("a", "a")
t.AssertGE(1, -1)
t.AssertGE(1, 1)
t.AssertGE(uint(1), uint(0))
t.AssertGE(uint(0), uint(0))
t.AssertGE(float32(123.45678), float32(123.4567))
t.AssertGE(float32(123.456), float32(123.456))
})
}
func TestAssertLT(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertLT("a", "b")
t.AssertLT(-1, 1)
t.AssertLT(uint(0), uint(1))
t.AssertLT(float32(123.456), float32(123.4567))
})
}
func TestAssertLE(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertLE("a", "b")
t.AssertLE("a", "a")
t.AssertLE(-1, 1)
t.AssertLE(1, 1)
t.AssertLE(uint(0), uint(1))
t.AssertLE(uint(0), uint(0))
t.AssertLE(float32(123.456), float32(123.4567))
t.AssertLE(float32(123.456), float32(123.456))
})
}
func TestAssertIN(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertIN("a", []string{"a", "b", "c"})
t.AssertIN(1, []int{1, 2, 3})
})
}
func TestAssertNI(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNI("d", []string{"a", "b", "c"})
t.AssertNI(4, []int{1, 2, 3})
})
}
func TestAssertNil(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
nilChan chan struct{}
)
t.AssertNil(nilChan)
_, err := strconv.ParseInt("123", 10, 64)
t.AssertNil(err)
})
}

View File

@ -17,10 +17,22 @@ func IsSubDomain(subDomain string, mainDomain string) bool {
if p := strings.IndexByte(mainDomain, ':'); p != -1 {
mainDomain = mainDomain[0:p]
}
subArray := strings.Split(subDomain, ".")
mainArray := strings.Split(mainDomain, ".")
subLength := len(subArray)
mainLength := len(mainArray)
var (
subArray = strings.Split(subDomain, ".")
mainArray = strings.Split(mainDomain, ".")
subLength = len(subArray)
mainLength = len(mainArray)
)
// Eg:
// "goframe.org" is not sub-domain of "s.goframe.org".
if mainLength > subLength {
for i := range mainArray[0 : mainLength-subLength] {
if mainArray[i] != "*" {
return false
}
}
}
// Eg:
// "s.s.goframe.org" is not sub-domain of "*.goframe.org"
// but

View File

@ -55,24 +55,37 @@ func StrTillEx(haystack string, needle string) string {
// The parameter `length` is optional, it uses the length of `str` in default.
func SubStr(str string, start int, length ...int) (substr string) {
strLength := len(str)
// Simple border checks.
if start < 0 {
start = 0
}
if start >= strLength {
start = strLength
}
end := strLength
if len(length) > 0 {
end = start + length[0]
if end < start {
end = strLength
if -start > strLength {
start = 0
} else {
start = strLength + start
}
} else if start > strLength {
return ""
}
if end > strLength {
end = strLength
realLength := 0
if len(length) > 0 {
realLength = length[0]
if realLength < 0 {
if -realLength > strLength-start {
realLength = 0
} else {
realLength = strLength - start + realLength
}
} else if realLength > strLength-start {
realLength = strLength - start
}
} else {
realLength = strLength - start
}
if realLength == strLength {
return str
} else {
end := start + realLength
return str[start:end]
}
return str[start:end]
}
// SubStrRune returns a portion of string `str` specified by the `start` and `length` parameters.
@ -85,20 +98,32 @@ func SubStrRune(str string, start int, length ...int) (substr string) {
runesLength = len(runes)
)
// Simple border checks.
strLength := runesLength
if start < 0 {
start = 0
}
if start >= runesLength {
start = runesLength
}
end := runesLength
if len(length) > 0 {
end = start + length[0]
if end < start {
end = runesLength
if -start > strLength {
start = 0
} else {
start = strLength + start
}
} else if start > strLength {
return ""
}
realLength := 0
if len(length) > 0 {
realLength = length[0]
if realLength < 0 {
if -realLength > strLength-start {
realLength = 0
} else {
realLength = strLength - start + realLength
}
} else if realLength > strLength-start {
realLength = strLength - start
}
} else {
realLength = strLength - start
}
end := start + realLength
if end > runesLength {
end = runesLength
}

View File

@ -58,4 +58,20 @@ func Test_IsSubDomain(t *testing.T) {
t.Assert(gstr.IsSubDomain("s.johng.cn", main), false)
t.Assert(gstr.IsSubDomain("s.s.johng.cn", main), false)
})
gtest.C(t, func(t *gtest.T) {
main := "*.*.goframe.org:8080"
t.Assert(gstr.IsSubDomain("goframe.org", main), true)
t.Assert(gstr.IsSubDomain("s.goframe.org", main), true)
t.Assert(gstr.IsSubDomain("s.s.goframe.org", main), true)
t.Assert(gstr.IsSubDomain("s.s.goframe.org:8000", main), true)
t.Assert(gstr.IsSubDomain("s.s.s.goframe.org", main), false)
t.Assert(gstr.IsSubDomain("johng.cn", main), false)
t.Assert(gstr.IsSubDomain("s.johng.cn", main), false)
t.Assert(gstr.IsSubDomain("s.s.johng.cn", main), false)
})
gtest.C(t, func(t *gtest.T) {
main := "s.goframe.org"
t.Assert(gstr.IsSubDomain("goframe.org", main), false)
})
}

View File

@ -89,8 +89,12 @@ func Test_SubStr(t *testing.T) {
t.Assert(gstr.SubStr("我爱GoFrame", 0), "我爱GoFrame")
t.Assert(gstr.SubStr("我爱GoFrame", 6), "GoFrame")
t.Assert(gstr.SubStr("我爱GoFrame", 6, 2), "Go")
t.Assert(gstr.SubStr("我爱GoFrame", -1, 30), "我爱GoFrame")
t.Assert(gstr.SubStr("我爱GoFrame", -1, 30), "e")
t.Assert(gstr.SubStr("我爱GoFrame", 30, 30), "")
t.Assert(gstr.SubStr("abcdef", 0, -1), "abcde")
t.Assert(gstr.SubStr("abcdef", 2, -1), "cde")
t.Assert(gstr.SubStr("abcdef", 4, -4), "")
t.Assert(gstr.SubStr("abcdef", -3, -1), "de")
})
}
@ -99,8 +103,16 @@ func Test_SubStrRune(t *testing.T) {
t.Assert(gstr.SubStrRune("我爱GoFrame", 0), "我爱GoFrame")
t.Assert(gstr.SubStrRune("我爱GoFrame", 2), "GoFrame")
t.Assert(gstr.SubStrRune("我爱GoFrame", 2, 2), "Go")
t.Assert(gstr.SubStrRune("我爱GoFrame", -1, 30), "我爱GoFrame")
t.Assert(gstr.SubStrRune("我爱GoFrame", -1, 30), "e")
t.Assert(gstr.SubStrRune("我爱GoFrame", 30, 30), "")
t.Assert(gstr.SubStrRune("abcdef", 0, -1), "abcde")
t.Assert(gstr.SubStrRune("abcdef", 2, -1), "cde")
t.Assert(gstr.SubStrRune("abcdef", 4, -4), "")
t.Assert(gstr.SubStrRune("abcdef", -3, -1), "de")
t.Assert(gstr.SubStrRune("我爱GoFrame呵呵", -3, 100), "e呵呵")
t.Assert(gstr.SubStrRune("abcdef哈哈", -3, -1), "f哈")
t.Assert(gstr.SubStrRune("ab我爱GoFramecdef哈哈", -3, -1), "f哈")
t.Assert(gstr.SubStrRune("我爱GoFrame", 0, 3), "我爱G")
})
}

View File

@ -23,6 +23,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/reflection"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gtag"
)
var (
@ -36,9 +37,11 @@ var (
}
// StructTagPriority defines the default priority tags for Map*/Struct* functions.
// Note, the `gconv/param/params` tags are used by old version of package.
// Note that, the `gconv/param` tags are used by old version of package.
// It is strongly recommended using short tag `c/p` instead in the future.
StructTagPriority = []string{"gconv", "param", "params", "c", "p", "json"}
StructTagPriority = []string{
gtag.GConv, gtag.Param, gtag.GConvShort, gtag.ParamShort, gtag.Json,
}
)
// Byte converts `any` to byte.

View File

@ -7,6 +7,7 @@
package gconv_test
import (
"github.com/gogf/gf/v2/container/gvar"
"math"
"testing"
"time"
@ -583,6 +584,7 @@ func Test_Float32_All(t *testing.T) {
t.AssertEQ(gconv.Float32([2]int{1, 2}), float32(0))
t.AssertEQ(gconv.Float32([]interface{}{}), float32(0))
t.AssertEQ(gconv.Float32([]map[int]int{}), float32(0))
t.AssertEQ(gconv.Float32(gvar.New(float32(0))), float32(0))
var countryCapitalMap = make(map[string]string)
/* map插入key - value对,各个国家对应的首都 */
@ -618,6 +620,7 @@ func Test_Float64_All(t *testing.T) {
t.AssertEQ(gconv.Float64([2]int{1, 2}), float64(0))
t.AssertEQ(gconv.Float64([]interface{}{}), float64(0))
t.AssertEQ(gconv.Float64([]map[int]int{}), float64(0))
t.AssertEQ(gconv.Float64(gvar.New(float64(0))), float64(0))
var countryCapitalMap = make(map[string]string)
/* map插入key - value对,各个国家对应的首都 */
@ -716,6 +719,7 @@ func Test_Bytes_All(t *testing.T) {
t.AssertEQ(gconv.Bytes(int32(0)), []uint8{0, 0, 0, 0})
t.AssertEQ(gconv.Bytes("s"), []uint8{115})
t.AssertEQ(gconv.Bytes([]byte("s")), []uint8{115})
t.AssertEQ(gconv.Bytes(gvar.New([]byte("s"))), []uint8{115})
})
}
@ -748,6 +752,7 @@ func Test_Convert_All(t *testing.T) {
t.AssertEQ(gconv.Convert([]byte{}, "[]byte"), []uint8{})
t.AssertEQ(gconv.Convert([]string{}, "[]string"), []string{})
t.AssertEQ(gconv.Convert([2]int{1, 2}, "[]int"), []int{1, 2})
t.AssertEQ(gconv.Convert([2]uint8{1, 2}, "[]uint8"), []uint8{1, 2})
t.AssertEQ(gconv.Convert("1989-01-02", "Time", "Y-m-d"), gconv.Time("1989-01-02", "Y-m-d"))
t.AssertEQ(gconv.Convert(1989, "Time"), gconv.Time("1970-01-01 08:33:09 +0800 CST"))
t.AssertEQ(gconv.Convert(gtime.Now(), "gtime.Time", 1), *gtime.New())
@ -758,6 +763,63 @@ func Test_Convert_All(t *testing.T) {
t.AssertEQ(gconv.Convert(1989, "Duration"), time.Duration(int64(1989)))
t.AssertEQ(gconv.Convert("1989", "Duration"), time.Duration(int64(1989)))
t.AssertEQ(gconv.Convert("1989", ""), "1989")
var intNum int = 1
t.Assert(gconv.Convert(&intNum, "*int"), int(1))
var int8Num int8 = 1
t.Assert(gconv.Convert(int8Num, "*int8"), int(1))
t.Assert(gconv.Convert(&int8Num, "*int8"), int(1))
var int16Num int16 = 1
t.Assert(gconv.Convert(int16Num, "*int16"), int(1))
t.Assert(gconv.Convert(&int16Num, "*int16"), int(1))
var int32Num int32 = 1
t.Assert(gconv.Convert(int32Num, "*int32"), int(1))
t.Assert(gconv.Convert(&int32Num, "*int32"), int(1))
var int64Num int64 = 1
t.Assert(gconv.Convert(int64Num, "*int64"), int(1))
t.Assert(gconv.Convert(&int64Num, "*int64"), int(1))
var uintNum uint = 1
t.Assert(gconv.Convert(&uintNum, "*uint"), int(1))
var uint8Num uint8 = 1
t.Assert(gconv.Convert(uint8Num, "*uint8"), int(1))
t.Assert(gconv.Convert(&uint8Num, "*uint8"), int(1))
var uint16Num uint16 = 1
t.Assert(gconv.Convert(uint16Num, "*uint16"), int(1))
t.Assert(gconv.Convert(&uint16Num, "*uint16"), int(1))
var uint32Num uint32 = 1
t.Assert(gconv.Convert(uint32Num, "*uint32"), int(1))
t.Assert(gconv.Convert(&uint32Num, "*uint32"), int(1))
var uint64Num uint64 = 1
t.Assert(gconv.Convert(uint64Num, "*uint64"), int(1))
t.Assert(gconv.Convert(&uint64Num, "*uint64"), int(1))
var float32Num float32 = 1.1
t.Assert(gconv.Convert(float32Num, "*float32"), float32(1.1))
t.Assert(gconv.Convert(&float32Num, "*float32"), float32(1.1))
var float64Num float64 = 1.1
t.Assert(gconv.Convert(float64Num, "*float64"), float64(1.1))
t.Assert(gconv.Convert(&float64Num, "*float64"), float64(1.1))
var boolValue bool = true
t.Assert(gconv.Convert(boolValue, "*bool"), true)
t.Assert(gconv.Convert(&boolValue, "*bool"), true)
var stringValue string = "1"
t.Assert(gconv.Convert(stringValue, "*string"), "1")
t.Assert(gconv.Convert(&stringValue, "*string"), "1")
var durationValue time.Duration = 1989
var expectDurationValue = time.Duration(int64(1989))
t.AssertEQ(gconv.Convert(&durationValue, "*time.Duration"), &expectDurationValue)
t.AssertEQ(gconv.Convert(durationValue, "*time.Duration"), &expectDurationValue)
var string_interface_map = map[string]interface{}{"k1": 1}
var string_int_map = map[string]int{"k1": 1}
var string_string_map = map[string]string{"k1": "1"}
t.AssertEQ(gconv.Convert(string_int_map, "map[string]string"), string_string_map)
t.AssertEQ(gconv.Convert(string_int_map, "map[string]interface{}"), string_interface_map)
})
}

View File

@ -38,6 +38,16 @@ func Test_Map_Basic(t *testing.T) {
t.Assert(gconv.Map(m3), g.Map{
"1.22": "3.1",
})
t.Assert(gconv.Map(`{"name":"goframe"}`), g.Map{
"name": "goframe",
})
t.Assert(gconv.Map(`{"name":"goframe"`), nil)
t.Assert(gconv.Map(`{goframe}`), nil)
t.Assert(gconv.Map([]byte(`{"name":"goframe"}`)), g.Map{
"name": "goframe",
})
t.Assert(gconv.Map([]byte(`{"name":"goframe"`)), nil)
t.Assert(gconv.Map([]byte(`{goframe}`)), nil)
})
}
@ -69,6 +79,44 @@ func Test_Maps_Basic(t *testing.T) {
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
gtest.C(t, func(t *gtest.T) {
list := gconv.SliceMap(params)
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
gtest.C(t, func(t *gtest.T) {
list := gconv.SliceMapDeep(params)
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
gtest.C(t, func(t *gtest.T) {
type Base struct {
Age int
}
type User struct {
Id int
Name string
Base
}
users := make([]User, 0)
params := []g.Map{
{"id": 1, "name": "john", "age": 18},
{"id": 2, "name": "smith", "age": 20},
}
err := gconv.SliceStruct(params, &users)
t.AssertNil(err)
t.Assert(len(users), 2)
t.Assert(users[0].Id, params[0]["id"])
t.Assert(users[0].Name, params[0]["name"])
t.Assert(users[0].Age, 18)
t.Assert(users[1].Id, params[1]["id"])
t.Assert(users[1].Name, params[1]["name"])
t.Assert(users[1].Age, 20)
})
}
func Test_Maps_JsonStr(t *testing.T) {
@ -78,6 +126,18 @@ func Test_Maps_JsonStr(t *testing.T) {
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
list = gconv.Maps([]byte(jsonStr))
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gconv.Maps(`[id]`), nil)
t.Assert(gconv.Maps(`test`), nil)
t.Assert(gconv.Maps([]byte(`[id]`)), nil)
t.Assert(gconv.Maps([]byte(`test`)), nil)
})
}
@ -477,3 +537,72 @@ field3:
t.Assert(string(jsonData), `{"field3":{"123":"integer_key"},"outer_struct":{"field1":{"inner1":123,"inner2":345},"field2":{"inner1":123,"inner2":345,"inner3":456,"inner4":789}}}`)
})
}
func TestMapStrStr(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gconv.MapStrStr(map[string]string{"k": "v"}), map[string]string{"k": "v"})
t.Assert(gconv.MapStrStr(`{}`), nil)
})
}
func TestMapStrStrDeep(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gconv.MapStrStrDeep(map[string]string{"k": "v"}), map[string]string{"k": "v"})
t.Assert(gconv.MapStrStrDeep(`{"k":"v"}`), map[string]string{"k": "v"})
t.Assert(gconv.MapStrStrDeep(`{}`), nil)
})
}
func TestMapsDeep(t *testing.T) {
jsonStr := `[{"id":100, "name":"john"},{"id":200, "name":"smith"}]`
params := g.Slice{
g.Map{"id": 100, "name": "john"},
g.Map{"id": 200, "name": "smith"},
}
gtest.C(t, func(t *gtest.T) {
t.Assert(gconv.MapsDeep(nil), nil)
})
gtest.C(t, func(t *gtest.T) {
list := gconv.MapsDeep(params)
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
gtest.C(t, func(t *gtest.T) {
list := gconv.MapsDeep(jsonStr)
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
list = gconv.MapsDeep([]byte(jsonStr))
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gconv.MapsDeep(`[id]`), nil)
t.Assert(gconv.MapsDeep(`test`), nil)
t.Assert(gconv.MapsDeep([]byte(`[id]`)), nil)
t.Assert(gconv.MapsDeep([]byte(`test`)), nil)
t.Assert(gconv.MapsDeep([]string{}), nil)
})
gtest.C(t, func(t *gtest.T) {
string_interface_map_list := []map[string]interface{}{}
string_interface_map_list = append(string_interface_map_list, map[string]interface{}{"id": 100})
string_interface_map_list = append(string_interface_map_list, map[string]interface{}{"id": 200})
list := gconv.MapsDeep(string_interface_map_list)
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
list = gconv.MapsDeep([]byte(jsonStr))
t.Assert(len(list), 2)
t.Assert(list[0]["id"], 100)
t.Assert(list[1]["id"], 200)
})
}

View File

@ -67,6 +67,18 @@ func Test_MapToMap1(t *testing.T) {
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
// string -> map[string]interface{}
gtest.C(t, func(t *gtest.T) {
jsonStr := `{"id":100, "name":"john"}`
m1 := g.MapStrAny{}
t.Assert(gconv.MapToMap(jsonStr, &m1), nil)
t.Assert(m1["id"], 100)
m2 := g.MapStrAny{}
t.Assert(gconv.MapToMap([]byte(jsonStr), &m2), nil)
t.Assert(m2["id"], 100)
})
}
func Test_MapToMap2(t *testing.T) {
@ -162,6 +174,18 @@ func Test_MapToMaps(t *testing.T) {
t.Assert(len(s), 2)
t.Assert(s, params)
})
gtest.C(t, func(t *gtest.T) {
jsonStr := `[{"id":100, "name":"john"},{"id":200, "name":"smith"}]`
var m1 []g.Map
t.Assert(gconv.MapToMaps(jsonStr, &m1), nil)
t.Assert(m1[0]["id"], 100)
t.Assert(m1[1]["id"], 200)
t.Assert(gconv.MapToMaps([]byte(jsonStr), &m1), nil)
t.Assert(m1[0]["id"], 100)
t.Assert(m1[1]["id"], 200)
})
}
func Test_MapToMaps_StructParams(t *testing.T) {

View File

@ -22,9 +22,20 @@ func Test_Slice(t *testing.T) {
t.AssertEQ(gconv.Bytes([]interface{}{1}), []byte{1})
t.AssertEQ(gconv.Bytes([]interface{}{300}), []byte("[300]"))
t.AssertEQ(gconv.Strings(value), []string{"123.456"})
t.AssertEQ(gconv.SliceStr(value), []string{"123.456"})
t.AssertEQ(gconv.SliceInt(value), []int{123})
t.AssertEQ(gconv.SliceUint(value), []uint{123})
t.AssertEQ(gconv.SliceUint32(value), []uint32{123})
t.AssertEQ(gconv.SliceUint64(value), []uint64{123})
t.AssertEQ(gconv.SliceInt32(value), []int32{123})
t.AssertEQ(gconv.SliceInt64(value), []int64{123})
t.AssertEQ(gconv.Ints(value), []int{123})
t.AssertEQ(gconv.SliceFloat(value), []float64{123.456})
t.AssertEQ(gconv.Floats(value), []float64{123.456})
t.AssertEQ(gconv.SliceFloat32(value), []float32{123.456})
t.AssertEQ(gconv.SliceFloat64(value), []float64{123.456})
t.AssertEQ(gconv.Interfaces(value), []interface{}{123.456})
t.AssertEQ(gconv.SliceAny(" [26, 27] "), []interface{}{26, 27})
})
gtest.C(t, func(t *gtest.T) {
s := []*gvar.Var{
@ -40,14 +51,205 @@ func Test_Slice_Ints(t *testing.T) {
t.AssertEQ(gconv.Ints(nil), nil)
t.AssertEQ(gconv.Ints("[26, 27]"), []int{26, 27})
t.AssertEQ(gconv.Ints(" [26, 27] "), []int{26, 27})
t.AssertEQ(gconv.Ints([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []int{0, 0})
t.AssertEQ(gconv.Ints([]bool{true, false}), []int{1, 0})
t.AssertEQ(gconv.Ints([][]byte{[]byte{byte(1)}, []byte{byte(2)}}), []int{1, 2})
})
}
func Test_Slice_Int32s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Int32s(nil), nil)
t.AssertEQ(gconv.Int32s(" [26, 27] "), []int32{26, 27})
t.AssertEQ(gconv.Int32s([]string{"1", "2"}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]int{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]int8{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]int16{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]int32{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]int64{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]uint{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]uint8{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []int32{0, 0})
t.AssertEQ(gconv.Int32s([]uint16{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]uint32{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]uint64{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]bool{true, false}), []int32{1, 0})
t.AssertEQ(gconv.Int32s([]float32{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([]float64{1, 2}), []int32{1, 2})
t.AssertEQ(gconv.Int32s([][]byte{[]byte{byte(1)}, []byte{byte(2)}}), []int32{1, 2})
s := []*gvar.Var{
gvar.New(1),
gvar.New(2),
}
t.AssertEQ(gconv.SliceInt32(s), []int32{1, 2})
})
}
func Test_Slice_Int64s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Int64s(nil), nil)
t.AssertEQ(gconv.Int64s(" [26, 27] "), []int64{26, 27})
t.AssertEQ(gconv.Int64s([]string{"1", "2"}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]int{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]int8{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]int16{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]int32{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]int64{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]uint{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]uint8{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []int64{0, 0})
t.AssertEQ(gconv.Int64s([]uint16{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]uint32{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]uint64{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]bool{true, false}), []int64{1, 0})
t.AssertEQ(gconv.Int64s([]float32{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([]float64{1, 2}), []int64{1, 2})
t.AssertEQ(gconv.Int64s([][]byte{[]byte{byte(1)}, []byte{byte(2)}}), []int64{1, 2})
s := []*gvar.Var{
gvar.New(1),
gvar.New(2),
}
t.AssertEQ(gconv.Int64s(s), []int64{1, 2})
})
}
func Test_Slice_Uints(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Uints(nil), nil)
t.AssertEQ(gconv.Uints("1"), []uint{1})
t.AssertEQ(gconv.Uints(" [26, 27] "), []uint{26, 27})
t.AssertEQ(gconv.Uints([]string{"1", "2"}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]int{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]int8{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]int16{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]int32{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]int64{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]uint{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]uint8{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []uint{0, 0})
t.AssertEQ(gconv.Uints([]uint16{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]uint32{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]uint64{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]bool{true, false}), []uint{1, 0})
t.AssertEQ(gconv.Uints([]float32{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([]float64{1, 2}), []uint{1, 2})
t.AssertEQ(gconv.Uints([][]byte{[]byte{byte(1)}, []byte{byte(2)}}), []uint{1, 2})
s := []*gvar.Var{
gvar.New(1),
gvar.New(2),
}
t.AssertEQ(gconv.Uints(s), []uint{1, 2})
})
}
func Test_Slice_Uint32s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Uint32s(nil), nil)
t.AssertEQ(gconv.Uint32s("1"), []uint32{1})
t.AssertEQ(gconv.Uint32s(" [26, 27] "), []uint32{26, 27})
t.AssertEQ(gconv.Uint32s([]string{"1", "2"}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]int{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]int8{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]int16{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]int32{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]int64{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]uint{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]uint8{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []uint32{0, 0})
t.AssertEQ(gconv.Uint32s([]uint16{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]uint32{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]uint64{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]bool{true, false}), []uint32{1, 0})
t.AssertEQ(gconv.Uint32s([]float32{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([]float64{1, 2}), []uint32{1, 2})
t.AssertEQ(gconv.Uint32s([][]byte{[]byte{byte(1)}, []byte{byte(2)}}), []uint32{1, 2})
s := []*gvar.Var{
gvar.New(1),
gvar.New(2),
}
t.AssertEQ(gconv.Uint32s(s), []uint32{1, 2})
})
}
func Test_Slice_Uint64s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Uint64s(nil), nil)
t.AssertEQ(gconv.Uint64s("[26, 27]"), []uint64{26, 27})
t.AssertEQ(gconv.Uint64s("1"), []uint64{1})
t.AssertEQ(gconv.Uint64s(" [26, 27] "), []uint64{26, 27})
t.AssertEQ(gconv.Uint64s([]string{"1", "2"}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]int{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]int8{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]int16{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]int32{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]int64{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]uint{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]uint8{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []uint64{0, 0})
t.AssertEQ(gconv.Uint64s([]uint16{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]uint64{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]uint64{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]bool{true, false}), []uint64{1, 0})
t.AssertEQ(gconv.Uint64s([]float32{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([]float64{1, 2}), []uint64{1, 2})
t.AssertEQ(gconv.Uint64s([][]byte{[]byte{byte(1)}, []byte{byte(2)}}), []uint64{1, 2})
s := []*gvar.Var{
gvar.New(1),
gvar.New(2),
}
t.AssertEQ(gconv.Uint64s(s), []uint64{1, 2})
})
}
func Test_Slice_Float32s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Float32s("123.4"), []float32{123.4})
t.AssertEQ(gconv.Float32s([]string{"123.4", "123.5"}), []float32{123.4, 123.5})
t.AssertEQ(gconv.Float32s([]int{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]int8{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]int16{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]int32{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]int64{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]uint{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]uint8{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []float32{0, 0})
t.AssertEQ(gconv.Float32s([]uint16{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]uint32{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]uint64{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]bool{true, false}), []float32{0, 0})
t.AssertEQ(gconv.Float32s([]float32{123}), []float32{123})
t.AssertEQ(gconv.Float32s([]float64{123}), []float32{123})
s := []*gvar.Var{
gvar.New(1.1),
gvar.New(2.1),
}
t.AssertEQ(gconv.SliceFloat32(s), []float32{1.1, 2.1})
})
}
func Test_Slice_Float64s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Float64s("123.4"), []float64{123.4})
t.AssertEQ(gconv.Float64s([]string{"123.4", "123.5"}), []float64{123.4, 123.5})
t.AssertEQ(gconv.Float64s([]int{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]int8{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]int16{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]int32{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]int64{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]uint{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]uint8{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`)), []float64{0, 0})
t.AssertEQ(gconv.Float64s([]uint16{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]uint32{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]uint64{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]bool{true, false}), []float64{0, 0})
t.AssertEQ(gconv.Float64s([]float32{123}), []float64{123})
t.AssertEQ(gconv.Float64s([]float64{123}), []float64{123})
})
}
@ -91,6 +293,14 @@ func Test_Slice_Empty(t *testing.T) {
t.AssertEQ(gconv.Float64s(""), []float64{})
t.Assert(gconv.Float64s(nil), nil)
})
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Strings(""), []string{})
t.Assert(gconv.Strings(nil), nil)
})
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.SliceAny(""), []interface{}{})
t.Assert(gconv.SliceAny(nil), nil)
})
}
func Test_Strings(t *testing.T) {
@ -101,6 +311,9 @@ func Test_Strings(t *testing.T) {
g.NewVar(3),
}
t.AssertEQ(gconv.Strings(array), []string{"1", "2", "3"})
t.AssertEQ(gconv.Strings([]uint8(`["1","2"]`)), []string{"1", "2"})
t.AssertEQ(gconv.Strings([][]byte{{byte(0)}, {byte(1)}}), []string{"\u0000", "\u0001"})
})
// https://github.com/gogf/gf/issues/1750
gtest.C(t, func(t *gtest.T) {
@ -109,6 +322,12 @@ func Test_Strings(t *testing.T) {
}
func Test_Slice_Interfaces(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := gconv.Interfaces([]uint8(`[{"id": 1, "name":"john"},{"id": 2, "name":"huang"}]`))
t.Assert(len(array), 2)
t.Assert(array[0].(g.Map)["id"], 1)
t.Assert(array[0].(g.Map)["name"], "john")
})
// map
gtest.C(t, func(t *gtest.T) {
array := gconv.Interfaces(g.Map{
@ -176,4 +395,22 @@ func Test_Slice_Structs(t *testing.T) {
t.Assert(users[1].Name, params[1]["name"])
t.Assert(users[1].Age, 20)
})
gtest.C(t, func(t *gtest.T) {
users := make([]User, 0)
params := []g.Map{
{"id": 1, "name": "john", "age": 18},
{"id": 2, "name": "smith", "age": 20},
}
err := gconv.StructsTag(params, &users, "")
t.AssertNil(err)
t.Assert(len(users), 2)
t.Assert(users[0].Id, params[0]["id"])
t.Assert(users[0].Name, params[0]["name"])
t.Assert(users[0].Age, 18)
t.Assert(users[1].Id, params[1]["id"])
t.Assert(users[1].Name, params[1]["name"])
t.Assert(users[1].Age, 20)
})
}

View File

@ -7,10 +7,11 @@
package gconv_test
import (
"testing"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gconv"
"testing"
"time"
)
type stringStruct1 struct {
@ -61,5 +62,10 @@ func Test_String(t *testing.T) {
t.AssertEQ(gconv.String(stringStruct2{"john"}), `{"Name":"john"}`)
t.AssertEQ(gconv.String(&stringStruct2{"john"}), `{"Name":"john"}`)
var nilTime *time.Time = nil
t.AssertEQ(gconv.String(nilTime), "")
var nilGTime *gtime.Time = nil
t.AssertEQ(gconv.String(nilGTime), "")
})
}

View File

@ -541,8 +541,8 @@ func Test_StructEmbedded4(t *testing.T) {
func Test_StructEmbedded5(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type Base struct {
Pass1 string `params:"password1"`
Pass2 string `params:"password2"`
Pass1 string `param:"password1"`
Pass2 string `param:"password2"`
}
type UserWithBase1 struct {
Id int

View File

@ -21,11 +21,13 @@ func Test_Time(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertEQ(gconv.Duration(""), time.Duration(int64(0)))
t.AssertEQ(gconv.GTime(""), gtime.New())
t.AssertEQ(gconv.GTime(nil), nil)
})
gtest.C(t, func(t *gtest.T) {
s := "2011-10-10 01:02:03.456"
t.AssertEQ(gconv.GTime(s), gtime.NewFromStr(s))
t.AssertEQ(gconv.Time(nil), time.Time{})
t.AssertEQ(gconv.Time(s), gtime.NewFromStr(s).Time)
t.AssertEQ(gconv.Duration(100), 100*time.Nanosecond)
})

View File

@ -204,7 +204,7 @@ func (p *Page) GetContent(mode int) string {
}
// GetUrl parses the UrlTemplate with given page number and returns the URL string.
// Note that the UrlTemplate attribute can be either an URL or a URI string with "{.page}"
// Note that the UrlTemplate attribute can be either an URL or an URI string with "{.page}"
// place holder specifying the page number position.
func (p *Page) GetUrl(page int) string {
return gstr.Replace(p.UrlTemplate, DefaultPagePlaceHolder, gconv.String(page))

View File

@ -28,7 +28,7 @@ func init() {
go asyncProducingRandomBufferBytesLoop()
}
// asyncProducingRandomBufferBytes is a named goroutine, which uses a asynchronous goroutine
// asyncProducingRandomBufferBytes is a named goroutine, which uses an asynchronous goroutine
// to produce the random bytes, and a buffer chan to store the random bytes.
// So it has high performance to generate random numbers.
func asyncProducingRandomBufferBytesLoop() {

View File

@ -10,60 +10,38 @@
// which means you cannot call them in runtime but in boot procedure.
package gtag
import (
"regexp"
"github.com/gogf/gf/v2/errors/gerror"
const (
Default = "default" // Default value tag of struct field for receiving parameters from HTTP request.
DefaultShort = "d" // Short name of Default.
Param = "param" // Parameter name for converting certain parameter to specified struct field.
ParamShort = "p" // Short name of Param.
Valid = "valid" // Validation rule tag for struct of field.
ValidShort = "v" // Short name of Valid.
NoValidation = "nv" // No validation for specified struct/field.
ORM = "orm" // ORM tag for ORM feature, which performs different features according scenarios.
Arg = "arg" // Arg tag for struct, usually for command argument option.
Brief = "brief" // Brief tag for struct, usually be considered as summary.
Root = "root" // Root tag for struct, usually for nested commands management.
Additional = "additional" // Additional tag for struct, usually for additional description of command.
AdditionalShort = "ad" // Short name of Additional.
Path = `path` // Route path for HTTP request.
Method = `method` // Route method for HTTP request.
Domain = `domain` // Route domain for HTTP request.
Mime = `mime` // MIME type for HTTP request/response.
Consumes = `consumes` // MIME type for HTTP request.
Summary = `summary` // Summary for struct, usually for OpenAPI in request struct.
SummaryShort = `sm` // Short name of Summary.
SummaryShort2 = `sum` // Short name of Summary.
Description = `description` // Description for struct, usually for OpenAPI in request struct.
DescriptionShort = `dc` // Short name of Description.
DescriptionShort2 = `des` // Short name of Description.
Example = `example` // Example for struct, usually for OpenAPI in request struct.
ExampleShort = `eg` // Short name of Example.
Examples = `examples` // Examples for struct, usually for OpenAPI in request struct.
ExamplesShort = `egs` // Short name of Examples.
ExternalDocs = `externalDocs` // External docs for struct, always for OpenAPI in request struct.
ExternalDocsShort = `ed` // Short name of ExternalDocs.
GConv = "gconv" // GConv defines the converting target name for specified struct field.
GConvShort = "c" // GConv defines the converting target name for specified struct field.
Json = "json" // Json tag is supported by stdlib.
)
var (
data = make(map[string]string)
regex = regexp.MustCompile(`\{(.+?)\}`)
)
// Set sets tag content for specified name.
// Note that it panics if `name` already exists.
func Set(name, value string) {
if _, ok := data[name]; ok {
panic(gerror.Newf(`value for tag name "%s" already exists`, name))
}
data[name] = value
}
// SetOver performs as Set, but it overwrites the old value if `name` already exists.
func SetOver(name, value string) {
data[name] = value
}
// Sets sets multiple tag content by map.
func Sets(m map[string]string) {
for k, v := range m {
Set(k, v)
}
}
// SetsOver performs as Sets, but it overwrites the old value if `name` already exists.
func SetsOver(m map[string]string) {
for k, v := range m {
SetOver(k, v)
}
}
// Get retrieves and returns the stored tag content for specified name.
func Get(name string) string {
return data[name]
}
// Parse parses and returns the content by replacing all tag name variable to
// its content for given `content`.
// Eg:
// gtag.Set("demo", "content")
// Parse(`This is {demo}`) -> `This is content`.
func Parse(content string) string {
return regex.ReplaceAllStringFunc(content, func(s string) string {
if v, ok := data[s[1:len(s)-1]]; ok {
return v
}
return s
})
}

65
util/gtag/gtag_func.go Normal file
View File

@ -0,0 +1,65 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gtag
import (
"regexp"
"github.com/gogf/gf/v2/errors/gerror"
)
var (
data = make(map[string]string)
regex = regexp.MustCompile(`\{(.+?)\}`)
)
// Set sets tag content for specified name.
// Note that it panics if `name` already exists.
func Set(name, value string) {
if _, ok := data[name]; ok {
panic(gerror.Newf(`value for tag name "%s" already exists`, name))
}
data[name] = value
}
// SetOver performs as Set, but it overwrites the old value if `name` already exists.
func SetOver(name, value string) {
data[name] = value
}
// Sets sets multiple tag content by map.
func Sets(m map[string]string) {
for k, v := range m {
Set(k, v)
}
}
// SetsOver performs as Sets, but it overwrites the old value if `name` already exists.
func SetsOver(m map[string]string) {
for k, v := range m {
SetOver(k, v)
}
}
// Get retrieves and returns the stored tag content for specified name.
func Get(name string) string {
return data[name]
}
// Parse parses and returns the content by replacing all tag name variable to
// its content for given `content`.
// Eg:
// gtag.Set("demo", "content")
// Parse(`This is {demo}`) -> `This is content`.
func Parse(content string) string {
return regex.ReplaceAllStringFunc(content, func(s string) string {
if v, ok := data[s[1:len(s)-1]]; ok {
return v
}
return s
})
}

View File

@ -15,6 +15,7 @@ import (
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/util/gtag"
)
// CustomMsg is the custom error message type,
@ -42,7 +43,7 @@ const (
internalErrorMapKey = "__InternalError__" // error map key for internal errors.
internalDefaultRuleName = "__default__" // default rule name for i18n error message format if no i18n message found for specified error rule.
ruleMessagePrefixForI18n = "gf.gvalid.rule." // prefix string for each rule configuration in i18n content.
noValidationTagName = "nv" // no validation tag name for struct attribute.
noValidationTagName = gtag.NoValidation // no validation tag name for struct attribute.
ruleNameRegex = "regex" // the name for rule "regex"
ruleNameNotRegex = "not-regex" // the name for rule "not-regex"
ruleNameForeach = "foreach" // the name for rule "foreach"
@ -60,8 +61,11 @@ var (
internalDefaultRuleName: "The {field} value `{value}` is invalid",
}
structTagPriority = []string{"gvalid", "valid", "v"} // structTagPriority specifies the validation tag priority array.
aliasNameTagPriority = []string{"param", "params", "p"} // aliasNameTagPriority specifies the alias tag priority array.
// structTagPriority specifies the validation tag priority array.
structTagPriority = []string{gtag.Valid, gtag.ValidShort}
// aliasNameTagPriority specifies the alias tag priority array.
aliasNameTagPriority = []string{gtag.Param, gtag.ParamShort}
// all internal error keys.
internalErrKeyMap = map[string]string{

View File

@ -116,8 +116,8 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type LoginRequest struct {
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
var login LoginRequest
err := g.Validator().Data(login).Run(context.TODO())
@ -129,8 +129,8 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type LoginRequest struct {
Username string `json:"username" gvalid:"@required#用户名不能为空"`
Password string `json:"password" gvalid:"@required#登录密码不能为空"`
Username string `json:"username" valid:"@required#用户名不能为空"`
Password string `json:"password" valid:"@required#登录密码不能为空"`
}
var login LoginRequest
err := g.Validator().Data(login).Run(context.TODO())
@ -139,8 +139,8 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type LoginRequest struct {
username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
var login LoginRequest
err := g.Validator().Data(login).Run(context.TODO())
@ -151,10 +151,10 @@ func Test_CheckStruct(t *testing.T) {
// gvalid tag
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int `gvalid:"uid@required|min:10#|ID不能为空"`
Age int `gvalid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Id int `valid:"uid@required|min:10#|ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,
@ -169,10 +169,10 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int `gvalid:"uid@required|min:10#|ID不能为空"`
Age int `gvalid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Id int `valid:"uid@required|min:10#|ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,
@ -192,10 +192,10 @@ func Test_CheckStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int `gvalid:"uid@required|min:10#ID不能为空"`
Age int `gvalid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Id int `valid:"uid@required|min:10#ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,
@ -212,8 +212,8 @@ func Test_CheckStruct(t *testing.T) {
type User struct {
Id int `valid:"uid@required|min:10#|ID不能为空"`
Age int `valid:"age@required#年龄不能为空"`
Username string `json:"username" gvalid:"username@required#用户名不能为空"`
Password string `json:"password" gvalid:"password@required#登录密码不能为空"`
Username string `json:"username" valid:"username@required#用户名不能为空"`
Password string `json:"password" valid:"password@required#登录密码不能为空"`
}
user := &User{
Id: 1,

View File

@ -344,7 +344,7 @@ func Test_CheckStruct_Recursively_MapAttribute(t *testing.T) {
// https://github.com/gogf/gf/issues/1983
func Test_Issue1983(t *testing.T) {
// Error as the attribute Student in Teacher is a initialized struct, which has default value.
// Error as the attribute Student in Teacher is an initialized struct, which has default value.
gtest.C(t, func(t *gtest.T) {
type Student struct {
Name string `v:"required"`

View File

@ -2,5 +2,5 @@ package gf
const (
// VERSION is the current GoFrame version.
VERSION = "v2.2.2"
VERSION = "v2.2.4"
)