Compare commits

..

34 Commits

Author SHA1 Message Date
4553f90a83 improve lru clearing for package gcache (#2327) 2022-11-25 10:45:56 +08:00
ef7fec7e24 fix issue in failed installing when there's shortcut between file paths for command install (#2326)
* fix issue in failed installing when has shortcut between file paths for command install

* version updates

* template for command gf updates
2022-11-25 10:34:00 +08:00
0a76b9c61b fix invalid UpdatedAt usage in soft deleting feature for package gdb (#2323) 2022-11-24 21:23:15 +08:00
fbeb8f81ac add ut cases for package glog part2 (#2317) 2022-11-21 10:32:08 +08:00
62af4f1c2c add zookeeper registry support (#2284) 2022-11-18 14:07:17 +08:00
ed43efe4fb add ut cases for package gdebug (#2313)
* add ut cases for package gdebug

* add ut cases for package gdebug

* add ut cases for package gdebug

Co-authored-by: houseme <housemecn@gmail.com>
2022-11-18 14:05:39 +08:00
1cb42c32e3 add ut cases for package g (#2315) 2022-11-18 14:05:16 +08:00
628b454ebc feat: cmd gf prebuild suport oracle (#2312) 2022-11-17 21:07:12 +08:00
38a858d7d3 change result data type of function Count from int to int64 for package gdb (#2298)
* feat: modify model count value int64

* fix

* fix:modify int64

* fix
2022-11-17 19:47:17 +08:00
83b92ddfa4 add ut cases for package glog (#2302)
* add ut cases for package glog

* add ut cases for package glog

* add ut cases for package glog

* add ut cases for package glog

* add ut cases for package glog

* add ut cases for package glog
2022-11-17 19:44:48 +08:00
7cd415b1df add ut cases for package gtime (#2303)
* add ut cases for package gtime

* add ut cases for package gtime

* add ut cases for package gtime
2022-11-17 19:44:20 +08:00
d2113b4d23 add ut cases for package gerror (#2304)
* add ut cases for package gerror

* add ut cases for package gerror
2022-11-17 19:43:54 +08:00
d445987f95 add ut cases for package gcode (#2307) 2022-11-17 19:43:04 +08:00
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
131 changed files with 4076 additions and 1036 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

@ -127,19 +127,25 @@ jobs:
ports:
- 5236:5236
zookeeper:
image: loads/zookeeper:3.8
ports:
- 2181:2181
strategy:
matrix:
go-version: [ "1.15", "1.16", "1.17", "1.18" ]
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 +160,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 +192,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

1
.gitignore vendored
View File

@ -17,4 +17,5 @@ cbuild
cmd/gf/main
cmd/gf/gf
go.work
go.work.sum
temp/

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,20 +1,61 @@
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/oracle/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
github.com/sijms/go-ora/v2 v2.4.20 // 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 (
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql/
github.com/gogf/gf/contrib/drivers/mysql/v2 => ../../contrib/drivers/mysql/
github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle/
github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql/
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite/
github.com/gogf/gf/v2 => ../../

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=
@ -93,13 +94,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/sijms/go-ora/v2 v2.4.20 h1:9e3z7VLBQXRAHGiIda1GEFtRhfxata0LghyMZqvLKew=
github.com/sijms/go-ora/v2 v2.4.20/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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.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 +112,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 +147,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 +192,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

@ -3,6 +3,7 @@ package cmd
import (
_ "github.com/gogf/gf/contrib/drivers/mssql/v2"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"

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
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -119,20 +119,13 @@ func (s serviceInstall) Run(ctx context.Context) (err error) {
dstPath := paths[selectedID]
// Install the new binary.
mlog.Debugf(`copy file from "%s" to "%s"`, gfile.SelfPath(), dstPath.filePath)
err = gfile.CopyFile(gfile.SelfPath(), dstPath.filePath)
if err != nil {
mlog.Printf("install gf binary to '%s' failed: %v", dstPath.dirPath, err)
mlog.Printf("you can manually install gf by copying the binary to folder: %s", dstPath.dirPath)
} else {
mlog.Printf("gf binary is successfully installed to: %s", dstPath.dirPath)
}
// Uninstall the old binary.
for _, path := range paths {
// Do not delete myself.
if path.filePath != "" && path.filePath != dstPath.filePath && gfile.SelfPath() != path.filePath {
_ = gfile.Remove(path.filePath)
}
mlog.Printf("gf binary is successfully installed to: %s", dstPath.filePath)
}
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

@ -42,7 +42,7 @@ func Test_Model_Raw(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Raw(fmt.Sprintf("select id from %s ", table)).Count()
t.Assert(count, 10)
t.Assert(count, int64(10))
t.AssertNil(err)
})
@ -104,7 +104,7 @@ func Test_Model_Insert(t *testing.T) {
}).Insert()
t.AssertNil(err)
value, err := db.Model(table).Fields("passport").Where("id=3").Value() //model value
value, err := db.Model(table).Fields("passport").Where("id=3").Value() // model value
t.AssertNil(err)
t.Assert(value.String(), "t3")
@ -122,7 +122,7 @@ func Test_Model_Insert(t *testing.T) {
t.AssertNil(err)
t.Assert(value.String(), "t4")
_, err = db.Model(table).Where("id>?", 1).Delete() //model delete
_, err = db.Model(table).Where("id>?", 1).Delete() // model delete
t.AssertNil(err)
})
@ -150,7 +150,7 @@ func Test_Model_One(t *testing.T) {
_, err := db.Model(table).Data(data).Insert()
t.AssertNil(err)
one, err := db.Model(table).WherePri(1).One() //model one
one, err := db.Model(table).WherePri(1).One() // model one
t.AssertNil(err)
t.Assert(one["passport"], data.Passport)
t.Assert(one["create_time"], data.CreateTime)
@ -249,12 +249,12 @@ func Test_Model_Count(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).FieldsEx("id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
}

View File

@ -12,6 +12,9 @@ import (
"testing"
"time"
"github.com/google/uuid"
"github.com/shopspring/decimal"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
@ -19,105 +22,103 @@ import (
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
"github.com/gogf/gf/v2/util/guid"
"github.com/google/uuid"
"github.com/shopspring/decimal"
)
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
`
)
@ -282,9 +283,9 @@ func TestDriverClickhouse_Insert(t *testing.T) {
Created time.Time `orm:"created"`
}
var (
insertUrl = "https://goframe.org"
total = 0
item = insertItem{
insertUrl = "https://goframe.org"
total int64 = 0
item = insertItem{
Duration: 1,
Url: insertUrl,
Created: time.Now(),
@ -296,7 +297,7 @@ func TestDriverClickhouse_Insert(t *testing.T) {
gtest.AssertNil(err)
total, err = connect.Model("visits").Count()
gtest.AssertNil(err)
gtest.AssertEQ(total, 2)
gtest.AssertEQ(total, int64(2))
var list []*insertItem
for i := 0; i < 50; i++ {
list = append(list, &insertItem{
@ -311,7 +312,7 @@ func TestDriverClickhouse_Insert(t *testing.T) {
gtest.AssertNil(err)
total, err = connect.Model("visits").Count()
gtest.AssertNil(err)
gtest.AssertEQ(total, 102)
gtest.AssertEQ(total, int64(102))
}
func TestDriverClickhouse_Insert_Use_Exec(t *testing.T) {
@ -466,7 +467,7 @@ func TestDriverClickhouse_NilTime(t *testing.T) {
gtest.AssertNil(err)
count, err := connect.Model("data_type").Where("Col4", "Inc.").Count()
gtest.AssertNil(err)
gtest.AssertEQ(count, 10000)
gtest.AssertEQ(count, int64(10000))
data, err := connect.Model("data_type").Where("Col4", "Inc.").One()
gtest.AssertNil(err)
@ -507,7 +508,7 @@ func TestDriverClickhouse_BatchInsert(t *testing.T) {
gtest.AssertNil(err)
count, err := connect.Model("data_type").Where("Col2", "ClickHouse").Where("Col3", "Inc").Count()
gtest.AssertNil(err)
gtest.AssertEQ(count, 10000)
gtest.AssertEQ(count, int64(10000))
}
func TestDriverClickhouse_Open(t *testing.T) {

View File

@ -307,7 +307,7 @@ func Test_Model_Clone(t *testing.T) {
result, err := md.Safe(true).Order("id ASC").All()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
t.Assert(record["ID"].Int(), 3)
t.Assert(len(result), 2)
t.Assert(result[0]["ID"].Int(), 1)
@ -323,42 +323,42 @@ func Test_Model_Safe(t *testing.T) {
md := db.Model(table).Safe(false).Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 1)
t.Assert(count, int64(1))
})
gtest.C(t, func(t *gtest.T) {
md := db.Model(table).Safe(true).Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
md := db.Model(table).Safe().Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
md1 := db.Model(table).Safe()
md2 := md1.Where("id in (?)", g.Slice{1, 3})
count, err := md2.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
all, err := md2.All()
t.AssertNil(err)
@ -380,7 +380,7 @@ func Test_Model_Safe(t *testing.T) {
// 1,3
count, err := md2.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
all, err := md2.Order("id asc").All()
t.AssertNil(err)
@ -395,7 +395,7 @@ func Test_Model_Safe(t *testing.T) {
// 4,5,6
count, err = md3.Count()
t.AssertNil(err)
t.Assert(count, 3)
t.Assert(count, int64(3))
all, err = md3.Order("id asc").All()
t.AssertNil(err)
@ -487,7 +487,7 @@ func Test_Model_Count(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Count with cache, check internal ctx data feature.
gtest.C(t, func(t *gtest.T) {
@ -498,24 +498,24 @@ func Test_Model_Count(t *testing.T) {
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
}
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).FieldsEx("id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Fields("distinct id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
// COUNT...LIMIT...
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Page(1, 2).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
@ -1809,7 +1809,7 @@ func Test_Model_Distinct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id > 1").Distinct().Count()
t.AssertNil(err)
t.Assert(count, 9)
t.Assert(count, int64(9))
})
}
@ -2310,7 +2310,7 @@ func Test_Model_Raw(t *testing.T) {
OrderDesc("id").
Count()
t.AssertNil(err)
t.Assert(count, 6)
t.Assert(count, int64(6))
})
}
@ -2398,38 +2398,38 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 0).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Where("nickname", "").Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Slice where.
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{1, 2, 3}).Count()
t.AssertNil(err)
t.Assert(count, 3)
t.Assert(count, int64(3))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", g.Slice{}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Struct Where.
gtest.C(t, func(t *gtest.T) {
@ -2439,7 +2439,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
}
count, err := db.Model(table).Where(Input{}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
type Input struct {
@ -2448,7 +2448,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
}
count, err := db.Model(table).Where(Input{}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Map Where.
gtest.C(t, func(t *gtest.T) {
@ -2457,7 +2457,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
"nickname": []string{},
}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
type Input struct {
@ -2467,7 +2467,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
"id": []int{},
}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}

View File

@ -581,7 +581,7 @@ func Test_DB_GetCount(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.GetCount(ctx, fmt.Sprintf("SELECT * FROM %s", table))
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}

View File

@ -81,20 +81,20 @@ func Test_Master_Slave(t *testing.T) {
_, err = masterSlaveDB.Model(table).Data(array).Insert()
t.AssertNil(err)
var count int
var count int64
// Auto slave.
count, err = masterSlaveDB.Model(table).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
// slave.
count, err = masterSlaveDB.Model(table).Slave().Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
// master.
count, err = masterSlaveDB.Model(table).Master().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}

View File

@ -462,7 +462,7 @@ func Test_Model_Clone(t *testing.T) {
result, err := md.Safe(true).Order("id ASC").All()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
t.Assert(record["id"].Int(), 3)
t.Assert(len(result), 2)
t.Assert(result[0]["id"].Int(), 1)
@ -478,42 +478,42 @@ func Test_Model_Safe(t *testing.T) {
md := db.Model(table).Safe(false).Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 1)
t.Assert(count, int64(1))
})
gtest.C(t, func(t *gtest.T) {
md := db.Model(table).Safe(true).Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
md := db.Model(table).Safe().Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
md1 := db.Model(table).Safe()
md2 := md1.Where("id in (?)", g.Slice{1, 3})
count, err := md2.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
all, err := md2.All()
t.AssertNil(err)
@ -535,7 +535,7 @@ func Test_Model_Safe(t *testing.T) {
// 1,3
count, err := md2.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
all, err := md2.Order("id asc").All()
t.AssertNil(err)
@ -550,7 +550,7 @@ func Test_Model_Safe(t *testing.T) {
// 4,5,6
count, err = md3.Count()
t.AssertNil(err)
t.Assert(count, 3)
t.Assert(count, int64(3))
all, err = md3.Order("id asc").All()
t.AssertNil(err)
@ -701,7 +701,7 @@ func Test_Model_Count(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Count with cache, check internal ctx data feature.
gtest.C(t, func(t *gtest.T) {
@ -712,35 +712,176 @@ func Test_Model_Count(t *testing.T) {
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
}
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).FieldsEx("id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Fields("distinct id,nickname").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
// COUNT...LIMIT...
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Page(1, 2).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
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, int64(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, int64(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, int64(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, int64(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, int64(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, int64(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, int64(1))
})
// 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_Select(t *testing.T) {
@ -982,7 +1123,7 @@ func Test_Model_StructsWithOrmTag(t *testing.T) {
dbInvalid.GetLogger().(*glog.Logger).SetWriter(buffer)
defer dbInvalid.GetLogger().(*glog.Logger).SetWriter(os.Stdout)
dbInvalid.Model(table).Order("id asc").Scan(&users)
//fmt.Println(buffer.String())
// fmt.Println(buffer.String())
t.Assert(
gstr.Contains(
buffer.String(),
@ -1845,7 +1986,7 @@ func Test_Model_Page(t *testing.T) {
t.AssertNil(err)
t.Assert(len(all), 3)
t.Assert(all[0]["id"], "7")
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
@ -2749,7 +2890,7 @@ func Test_Model_Distinct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id > 1").Distinct().Count()
t.AssertNil(err)
t.Assert(count, 9)
t.Assert(count, int64(9))
})
}
@ -3495,7 +3636,7 @@ func Test_Model_Increment_Decrement(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 91).Count()
t.AssertNil(err)
t.Assert(count, 1)
t.Assert(count, int64(1))
})
}
@ -3671,7 +3812,7 @@ func Test_Model_Raw(t *testing.T) {
Limit(2).
Count()
t.AssertNil(err)
t.Assert(count, 6)
t.Assert(count, int64(6))
})
}
@ -3759,38 +3900,38 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 0).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Where("nickname", "").Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Slice where.
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{1, 2, 3}).Count()
t.AssertNil(err)
t.Assert(count, 3)
t.Assert(count, int64(3))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", g.Slice{}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Struct Where.
gtest.C(t, func(t *gtest.T) {
@ -3800,7 +3941,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
}
count, err := db.Model(table).Where(Input{}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
type Input struct {
@ -3809,7 +3950,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
}
count, err := db.Model(table).Where(Input{}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Map Where.
gtest.C(t, func(t *gtest.T) {
@ -3818,7 +3959,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
"nickname": []string{},
}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
type Input struct {
@ -3828,7 +3969,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
"id": []int{},
}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
@ -4508,12 +4649,12 @@ func Test_Builder_OmitEmptyWhere(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 1).Count()
t.AssertNil(err)
t.Assert(count, 1)
t.Assert(count, int64(1))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 0).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
builder := db.Model(table).OmitEmptyWhere().Builder()
@ -4521,6 +4662,6 @@ func Test_Builder_OmitEmptyWhere(t *testing.T) {
builder.Where("id", 0),
).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}

View File

@ -138,7 +138,7 @@ func Test_TX_Insert(t *testing.T) {
if n, err := tx.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, 2)
t.Assert(n, int64(2))
}
if err := tx.Commit(); err != nil {
@ -180,7 +180,7 @@ func Test_TX_BatchInsert(t *testing.T) {
if n, err := db.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, 2)
t.Assert(n, int64(2))
}
})
}
@ -218,7 +218,7 @@ func Test_TX_BatchReplace(t *testing.T) {
if n, err := db.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, TableSize)
t.Assert(n, int64(TableSize))
}
if value, err := db.Model(table).Fields("password").Where("id", 2).Value(); err != nil {
gtest.Error(err)
@ -255,7 +255,7 @@ func Test_TX_BatchSave(t *testing.T) {
if n, err := db.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, TableSize)
t.Assert(n, int64(TableSize))
}
if value, err := db.Model(table).Fields("password").Where("id", 4).Value(); err != nil {
@ -428,7 +428,7 @@ func Test_TX_GetCount(t *testing.T) {
if count, err := tx.GetCount("SELECT * FROM " + table); err != nil {
gtest.Error(err)
} else {
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
}
if err := tx.Commit(); err != nil {
gtest.Error(err)
@ -674,7 +674,7 @@ func Test_TX_Delete(t *testing.T) {
if n, err := db.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, 0)
t.Assert(n, int64(0))
}
t.Assert(tx.IsClosed(), true)
@ -693,7 +693,7 @@ func Test_TX_Delete(t *testing.T) {
if n, err := tx.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, 0)
t.Assert(n, int64(0))
}
if err := tx.Rollback(); err != nil {
gtest.Error(err)
@ -701,8 +701,8 @@ func Test_TX_Delete(t *testing.T) {
if n, err := db.Model(table).Count(); err != nil {
gtest.Error(err)
} else {
t.Assert(n, TableSize)
t.AssertNE(n, 0)
t.Assert(n, int64(TableSize))
t.AssertNE(n, int64(0))
}
t.Assert(tx.IsClosed(), true)
@ -1136,6 +1136,6 @@ func Test_Transaction_Method(t *testing.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
}

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

@ -9,6 +9,10 @@ package oracle_test
import (
"database/sql"
"fmt"
"strings"
"testing"
"time"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
@ -16,9 +20,6 @@ import (
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/guid"
"github.com/gogf/gf/v2/util/gutil"
"strings"
"testing"
"time"
)
func Test_Model_InnerJoin(t *testing.T) {
@ -162,7 +163,7 @@ func TestPage(t *testing.T) {
func Test_Model_Insert(t *testing.T) {
table := createTable()
defer dropTable(table)
//db.SetDebug(true)
// db.SetDebug(true)
gtest.C(t, func(t *gtest.T) {
user := db.Model(table)
result, err := user.Data(g.Map{
@ -406,7 +407,7 @@ func Test_Model_Count(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Count with cache, check internal ctx data feature.
gtest.C(t, func(t *gtest.T) {
@ -417,24 +418,24 @@ func Test_Model_Count(t *testing.T) {
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
}
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).FieldsEx("ID").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Fields("distinct id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
// COUNT...LIMIT...
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Page(1, 2).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
@ -922,11 +923,11 @@ func Test_Model_Distinct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id > 1").Distinct().Count()
t.AssertNil(err)
t.Assert(count, 9)
t.Assert(count, int64(9))
})
}
//not support
// not support
/*
func Test_Model_Min_Max(t *testing.T) {
table := createInitTable()
@ -947,7 +948,7 @@ func Test_Model_Min_Max(t *testing.T) {
func Test_Model_HasTable(t *testing.T) {
table := createTable()
defer dropTable(table)
//db.SetDebug(true)
// db.SetDebug(true)
gtest.C(t, func(t *gtest.T) {
result, err := db.GetCore().HasTable(strings.ToUpper(table))
t.Assert(result, true)

View File

@ -64,7 +64,7 @@ func Test_Model_Insert(t *testing.T) {
t.AssertNil(err)
n, _ = result.RowsAffected()
t.Assert(n, 1)
value, err := db.Model(table).Fields("passport").Where("id=3").Value() //model value
value, err := db.Model(table).Fields("passport").Where("id=3").Value() // model value
t.AssertNil(err)
t.Assert(value.String(), "t3")
@ -83,7 +83,7 @@ func Test_Model_Insert(t *testing.T) {
t.AssertNil(err)
t.Assert(value.String(), "t4")
result, err = db.Model(table).Where("id>?", 1).Delete() //model delete
result, err = db.Model(table).Where("id>?", 1).Delete() // model delete
t.AssertNil(err)
n, _ = result.RowsAffected()
t.Assert(n, 3)
@ -112,7 +112,7 @@ func Test_Model_One(t *testing.T) {
_, err := db.Model(table).Data(data).Insert()
t.AssertNil(err)
one, err := db.Model(table).WherePri(1).One() //model one
one, err := db.Model(table).WherePri(1).One() // model one
t.AssertNil(err)
t.Assert(one["passport"], data.Passport)
t.Assert(one["create_time"], data.CreateTime)
@ -214,12 +214,12 @@ func Test_Model_Count(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).FieldsEx("id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
}

View File

@ -94,6 +94,6 @@ func Test_Raw_Update(t *testing.T) {
user := db.Model(table)
n, err := user.Where("id", 101).Count()
t.AssertNil(err)
t.Assert(n, 1)
t.Assert(n, int64(1))
})
}

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

@ -452,7 +452,7 @@ func Test_Model_Clone(t *testing.T) {
result, err := md.Safe(true).Order("id ASC").All()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
t.Assert(record["id"].Int(), 3)
t.Assert(len(result), 2)
t.Assert(result[0]["id"].Int(), 1)
@ -468,42 +468,42 @@ func Test_Model_Safe(t *testing.T) {
md := db.Model(table).Safe(false).Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 1)
t.Assert(count, int64(1))
})
gtest.C(t, func(t *gtest.T) {
md := db.Model(table).Safe(true).Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
md := db.Model(table).Safe().Where("id IN(?)", g.Slice{1, 3})
count, err := md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
md.Where("id = ?", 1)
count, err = md.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
md1 := db.Model(table).Safe()
md2 := md1.Where("id in (?)", g.Slice{1, 3})
count, err := md2.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
all, err := md2.All()
t.AssertNil(err)
@ -525,7 +525,7 @@ func Test_Model_Safe(t *testing.T) {
// 1,3
count, err := md2.Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
all, err := md2.Order("id asc").All()
t.AssertNil(err)
@ -540,7 +540,7 @@ func Test_Model_Safe(t *testing.T) {
// 4,5,6
count, err = md3.Count()
t.AssertNil(err)
t.Assert(count, 3)
t.Assert(count, int64(3))
all, err = md3.Order("id asc").All()
t.AssertNil(err)
@ -692,7 +692,7 @@ func Test_Model_Count(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Count with cache, check internal ctx data feature.
gtest.C(t, func(t *gtest.T) {
@ -703,24 +703,24 @@ func Test_Model_Count(t *testing.T) {
Force: false,
}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
}
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).FieldsEx("id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Fields("distinct id").Where("id>8").Count()
t.AssertNil(err)
t.Assert(count, 2)
t.Assert(count, int64(2))
})
// COUNT...LIMIT...
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Page(1, 2).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
@ -1819,7 +1819,7 @@ func Test_Model_Page(t *testing.T) {
t.AssertNil(err)
t.Assert(len(all), 3)
t.Assert(all[0]["id"], "7")
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}
@ -2369,7 +2369,7 @@ func Test_Model_Distinct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id > 1").Distinct().Count()
t.AssertNil(err)
t.Assert(count, 9)
t.Assert(count, int64(9))
})
}
@ -3171,7 +3171,7 @@ func Test_Model_Increment_Decrement(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 91).Count()
t.AssertNil(err)
t.Assert(count, 1)
t.Assert(count, int64(1))
})
}
@ -3202,7 +3202,7 @@ func Test_Model_Raw(t *testing.T) {
Limit(2).
Count()
t.AssertNil(err)
t.Assert(count, 6)
t.Assert(count, int64(6))
})
}
@ -3290,38 +3290,38 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", 0).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", 0).Where("nickname", "").Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Slice where.
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{1, 2, 3}).Count()
t.AssertNil(err)
t.Assert(count, 3)
t.Assert(count, int64(3))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).OmitEmptyWhere().Where("id", g.Slice{}).Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where("id", g.Slice{}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Struct Where.
gtest.C(t, func(t *gtest.T) {
@ -3331,7 +3331,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
}
count, err := db.Model(table).Where(Input{}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
type Input struct {
@ -3340,7 +3340,7 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
}
count, err := db.Model(table).Where(Input{}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
// Map Where.
gtest.C(t, func(t *gtest.T) {
@ -3349,14 +3349,14 @@ func Test_Model_OmitEmptyWhere(t *testing.T) {
"nickname": []string{},
}).Count()
t.AssertNil(err)
t.Assert(count, 0)
t.Assert(count, int64(0))
})
gtest.C(t, func(t *gtest.T) {
count, err := db.Model(table).Where(g.Map{
"id": []int{},
}).OmitEmptyWhere().Count()
t.AssertNil(err)
t.Assert(count, TableSize)
t.Assert(count, int64(TableSize))
})
}

View File

@ -0,0 +1,71 @@
# GoFrame Etcd Registry
Use `zookeeper` as service registration and discovery management.
## Installation
```
go get -u -v github.com/gogf/gf/contrib/registry/zookeeper/v2
```
suggested using `go.mod`:
```
require github.com/gogf/gf/contrib/registry/zookeeper/v2 latest
```
```go
package main
import (
"github.com/gogf/gf/contrib/registry/zookeeper/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/net/gsvc"
)
func main() {
r := zookeeper.New([]string{"127.0.0.1:2181"}, zookeeper.WithRootPath("/gogf"))
gsvc.SetRegistry(r)
s := g.Server(`hello.svc`)
s.BindHandler("/", func(r *ghttp.Request) {
g.Log().Info(r.Context(), `request received`)
r.Response.Write(`Hello world`)
})
s.Run()
}
```
```go
package main
import (
"fmt"
"time"
"github.com/gogf/gf/contrib/registry/zookeeper/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gsel"
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
gsvc.SetRegistry(zookeeper.New([]string{"127.0.0.1:2181"},zookeeper.WithRootPath("/gogf")))
gsel.SetBuilder(gsel.NewBuilderRoundRobin())
client := g.Client()
for i := 0; i < 100; i++ {
res, err := client.Get(gctx.New(), `http://hello.svc/`)
if err != nil {
panic(err)
}
fmt.Println(res.ReadAllString())
res.Close()
time.Sleep(time.Second)
}
}
```
## License
`GoFrame zookeeper` is licensed under the [MIT License](../../../LICENSE), 100% free and open-source, forever.

View File

@ -0,0 +1,11 @@
module github.com/gogf/gf/contrib/registry/zookeeper/v2
go 1.15
require (
github.com/go-zookeeper/zk v1.0.3
github.com/gogf/gf/v2 v2.2.2
golang.org/x/sync v0.1.0
)
replace github.com/gogf/gf/v2 => ../../../

View File

@ -0,0 +1,172 @@
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/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=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
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=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/gogf/gf/v2 v2.2.2 h1:ew4k/VSr/gcPdMZcI8/HZYBYPjB0KOk6bQqA61M8bYE=
github.com/gogf/gf/v2 v2.2.2/go.mod h1:thvkyb43RWUu/m05sRm4CbH9r7t7/FrW2M56L9Ystwk=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
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/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/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.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
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/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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
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 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
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 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/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=
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=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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-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-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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-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-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-20211216021012-1d35b9e2eb4e/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/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.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
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-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=

View File

@ -0,0 +1,71 @@
// 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 zookeeper implements service Registry and Discovery using zookeeper.
package zookeeper
import (
"github.com/go-zookeeper/zk"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/gsvc"
"golang.org/x/sync/singleflight"
"time"
)
var _ gsvc.Registry = &Registry{}
type Content struct {
Key string
Value string
}
// Option is etcd registry option.
type Option func(o *options)
type options struct {
namespace string
user string
password string
}
// WithRootPath with registry root path.
func WithRootPath(path string) Option {
return func(o *options) { o.namespace = path }
}
// WithDigestACL with registry password.
func WithDigestACL(user string, password string) Option {
return func(o *options) {
o.user = user
o.password = password
}
}
// Registry is consul registry
type Registry struct {
opts *options
conn *zk.Conn
group singleflight.Group
}
func New(address []string, opts ...Option) *Registry {
conn, _, err := zk.Connect(address, time.Second*120)
if err != nil {
panic(gerror.Wrapf(err,
"Error with connect to zookeeper"),
)
}
options := &options{
namespace: "/microservices",
}
for _, o := range opts {
o(options)
}
return &Registry{
opts: options,
conn: conn,
}
}

View File

@ -0,0 +1,71 @@
// 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 zookeeper
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/gsvc"
"path"
"strings"
)
// Search is the etcd discovery search function.
func (r *Registry) Search(_ context.Context, in gsvc.SearchInput) ([]gsvc.Service, error) {
prefix := strings.TrimPrefix(strings.ReplaceAll(in.Prefix, "/", "-"), "-")
instances, err, _ := r.group.Do(prefix, func() (interface{}, error) {
serviceNamePath := path.Join(r.opts.namespace, prefix)
servicesID, _, err := r.conn.Children(serviceNamePath)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with search the children node under %s",
serviceNamePath,
)
}
items := make([]gsvc.Service, 0, len(servicesID))
for _, service := range servicesID {
servicePath := path.Join(serviceNamePath, service)
byteData, _, err := r.conn.Get(servicePath)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with node data which name is %s",
servicePath,
)
}
item, err := unmarshal(byteData)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with unmarshal node data to Content",
)
}
svc, err := gsvc.NewServiceWithKV(item.Key, item.Value)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with new service with KV in Content",
)
}
items = append(items, svc)
}
return items, nil
})
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with group do",
)
}
return instances.([]gsvc.Service), nil
}
// Watch is the etcd discovery watch function.
func (r *Registry) Watch(ctx context.Context, key string) (gsvc.Watcher, error) {
return newWatcher(ctx, r.opts.namespace, key, r.conn)
}

View File

@ -0,0 +1,20 @@
// 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 zookeeper
import (
"encoding/json"
)
func unmarshal(data []byte) (c *Content, err error) {
err = json.Unmarshal(data, &c)
return
}
func marshal(c *Content) ([]byte, error) {
return json.Marshal(c)
}

View File

@ -0,0 +1,139 @@
// 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 zookeeper
import (
"context"
"github.com/go-zookeeper/zk"
"github.com/gogf/gf/v2/errors/gerror"
"path"
"strings"
"time"
"github.com/gogf/gf/v2/net/gsvc"
)
// Register registers `service` to Registry.
// Note that it returns a new Service if it changes the input Service with custom one.
func (r *Registry) Register(_ context.Context, service gsvc.Service) (gsvc.Service, error) {
var (
data []byte
err error
)
if err = r.ensureName(r.opts.namespace, []byte(""), 0); err != nil {
return service, gerror.Wrapf(
err,
"Error Creat node which name is %s",
r.opts.namespace,
)
}
prefix := strings.TrimPrefix(strings.ReplaceAll(service.GetPrefix(), "/", "-"), "-")
servicePrefixPath := path.Join(r.opts.namespace, prefix)
if err = r.ensureName(servicePrefixPath, []byte(""), 0); err != nil {
return service, gerror.Wrapf(
err,
"Error Creat node which name is %s",
servicePrefixPath,
)
}
if data, err = marshal(&Content{
Key: service.GetKey(),
Value: service.GetValue(),
}); err != nil {
return service, gerror.Wrapf(
err,
"Error with marshal Content to Json string",
)
}
servicePath := path.Join(servicePrefixPath, service.GetName())
if err = r.ensureName(servicePath, data, zk.FlagEphemeral); err != nil {
return service, gerror.Wrapf(
err,
"Error Creat node which name is %s",
servicePath,
)
}
go r.reRegister(servicePath, data)
return service, nil
}
// Deregister off-lines and removes `service` from the Registry.
func (r *Registry) Deregister(ctx context.Context, service gsvc.Service) error {
ch := make(chan error, 1)
prefix := strings.TrimPrefix(strings.ReplaceAll(service.GetPrefix(), "/", "-"), "-")
servicePath := path.Join(r.opts.namespace, prefix, service.GetName())
go func() {
err := r.conn.Delete(servicePath, -1)
ch <- err
}()
var err error
select {
case <-ctx.Done():
err = ctx.Err()
case err = <-ch:
}
return gerror.Wrapf(err,
"Error with deregister service:%s",
service.GetName(),
)
}
// ensureName ensure node exists, if not exist, create and set data
func (r *Registry) ensureName(path string, data []byte, flags int32) error {
exists, stat, err := r.conn.Exists(path)
if err != nil {
return gerror.Wrapf(err,
"Error with check node exist which name is %s",
path,
)
}
// ephemeral nodes handling after restart
// fixes a race condition if the server crashes without using CreateProtectedEphemeralSequential()
if flags&zk.FlagEphemeral == zk.FlagEphemeral {
err = r.conn.Delete(path, stat.Version)
if err != nil && err != zk.ErrNoNode {
return gerror.Wrapf(err,
"Error with delete node which name is %s",
path,
)
}
exists = false
}
if !exists {
if len(r.opts.user) > 0 && len(r.opts.password) > 0 {
_, err = r.conn.Create(path, data, flags, zk.DigestACL(zk.PermAll, r.opts.user, r.opts.password))
} else {
_, err = r.conn.Create(path, data, flags, zk.WorldACL(zk.PermAll))
}
if err != nil {
return gerror.Wrapf(err,
"Error with create node which name is %s",
path,
)
}
}
return nil
}
// reRegister re-register data node info when bad connection recovered
func (r *Registry) reRegister(path string, data []byte) {
sessionID := r.conn.SessionID()
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for range ticker.C {
cur := r.conn.SessionID()
// sessionID changed
if cur > 0 && sessionID != cur {
// re-ensureName
if err := r.ensureName(path, data, zk.FlagEphemeral); err != nil {
return
}
sessionID = cur
}
}
}

View File

@ -0,0 +1,138 @@
// 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 zookeeper
import (
"context"
"errors"
"github.com/go-zookeeper/zk"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/gsvc"
"golang.org/x/sync/singleflight"
"path"
"strings"
)
var _ gsvc.Watcher = (*watcher)(nil)
var ErrWatcherStopped = errors.New("watcher stopped")
type watcher struct {
ctx context.Context
event chan zk.Event
conn *zk.Conn
cancel context.CancelFunc
prefix string
nameSpace string
group singleflight.Group
}
func newWatcher(ctx context.Context, nameSpace, prefix string, conn *zk.Conn) (*watcher, error) {
w := &watcher{
conn: conn,
event: make(chan zk.Event, 1),
nameSpace: nameSpace,
prefix: prefix,
}
w.ctx, w.cancel = context.WithCancel(ctx)
go w.watch(w.ctx)
return w, nil
}
func (w *watcher) Proceed() ([]gsvc.Service, error) {
select {
case <-w.ctx.Done():
return nil, w.ctx.Err()
case e := <-w.event:
if e.State == zk.StateDisconnected {
return nil, gerror.Wrapf(
ErrWatcherStopped,
"watcher stopped",
)
}
if e.Err != nil {
return nil, e.Err
}
return w.getServicesByPrefix()
}
}
func (w *watcher) getServicesByPrefix() ([]gsvc.Service, error) {
prefix := strings.TrimPrefix(strings.ReplaceAll(w.prefix, "/", "-"), "-")
serviceNamePath := path.Join(w.nameSpace, prefix)
instances, err, _ := w.group.Do(serviceNamePath, func() (interface{}, error) {
servicesID, _, err := w.conn.Children(serviceNamePath)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with search the children node under %s",
serviceNamePath,
)
}
items := make([]gsvc.Service, 0, len(servicesID))
for _, service := range servicesID {
servicePath := path.Join(serviceNamePath, service)
byteData, _, err := w.conn.Get(servicePath)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with node data which name is %s",
servicePath,
)
}
item, err := unmarshal(byteData)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with unmarshal node data to Content",
)
}
svc, err := gsvc.NewServiceWithKV(item.Key, item.Value)
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with new service with KV in Content",
)
}
items = append(items, svc)
}
return items, nil
})
if err != nil {
return nil, gerror.Wrapf(
err,
"Error with group do",
)
}
return instances.([]gsvc.Service), nil
}
func (w *watcher) Close() error {
w.cancel()
return nil
}
func (w *watcher) watch(ctx context.Context) {
prefix := strings.TrimPrefix(strings.ReplaceAll(w.prefix, "/", "-"), "-")
serviceNamePath := path.Join(w.nameSpace, prefix)
for {
if w.conn.State() == zk.StateConnected || w.conn.State() == zk.StateHasSession {
// each watch action is only valid once
_, _, ch, err := w.conn.ChildrenW(serviceNamePath)
if err != nil {
w.event <- zk.Event{Err: err}
}
select {
case <-ctx.Done():
return
default:
w.event <- <-ch
}
}
}
}

View File

@ -0,0 +1,189 @@
// 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 zookeeper
import (
"context"
"testing"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/os/gctx"
)
// TestRegistry TestRegistryManyService
func TestRegistry(t *testing.T) {
r := New([]string{"127.0.0.1:2181"}, WithRootPath("/gogf"))
ctx := context.Background()
svc := &gsvc.LocalService{
Name: "goframe-provider-0-tcp",
Version: "test",
Metadata: map[string]interface{}{"app": "goframe", gsvc.MDProtocol: "tcp"},
Endpoints: gsvc.NewEndpoints("127.0.0.1:9000"),
}
s, err := r.Register(ctx, svc)
if err != nil {
t.Fatal(err)
}
err = r.Deregister(ctx, s)
if err != nil {
t.Fatal(err)
}
}
// TestRegistryMany TestRegistryManyService
func TestRegistryMany(t *testing.T) {
r := New([]string{"127.0.0.1:2181"}, WithRootPath("/gogf"))
svc := &gsvc.LocalService{
Name: "goframe-provider-1-tcp",
Version: "test",
Metadata: map[string]interface{}{"app": "goframe", gsvc.MDProtocol: "tcp"},
Endpoints: gsvc.NewEndpoints("127.0.0.1:9000"),
}
svc1 := &gsvc.LocalService{
Name: "goframe-provider-2-tcp",
Version: "test",
Metadata: map[string]interface{}{"app": "goframe", gsvc.MDProtocol: "tcp"},
Endpoints: gsvc.NewEndpoints("127.0.0.1:9001"),
}
svc2 := &gsvc.LocalService{
Name: "goframe-provider-3-tcp",
Version: "test",
Metadata: map[string]interface{}{"app": "goframe", gsvc.MDProtocol: "tcp"},
Endpoints: gsvc.NewEndpoints("127.0.0.1:9002"),
}
s0, err := r.Register(context.Background(), svc)
if err != nil {
t.Fatal(err)
}
s1, err := r.Register(context.Background(), svc1)
if err != nil {
t.Fatal(err)
}
s2, err := r.Register(context.Background(), svc2)
if err != nil {
t.Fatal(err)
}
err = r.Deregister(context.Background(), s0)
if err != nil {
t.Fatal(err)
}
err = r.Deregister(context.Background(), s1)
if err != nil {
t.Fatal(err)
}
err = r.Deregister(context.Background(), s2)
if err != nil {
t.Fatal(err)
}
}
// TestGetService Test GetService
func TestGetService(t *testing.T) {
r := New([]string{"127.0.0.1:2181"}, WithRootPath("/gogf"))
ctx := context.Background()
svc := &gsvc.LocalService{
Name: "goframe-provider-4-tcp",
Version: "test",
Metadata: map[string]interface{}{"app": "goframe", gsvc.MDProtocol: "tcp"},
Endpoints: gsvc.NewEndpoints("127.0.0.1:9000"),
}
s, err := r.Register(ctx, svc)
if err != nil {
t.Fatal(err)
}
time.Sleep(time.Second * 1)
serviceInstances, err := r.Search(ctx, gsvc.SearchInput{
Prefix: s.GetPrefix(),
Name: svc.Name,
Version: svc.Version,
Metadata: svc.Metadata,
})
if err != nil {
t.Fatal(err)
}
for _, instance := range serviceInstances {
g.Log().Info(ctx, instance)
}
err = r.Deregister(ctx, s)
if err != nil {
t.Fatal(err)
}
}
// TestWatch Test Watch
func TestWatch(t *testing.T) {
r := New([]string{"127.0.0.1:2181"}, WithRootPath("/gogf"))
ctx := gctx.New()
svc := &gsvc.LocalService{
Name: "goframe-provider-4-tcp",
Version: "test",
Metadata: map[string]interface{}{"app": "goframe", gsvc.MDProtocol: "tcp"},
Endpoints: gsvc.NewEndpoints("127.0.0.1:9000"),
}
t.Log("watch")
watch, err := r.Watch(context.Background(), svc.GetPrefix())
if err != nil {
t.Fatal(err)
}
s1, err := r.Register(context.Background(), svc)
if err != nil {
t.Fatal(err)
}
// watch svc
// svc register, AddEvent
next, err := watch.Proceed()
if err != nil {
t.Fatal(err)
}
for _, instance := range next {
// it will output one instance
g.Log().Info(ctx, "Register Proceed service: ", instance)
}
err = r.Deregister(context.Background(), s1)
if err != nil {
t.Fatal(err)
}
// svc deregister, DeleteEvent
next, err = watch.Proceed()
if err != nil {
t.Fatal(err)
}
for _, instance := range next {
// it will output nothing
g.Log().Info(ctx, "Deregister Proceed service: ", instance)
}
err = watch.Close()
if err != nil {
t.Fatal(err)
}
_, err = watch.Proceed()
if err == nil {
// if nil, stop failed
t.Fatal()
}
}

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,10 +266,49 @@ 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.
func (m *Model) Count(where ...interface{}) (int, error) {
func (m *Model) Count(where ...interface{}) (int64, error) {
var ctx = m.GetCtx()
if len(where) > 0 {
return m.Where(where[0], where[1:]...).Count()
@ -394,7 +324,7 @@ func (m *Model) Count(where ...interface{}) (int, error) {
if internalData := m.db.GetCore().GetInternalCtxDataFromCtx(ctx); internalData != nil {
record := all[0]
if v, ok := record[internalData.FirstResultColumn]; ok {
return v.Int(), nil
return v.Int64(), nil
}
}
return 0, gerror.NewCode(
@ -406,7 +336,7 @@ func (m *Model) Count(where ...interface{}) (int, error) {
}
// CountColumn does "SELECT COUNT(x) FROM ..." statement for the model.
func (m *Model) CountColumn(column string) (int, error) {
func (m *Model) CountColumn(column string) (int64, error) {
if len(column) == 0 {
return 0, nil
}
@ -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

@ -86,7 +86,7 @@ func (m *Model) getSoftFieldNameDeleted(table ...string) (field string) {
tableName = m.tablesInit
}
config := m.db.GetConfig()
if config.UpdatedAt != "" {
if config.DeletedAt != "" {
return m.getSoftFieldName(tableName, []string{config.DeletedAt})
}
return m.getSoftFieldName(tableName, deletedFiledNames)

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

@ -0,0 +1,92 @@
package gdebug_test
import (
"github.com/gogf/gf/v2/debug/gdebug"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"testing"
)
func Test_CallerPackage(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gdebug.CallerPackage(), "github.com/gogf/gf/v2/test/gtest")
})
}
func Test_CallerFunction(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gdebug.CallerFunction(), "C")
})
}
func Test_CallerFilePath(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gstr.Contains(gdebug.CallerFilePath(), "gtest_util.go"), true)
})
}
func Test_CallerDirectory(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gstr.Contains(gdebug.CallerDirectory(), "gtest"), true)
})
}
func Test_CallerFileLine(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gstr.Contains(gdebug.CallerFileLine(), "gtest_util.go:36"), true)
})
}
func Test_CallerFileLineShort(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gstr.Contains(gdebug.CallerFileLineShort(), "gtest_util.go:36"), true)
})
}
func Test_FuncPath(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gdebug.FuncPath(Test_FuncPath), "github.com/gogf/gf/v2/debug/gdebug_test.Test_FuncPath")
})
}
func Test_FuncName(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gdebug.FuncName(Test_FuncName), "gdebug_test.Test_FuncName")
})
}
func Test_PrintStack(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
gdebug.PrintStack()
})
}
func Test_GoroutineId(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertGT(gdebug.GoroutineId(), 0)
})
}
func Test_Stack(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gstr.Contains(gdebug.Stack(), "gtest_util.go:36"), true)
})
}
func Test_StackWithFilter(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gstr.Contains(gdebug.StackWithFilter([]string{"github.com"}), "gtest_util.go:36"), true)
})
}
func Test_BinVersion(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertGT(len(gdebug.BinVersion()), 0)
})
}
func Test_BinVersionMd5(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertGT(len(gdebug.BinVersionMd5()), 0)
})
}

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

@ -13,6 +13,13 @@ import (
"github.com/gogf/gf/v2/test/gtest"
)
func Test_Case(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gcode.CodeNil.String(), "-1")
t.Assert(gcode.CodeInternalError.String(), "50:Internal Error")
})
}
func Test_Nil(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
c := gcode.New(1, "custom error", "detailed description")
@ -21,3 +28,11 @@ func Test_Nil(t *testing.T) {
t.Assert(c.Detail(), "detailed description")
})
}
func Test_WithCode(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
c := gcode.WithCode(gcode.CodeInternalError, "CodeInternalError")
t.Assert(c.Code(), gcode.CodeInternalError.Code())
t.Assert(c.Detail(), "CodeInternalError")
})
}

View File

@ -95,10 +95,14 @@ func Test_Wrapf(t *testing.T) {
t.AssertNE(err, nil)
t.Assert(err.Error(), "1")
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.Wrapf(nil, ""), nil)
})
}
func Test_WrapSkip(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.WrapSkip(1, nil, "2"), nil)
err := errors.New("1")
err = gerror.WrapSkip(1, err, "2")
err = gerror.WrapSkip(1, err, "3")
@ -122,6 +126,7 @@ func Test_WrapSkip(t *testing.T) {
func Test_WrapSkipf(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.WrapSkipf(1, nil, "2"), nil)
err := errors.New("1")
err = gerror.WrapSkipf(1, err, "2")
err = gerror.WrapSkipf(1, err, "3")
@ -145,6 +150,7 @@ func Test_WrapSkipf(t *testing.T) {
func Test_Cause(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.Cause(nil), nil)
err := errors.New("1")
t.Assert(gerror.Cause(err), err)
})
@ -167,6 +173,17 @@ func Test_Cause(t *testing.T) {
err = gerror.Wrap(err, "3")
t.Assert(gerror.Cause(err), "1")
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.Stack(nil), "")
err := errors.New("1")
t.Assert(gerror.Stack(err), err)
})
gtest.C(t, func(t *gtest.T) {
var e *gerror.Error = nil
t.Assert(e.Cause(), nil)
})
}
func Test_Format(t *testing.T) {
@ -229,16 +246,22 @@ func Test_Stack(t *testing.T) {
func Test_Current(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.Current(nil), nil)
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.Wrap(err, "3")
t.Assert(err.Error(), "3: 2: 1")
t.Assert(gerror.Current(err).Error(), "3")
})
gtest.C(t, func(t *gtest.T) {
var e *gerror.Error = nil
t.Assert(e.Current(), nil)
})
}
func Test_Unwrap(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.Unwrap(nil), nil)
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.Wrap(err, "3")
@ -253,6 +276,10 @@ func Test_Unwrap(t *testing.T) {
err = gerror.Unwrap(err)
t.AssertNil(err)
})
gtest.C(t, func(t *gtest.T) {
var e *gerror.Error = nil
t.Assert(e.Unwrap(), nil)
})
}
func Test_Code(t *testing.T) {
@ -282,6 +309,7 @@ func Test_Code(t *testing.T) {
t.Assert(err.Error(), "123")
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.WrapCode(gcode.New(1, "", nil), nil, "3"), nil)
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.WrapCode(gcode.New(1, "", nil), err, "3")
@ -289,6 +317,7 @@ func Test_Code(t *testing.T) {
t.Assert(err.Error(), "3: 2: 1")
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.WrapCodef(gcode.New(1, "", nil), nil, "%s", "3"), nil)
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.WrapCodef(gcode.New(1, "", nil), err, "%s", "3")
@ -296,6 +325,7 @@ func Test_Code(t *testing.T) {
t.Assert(err.Error(), "3: 2: 1")
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.WrapCodeSkip(gcode.New(1, "", nil), 100, nil, "3"), nil)
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.WrapCodeSkip(gcode.New(1, "", nil), 100, err, "3")
@ -303,6 +333,7 @@ func Test_Code(t *testing.T) {
t.Assert(err.Error(), "3: 2: 1")
})
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.WrapCodeSkipf(gcode.New(1, "", nil), 100, nil, "%s", "3"), nil)
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.WrapCodeSkipf(gcode.New(1, "", nil), 100, err, "%s", "3")
@ -311,6 +342,20 @@ func Test_Code(t *testing.T) {
})
}
func TestError_Error(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var e *gerror.Error = nil
t.Assert(e.Error(), nil)
})
}
func TestError_Code(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var e *gerror.Error = nil
t.Assert(e.Code(), gcode.CodeNil)
})
}
func Test_SetCode(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
err := gerror.New("123")
@ -321,6 +366,10 @@ func Test_SetCode(t *testing.T) {
t.Assert(gerror.Code(err), gcode.CodeValidationFailed)
t.Assert(err.Error(), "123")
})
gtest.C(t, func(t *gtest.T) {
var err *gerror.Error = nil
err.SetCode(gcode.CodeValidationFailed)
})
}
func Test_Json(t *testing.T) {
@ -353,6 +402,10 @@ func Test_Equal(t *testing.T) {
t.Assert(gerror.Equal(err3, err4), false)
t.Assert(gerror.Equal(err1, err4), false)
})
gtest.C(t, func(t *gtest.T) {
var e = new(gerror.Error)
t.Assert(e.Equal(e), true)
})
}
func Test_Is(t *testing.T) {
@ -375,6 +428,7 @@ func Test_HashError(t *testing.T) {
func Test_HashCode(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(gerror.HasCode(nil, gcode.CodeNotAuthorized), false)
err1 := errors.New("1")
err2 := gerror.WrapCode(gcode.CodeNotAuthorized, err1, "2")
err3 := gerror.Wrap(err2, "3")
@ -385,3 +439,14 @@ func Test_HashCode(t *testing.T) {
t.Assert(gerror.HasCode(err4, gcode.CodeNotAuthorized), true)
})
}
func Test_NewOption(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNE(gerror.NewOption(gerror.Option{
Error: errors.New("NewOptionError"),
Stack: true,
Text: "Text",
Code: gcode.CodeNotAuthorized,
}), gerror.New("NewOptionError"))
})
}

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()
}

102
frame/g/g_z_unit_test.go Normal file
View File

@ -0,0 +1,102 @@
package g_test
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gutil"
"os"
"testing"
)
var (
ctx = context.TODO()
)
func Test_NewVar(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(g.NewVar(1).Int(), 1)
t.Assert(g.NewVar(1, true).Int(), 1)
})
}
func Test_Dump(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.Dump("GoFrame")
})
}
func Test_DumpTo(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.DumpTo(os.Stdout, "GoFrame", gutil.DumpOption{})
})
}
func Test_DumpWithType(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.DumpWithType("GoFrame", 123)
})
}
func Test_DumpWithOption(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.DumpWithOption("GoFrame", gutil.DumpOption{})
})
}
func Test_Try(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.Try(ctx, func(ctx context.Context) {
g.Dump("GoFrame")
})
})
}
func Test_TryCatch(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.TryCatch(ctx, func(ctx context.Context) {
g.Dump("GoFrame")
}, func(ctx context.Context, exception error) {
g.Dump(exception)
})
})
}
func Test_IsNil(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(g.IsNil(nil), true)
t.Assert(g.IsNil(0), false)
t.Assert(g.IsNil("GoFrame"), false)
})
}
func Test_IsEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(g.IsEmpty(nil), true)
t.Assert(g.IsEmpty(0), true)
t.Assert(g.IsEmpty("GoFrame"), false)
})
}
func Test_SetDebug(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
g.SetDebug(true)
})
}
func Test_Object(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNE(g.Client(), nil)
t.AssertNE(g.Server(), nil)
t.AssertNE(g.TCPServer(), nil)
t.AssertNE(g.UDPServer(), nil)
t.AssertNE(g.View(), nil)
t.AssertNE(g.Config(), nil)
t.AssertNE(g.Cfg(), nil)
t.AssertNE(g.Resource(), nil)
t.AssertNE(g.I18n(), nil)
t.AssertNE(g.Res(), nil)
t.AssertNE(g.Log(), nil)
t.AssertNE(g.Validator(), nil)
})
}

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

@ -427,14 +427,17 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) {
}
}
// Processing expired keys from LRU.
if c.cap > 0 && c.lruGetList.Len() > 0 {
for {
if v := c.lruGetList.PopFront(); v != nil {
c.lru.Push(v)
} else {
break
if c.cap > 0 {
if c.lruGetList.Len() > 0 {
for {
if v := c.lruGetList.PopFront(); v != nil {
c.lru.Push(v)
} else {
break
}
}
}
c.lru.SyncAndClear(ctx)
}
// ========================
// Data Cleaning up.

View File

@ -8,7 +8,6 @@ package gcache
import (
"context"
"time"
"github.com/gogf/gf/v2/container/glist"
"github.com/gogf/gf/v2/container/gmap"
@ -35,7 +34,6 @@ func newMemCacheLru(cache *AdapterMemory) *adapterMemoryLru {
rawList: glist.New(true),
closed: gtype.NewBool(),
}
gtimer.AddSingleton(context.Background(), time.Second, lru.SyncAndClear)
return lru
}

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

@ -50,34 +50,35 @@ func CopyFile(src, dst string) (err error) {
if src == dst {
return nil
}
in, err := Open(src)
var inFile *os.File
inFile, err = Open(src)
if err != nil {
return
}
defer func() {
if e := in.Close(); e != nil {
if e := inFile.Close(); e != nil {
err = gerror.Wrapf(e, `file close failed for "%s"`, src)
}
}()
out, err := Create(dst)
var outFile *os.File
outFile, err = Create(dst)
if err != nil {
return
}
defer func() {
if e := out.Close(); e != nil {
if e := outFile.Close(); e != nil {
err = gerror.Wrapf(e, `file close failed for "%s"`, dst)
}
}()
if _, err = io.Copy(out, in); err != nil {
if _, err = io.Copy(outFile, inFile); err != nil {
err = gerror.Wrapf(err, `io.Copy failed from "%s" to "%s"`, src, dst)
return
}
if err = out.Sync(); err != nil {
if err = outFile.Sync(); err != nil {
err = gerror.Wrapf(err, `file sync failed for file "%s"`, dst)
return
}
err = Chmod(dst, DefaultPermCopy)
if err != nil {
if err = Chmod(dst, DefaultPermCopy); err != nil {
return
}
return

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,6 +9,7 @@ package glog_test
import (
"bytes"
"context"
"os"
"sync"
"testing"
@ -20,6 +21,386 @@ import (
"github.com/gogf/gf/v2/text/gstr"
)
func TestCase(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.AssertNE(glog.Instance(), nil)
})
}
func TestDefaultLogger(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.AssertNE(defaultLog, nil)
log := glog.New()
glog.SetDefaultLogger(log)
t.AssertEQ(glog.DefaultLogger(), defaultLog)
t.AssertEQ(glog.Expose(), defaultLog)
})
}
func TestAPI(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
glog.Print(ctx, "Print")
glog.Printf(ctx, "%s", "Printf")
glog.Info(ctx, "Info")
glog.Infof(ctx, "%s", "Infof")
glog.Debug(ctx, "Debug")
glog.Debugf(ctx, "%s", "Debugf")
glog.Notice(ctx, "Notice")
glog.Noticef(ctx, "%s", "Noticef")
glog.Warning(ctx, "Warning")
glog.Warningf(ctx, "%s", "Warningf")
glog.Error(ctx, "Error")
glog.Errorf(ctx, "%s", "Errorf")
glog.Critical(ctx, "Critical")
glog.Criticalf(ctx, "%s", "Criticalf")
})
}
func TestChaining(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.AssertNE(glog.Cat("module"), nil)
t.AssertNE(glog.File("test.log"), nil)
t.AssertNE(glog.Level(glog.LEVEL_ALL), nil)
t.AssertNE(glog.LevelStr("all"), nil)
t.AssertNE(glog.Skip(1), nil)
t.AssertNE(glog.Stack(false), nil)
t.AssertNE(glog.StackWithFilter("none"), nil)
t.AssertNE(glog.Stdout(false), nil)
t.AssertNE(glog.Header(false), nil)
t.AssertNE(glog.Line(false), nil)
t.AssertNE(glog.Async(false), nil)
})
}
func Test_SetFile(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetFile("test.log")
})
}
func Test_SetLevel(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetLevel(glog.LEVEL_ALL)
t.Assert(glog.GetLevel()&glog.LEVEL_ALL, glog.LEVEL_ALL)
})
}
func Test_SetAsync(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetAsync(false)
})
}
func Test_SetStdoutPrint(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetStdoutPrint(false)
})
}
func Test_SetHeaderPrint(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetHeaderPrint(false)
})
}
func Test_SetPrefix(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetPrefix("log_prefix")
})
}
func Test_SetConfigWithMap(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.Assert(glog.SetConfigWithMap(map[string]interface{}{
"level": "all",
}), nil)
})
}
func Test_SetPath(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.Assert(glog.SetPath("/var/log"), nil)
t.Assert(glog.GetPath(), "/var/log")
})
}
func Test_SetWriter(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetWriter(os.Stdout)
t.Assert(glog.GetWriter(), os.Stdout)
})
}
func Test_SetFlags(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetFlags(glog.F_ASYNC)
t.Assert(glog.GetFlags(), glog.F_ASYNC)
})
}
func Test_SetCtxKeys(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetCtxKeys("SpanId", "TraceId")
t.Assert(glog.GetCtxKeys(), []string{"SpanId", "TraceId"})
})
}
func Test_PrintStack(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.PrintStack(ctx, 1)
})
}
func Test_SetStack(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetStack(true)
t.Assert(glog.GetStack(1), "")
})
}
func Test_SetLevelStr(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.Assert(glog.SetLevelStr("all"), nil)
})
gtest.C(t, func(t *gtest.T) {
l := glog.New()
t.AssertNE(l.SetLevelStr("test"), nil)
})
}
func Test_SetLevelPrefix(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetLevelPrefix(glog.LEVEL_ALL, "LevelPrefix")
t.Assert(glog.GetLevelPrefix(glog.LEVEL_ALL), "LevelPrefix")
})
}
func Test_SetLevelPrefixes(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetLevelPrefixes(map[int]string{
glog.LEVEL_ALL: "ALL_Prefix",
})
})
}
func Test_SetHandlers(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetHandlers(func(ctx context.Context, in *glog.HandlerInput) {
})
})
}
func Test_SetWriterColorEnable(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
glog.SetWriterColorEnable(true)
})
}
func Test_Instance(t *testing.T) {
defaultLog := glog.DefaultLogger().Clone()
defer glog.SetDefaultLogger(defaultLog)
gtest.C(t, func(t *gtest.T) {
t.AssertNE(glog.Instance("gf"), nil)
})
}
func Test_GetConfig(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
config := glog.DefaultLogger().GetConfig()
t.Assert(config.Path, "")
t.Assert(config.StdoutPrint, true)
})
}
func Test_Write(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
len, err := l.Write([]byte("GoFrame"))
t.AssertNil(err)
t.Assert(len, 7)
})
}
func Test_Chaining_To(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.DefaultLogger().Clone()
logTo := l.To(os.Stdout)
t.AssertNE(logTo, nil)
})
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logTo := l.To(os.Stdout)
t.AssertNE(logTo, nil)
})
}
func Test_Chaining_Path(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.DefaultLogger().Clone()
logPath := l.Path("./")
t.AssertNE(logPath, nil)
})
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logPath := l.Path("./")
t.AssertNE(logPath, nil)
})
}
func Test_Chaining_Cat(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logCat := l.Cat(".gf")
t.AssertNE(logCat, nil)
})
}
func Test_Chaining_Level(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logLevel := l.Level(glog.LEVEL_ALL)
t.AssertNE(logLevel, nil)
})
}
func Test_Chaining_LevelStr(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logLevelStr := l.LevelStr("all")
t.AssertNE(logLevelStr, nil)
})
}
func Test_Chaining_Skip(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logSkip := l.Skip(1)
t.AssertNE(logSkip, nil)
})
}
func Test_Chaining_Stack(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logStack := l.Stack(true)
t.AssertNE(logStack, nil)
})
}
func Test_Chaining_StackWithFilter(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logStackWithFilter := l.StackWithFilter("gtest")
t.AssertNE(logStackWithFilter, nil)
})
}
func Test_Chaining_Stdout(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logStdout := l.Stdout(true)
t.AssertNE(logStdout, nil)
})
}
func Test_Chaining_Header(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logHeader := l.Header(true)
t.AssertNE(logHeader, nil)
})
}
func Test_Chaining_Line(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logLine := l.Line(true)
t.AssertNE(logLine, nil)
})
}
func Test_Chaining_Async(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
logAsync := l.Async(true)
t.AssertNE(logAsync, nil)
})
}
func Test_Config_SetDebug(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
l.SetDebug(false)
})
}
func Test_Config_AppendCtxKeys(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
l.AppendCtxKeys("Trace-Id", "Span-Id", "Test")
l.AppendCtxKeys("Trace-Id-New", "Span-Id-New", "Test")
})
}
func Test_Config_SetPath(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
t.AssertNE(l.SetPath(""), nil)
})
}
func Test_Config_SetStdoutColorDisabled(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := glog.New()
l.SetStdoutColorDisabled(false)
})
}
func Test_Ctx(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
w := bytes.NewBuffer(nil)
@ -42,8 +423,13 @@ func Test_Ctx_Config(t *testing.T) {
m := map[string]interface{}{
"CtxKeys": g.SliceStr{"Trace-Id", "Span-Id", "Test"},
}
var nilMap map[string]interface{}
err := l.SetConfigWithMap(m)
t.AssertNil(err)
err = l.SetConfigWithMap(nilMap)
t.AssertNE(err, nil)
ctx := context.WithValue(context.Background(), "Trace-Id", "1234567890")
ctx = context.WithValue(ctx, "Span-Id", "abcdefg")

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()
}
}
}

Some files were not shown because too many files have changed in this diff Show More