Compare commits

..

4 Commits

Author SHA1 Message Date
bb3ca6d414 improve clickhouse driver 2022-04-19 14:21:03 +08:00
674eada9ed improve clickhouse driver 2022-04-19 14:20:00 +08:00
310baaf67d improve clickhouse driver 2022-04-19 14:18:25 +08:00
c9971b21ec improve clickhouse driver 2022-04-19 14:15:53 +08:00
495 changed files with 7273 additions and 30262 deletions

View File

@ -52,7 +52,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: GoFrame Release ${{ github.ref }}
release_name: GoFrame CLI Release ${{ github.ref }}
draft: false
prerelease: false

View File

@ -1,95 +0,0 @@
version: "2"
services:
redis-master:
container_name: redis-master
image: "loads/redis:7.0"
environment:
- REDIS_REPLICATION_MODE=master
- REDIS_PASSWORD=111111
ports:
- 6380:6379
redis-slave1:
container_name: redis-slave1
image: "loads/redis:7.0"
environment:
- REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PASSWORD=111111
- REDIS_PASSWORD=111111
ports:
- 6381:6379
depends_on:
- redis-master
links:
- redis-master
redis-slave2:
container_name: redis-slave2
image: "loads/redis:7.0"
environment:
- REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PASSWORD=111111
- REDIS_PASSWORD=111111
ports:
- 6382:6379
depends_on:
- redis-master
links:
- redis-master
redis-sentinel-1:
container_name: redis-sentinel-1
image: "loads/redis-sentinel:7.0"
environment:
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PORT_NUMBER=6379
- REDIS_MASTER_PASSWORD=111111
depends_on:
- redis-master
- redis-slave1
- redis-slave2
ports:
- 26379:26379
links:
- redis-master
- redis-slave1
- redis-slave2
redis-sentinel-2:
container_name: redis-sentinel-2
image: "loads/redis-sentinel:7.0"
environment:
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PORT_NUMBER=6379
- REDIS_MASTER_PASSWORD=111111
depends_on:
- redis-master
- redis-slave1
- redis-slave2
links:
- redis-master
- redis-slave1
- redis-slave2
ports:
- 26380:26379
redis-sentinel-3:
container_name: redis-sentinel-3
image: "loads/redis-sentinel:7.0"
environment:
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PORT_NUMBER=6379
- REDIS_MASTER_PASSWORD=111111
depends_on:
- redis-master
- redis-slave1
- redis-slave2
ports:
- 26381:26379
links:
- redis-master
- redis-slave1
- redis-slave2

View File

@ -6,38 +6,25 @@ on:
branches:
- master
- develop
- personal/**
- feature/**
- enhance/**
- fix/**
pull_request:
branches:
- master
- develop
- personal/**
- feature/**
- enhance/**
- fix/**
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true
env:
TZ: "Asia/Shanghai"
GF_DEBUG: 0
jobs:
code-test:
runs-on: ubuntu-latest
# Service containers to run with `code-test`
services:
# Redis backend server.
redis:
image : loads/redis:latest
image : redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
@ -47,9 +34,8 @@ jobs:
# Maps tcp port 6379 on service container to the host
- 6379:6379
# MySQL backend server.
mysql:
image: loads/mysql:5.7
image: mysql:5.7
env:
MYSQL_DATABASE : test
MYSQL_ROOT_PASSWORD: 12345678
@ -57,12 +43,11 @@ jobs:
# Maps tcp port 3306 on service container to the host
- 3306:3306
# PostgreSQL backend server.
postgres:
image: loads/postgres:13
image: postgres:13
env:
POSTGRES_PASSWORD: 12345678
POSTGRES_USER: postgres
POSTGRES_USER: root
POSTGRES_DB: test
TZ: Asia/Shanghai
ports:
@ -74,9 +59,8 @@ jobs:
--health-timeout 5s
--health-retries 5
# MSSQL backend server.
mssql:
image: loads/mssqldocker:latest
image: mcmoe/mssqldocker:latest
env:
ACCEPT_EULA: Y
SA_PASSWORD: LoremIpsum86
@ -92,39 +76,22 @@ jobs:
--health-timeout 5s
--health-retries 10
# ClickHouse backend server.
clickhouse-server:
image: loads/clickhouse-server:latest
image: yandex/clickhouse-server
ports:
- 9000:9000
- 8123:8123
- 9001:9001
polaris:
image: polarismesh/polaris-server-standalone:latest
ports:
- 8090:8090
- 8091:8091
#oracle 11g server
oracle-server:
image: loads/oracle-xe-11g-r2:latest
env:
ORACLE_ALLOW_REMOTE: true
ORACLE_SID: XE
ORACLE_DB_USER_NAME: system
ORACLE_DB_PASSWORD: oracle
ports:
- 1521:1521
# strategy set
strategy:
matrix:
go-version: [ "1.15", "1.16", "1.17", "1.18" ]
goarch: [ "386", "amd64" ]
go: ["1.16", "1.17"]
steps:
- name: Setup Timezone
- name: Set Up Timezone
uses: szenius/set-timezone@v1.0
with:
timezoneLinux: "Asia/Shanghai"
@ -132,30 +99,10 @@ jobs:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Setup Golang ${{ matrix.go-version }}
- name: Set Up Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Setup Golang caches
uses: actions/cache@v3
with:
# In order:
# * Module download cache
# * Build cache (Linux)
# * Build cache (Mac)
# * Build cache (Windows)
path: |
~/go/pkg/mod
~/.cache/go-build
~/Library/Caches/go-build
~\AppData\Local\go-build
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ matrix.go-version }}-
- name: Start containers
run: docker-compose -f ".github/workflows/docker/docker-compose.yml" up -d --build
go-version: ${{ matrix.go }}
- name: Before Script
run: |
@ -164,33 +111,46 @@ jobs:
echo "gofmt check pass."
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
- name: Build & Test
- name: CLI Build & Test
run: |
GOARCH=${{ matrix.goarch }}
cd cmd/gf
go mod tidy
go build ./...
go test ./...
- name: Example Build & Test
run: |
cd example
go mod tidy
go build ./...
go test ./...
- name: Contrib Build & Test
run: |
cd contrib
for file in `find . -name go.mod`; do
dirpath=$(dirname $file)
if [ "oracle" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.17"; then
continue 1
fi
path=$(dirname $file)
# Ignore oracle database driver build&test.
if [ "oracle" = $(basename $path) ]; then
continue 1
fi
cd $dirpath
cd $path
go mod tidy
go build ./...
go test ./... -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
if grep -q "/gogf/gf/.*/v2" go.mod; then
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
fi
go test ./...
cd -
done
- name: Stop containers
run: docker-compose -f ".github/workflows/docker/docker-compose.yml" down
- name: Run i386 Arch Test
run: |
GOARCH=386 go test -v ./... || exit 1
- name: Run amd64 Arch Test
run: |
GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic
- name: Report Coverage
uses: codecov/codecov-action@v2
with:
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}
flags: go-${{ matrix.go }}

View File

@ -1,28 +0,0 @@
# 规则描述每天0点(GMT+8)执行一次将最近7天没有活跃且非BUG的ISSUE设置标签:inactive
name: Issue Check Inactive
on:
schedule:
- cron: "0 3 * * *"
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
permissions:
contents: read
jobs:
issue-check-inactive:
permissions:
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: check-inactive
uses: actions-cool/issues-helper@v3
with:
actions: 'check-inactive'
inactive-label: 'inactive'
inactive-day: 7
issue-state: open
exclude-labels: 'bug'

View File

@ -1,22 +0,0 @@
# 规则描述每天0点(GMT+8)执行一次将最近30天没有活跃且非BUG的ISSUE关闭
name: Issue Close Inactive
on:
schedule:
- cron: "0 3 * * *"
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- name: need close
uses: actions-cool/issues-helper@v3
with:
actions: "close-issues"
# token: ${{ secrets.GF_TOKEN }}
labels: 'inactive'
inactive-day: 30
exclude-labels: 'bug'

View File

@ -1,25 +0,0 @@
## 规则描述当issue被标记为help wanted 时,增加评论
name: Issue Labeled
on:
issues:
types: [labeled]
env: # 设置环境变量
TZ: Asia/Shanghai # 时区(设置时区可使页面中的`最近更新时间`使用时区时间)
jobs:
reply-labeled:
runs-on: ubuntu-latest
steps:
- name: contribution welcome
if: github.event.label.name == 'help wanted'
uses: actions-cool/issues-helper@v3
with:
actions: "create-comment, remove-labels"
# token: ${{ secrets.GF_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}. We like your proposal/feedback and would appreciate a contribution via a Pull Request by you or another community member. We thank you in advance for your contribution and are looking forward to reviewing it!
你好 @${{ github.event.issue.user.login }}。我们喜欢您的提案/反馈,并希望您或其他社区成员通过拉取请求做出贡献。我们提前感谢您的贡献,并期待对其进行审查。

View File

@ -1,29 +0,0 @@
# 规则描述在issue没有活跃且尚未被关闭期间若issue作者更新或评论该ISSUE则移除其inactive标签
name: Issue Remove Inactive
on:
issues:
types: [edited]
issue_comment:
types: [created, edited]
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
permissions:
contents: read
jobs:
issue-remove-inactive:
permissions:
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: remove inactive
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
issue-number: ${{ github.event.issue.number }}
labels: 'inactive'

View File

@ -1,29 +0,0 @@
# 规则描述将需要提供更多细节且暂未关闭的issue在issue作者评论后移除 need more details 标签
name: Issue Remove Need More Details
on:
issues:
types: [edited]
issue_comment:
types: [created, edited]
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
permissions:
contents: read
jobs:
issue-remove-need-more-details:
permissions:
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: remove need more details
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
issue-number: ${{ github.event.issue.number }}
labels: 'need more details'

5
.gitignore vendored
View File

@ -14,6 +14,5 @@ bin/
cbuild
**/.DS_Store
.test/
cmd/gf/main
cmd/gf/gf
go.work
main
gf

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
.PHONY: tidy
tidy:
$(eval files=$(shell find . -name go.mod))
@set -e; \
for file in ${files}; do \
goModPath=$$(dirname $$file); \
cd $$goModPath; \
go mod tidy; \
cd -; \
done

View File

@ -3,18 +3,17 @@ module github.com/gogf/gf/cmd/gf/v2
go 1.15
require (
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.1.0
github.com/gogf/gf/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.0.6
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.0.6
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.0.6
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.0.6
github.com/gogf/gf/v2 v2.0.6
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/tools v0.1.11
)
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,10 +1,7 @@
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 v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.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=
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=
@ -14,25 +11,19 @@ github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL
github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
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/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
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/glebarez/go-sqlite v1.17.3 h1:Rji9ROVSTTfjuWD6j5B+8DtkNvPILoUC3xRhkQzGxvk=
github.com/glebarez/go-sqlite v1.17.3/go.mod h1:Hg+PQuhUy98XCxWEJEaWob8x7lhJzhNYF1nZbUiRGIY=
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/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -48,32 +39,29 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
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.3/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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/longbridgeapp/sqlparser v0.3.1 h1:iWOZWGIFgQrJRgobLXUNJdvqGRpbVXkyKUKUA5CNJBE=
github.com/longbridgeapp/sqlparser v0.3.1/go.mod h1:GIHaUq8zvYyHLCLMJJykx1CdM6LHtkUih/QaJXySSx4=
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-oci8 v0.1.1 h1:aEUDxNAyDG0tv8CA3TArnDQNyc4EhnWlsfxRgDHABHM=
github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
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/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
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=
@ -81,52 +69,40 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
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 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
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/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/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=
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/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
go.opentelemetry.io/otel/sdk v1.0.0 h1:BNPMYUONPNbLneMttKSjQhOTlFLOD9U22HNG1KrIN2Y=
go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
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/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/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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -139,7 +115,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
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=
@ -148,29 +123,19 @@ 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 h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
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/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/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/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=
@ -198,29 +163,3 @@ 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=
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=
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o=
modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.17.3 h1:iE+coC5g17LtByDYDWKpR6m2Z9022YrSh3bumwOnIrI=
modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=

View File

@ -109,7 +109,7 @@ func init() {
type cBuildInput struct {
g.Meta `name:"build" config:"gfcli.build"`
File string `name:"FILE" arg:"true" brief:"building file path"`
File string `name:"FILE" arg:"true" brief:"building file path"`
Name string `short:"n" name:"name" brief:"output binary name"`
Version string `short:"v" name:"version" brief:"output binary version"`
Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"`
@ -206,14 +206,11 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
}
packCmd := fmt.Sprintf(`gf pack %s %s`, in.PackSrc, in.PackDst)
mlog.Print(packCmd)
gproc.MustShellRun(ctx, packCmd)
gproc.MustShellRun(packCmd)
}
// Injected information by building flags.
ldFlags := fmt.Sprintf(
`-X 'github.com/gogf/gf/v2/os/gbuild.builtInVarStr=%v'`,
c.getBuildInVarStr(ctx, in),
)
ldFlags := fmt.Sprintf(`-X 'github.com/gogf/gf/v2/os/gbuild.builtInVarStr=%v'`, c.getBuildInVarStr(in))
// start building
mlog.Print("start building...")
@ -264,7 +261,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
// It's not necessary printing the complete command string.
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
mlog.Print(cmdShow)
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
if result, err := gproc.ShellExec(cmd); err != nil {
mlog.Printf(
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
system, arch, gstr.Trim(result),
@ -290,12 +287,12 @@ buildDone:
// getBuildInVarMapJson retrieves and returns the custom build-in variables in configuration
// file as json.
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
func (c cBuild) getBuildInVarStr(in cBuildInput) string {
buildInVarMap := in.VarMap
if buildInVarMap == nil {
buildInVarMap = make(g.Map)
}
buildInVarMap["builtGit"] = c.getGitCommit(ctx)
buildInVarMap["builtGit"] = c.getGitCommit()
buildInVarMap["builtTime"] = gtime.Now().String()
b, err := json.Marshal(buildInVarMap)
if err != nil {
@ -305,13 +302,13 @@ func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
}
// getGitCommit retrieves and returns the latest git commit hash string if present.
func (c cBuild) getGitCommit(ctx context.Context) string {
func (c cBuild) getGitCommit() string {
if gproc.SearchBinary("git") == "" {
return ""
}
var (
cmd = `git log -1 --format="%cd %H" --date=format:"%Y-%m-%d %H:%M:%S"`
s, _ = gproc.ShellExec(ctx, cmd)
s, _ = gproc.ShellExec(cmd)
)
mlog.Debug(cmd)
if s != "" {

View File

@ -3,13 +3,11 @@ package cmd
import (
"context"
"fmt"
"runtime"
"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"
)
@ -39,43 +37,40 @@ It runs "gf build" firstly to compile the project to binary file.
It then runs "docker build" command automatically to generate the docker image.
You should have docker installed, and there must be a Dockerfile in the root of the project.
`
cDockerMainBrief = `main file path for "gf build", it's "main.go" in default. empty string for no binary build`
cDockerBuildBrief = `binary build options before docker image build, it's "-a amd64 -s linux" in default`
cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default`
cDockerShellBrief = `path of the shell file which is executed before docker build`
cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed`
cDockerTagNameBrief = `tag name for this docker, pattern like "image:tag". this option is required with TagPrefixes`
cDockerTagPrefixesBrief = `tag prefixes for this docker, which are used for docker push. this option is required with TagName`
cDockerExtraBrief = `extra build options passed to "docker image"`
cDockerMainBrief = `main file path for "gf build", it's "main.go" in default. empty string for no binary build`
cDockerBuildBrief = `binary build options before docker image build, it's "-a amd64 -s linux" in default`
cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default`
cDockerShellBrief = `path of the shell file which is executed before docker build`
cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed`
cDockerTagBrief = `tag name for this docker, which is usually used for docker push`
cDockerExtraBrief = `extra build options passed to "docker image"`
)
func init() {
gtag.Sets(g.MapStrStr{
`cDockerUsage`: cDockerUsage,
`cDockerBrief`: cDockerBrief,
`cDockerEg`: cDockerEg,
`cDockerDc`: cDockerDc,
`cDockerMainBrief`: cDockerMainBrief,
`cDockerFileBrief`: cDockerFileBrief,
`cDockerShellBrief`: cDockerShellBrief,
`cDockerBuildBrief`: cDockerBuildBrief,
`cDockerPushBrief`: cDockerPushBrief,
`cDockerTagNameBrief`: cDockerTagNameBrief,
`cDockerTagPrefixesBrief`: cDockerTagPrefixesBrief,
`cDockerExtraBrief`: cDockerExtraBrief,
`cDockerUsage`: cDockerUsage,
`cDockerBrief`: cDockerBrief,
`cDockerEg`: cDockerEg,
`cDockerDc`: cDockerDc,
`cDockerMainBrief`: cDockerMainBrief,
`cDockerFileBrief`: cDockerFileBrief,
`cDockerShellBrief`: cDockerShellBrief,
`cDockerBuildBrief`: cDockerBuildBrief,
`cDockerPushBrief`: cDockerPushBrief,
`cDockerTagBrief`: cDockerTagBrief,
`cDockerExtraBrief`: cDockerExtraBrief,
})
}
type cDockerInput struct {
g.Meta `name:"docker" config:"gfcli.docker"`
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
TagName string `name:"tagName" short:"tn" brief:"{cDockerTagNameBrief}" v:"required-with:TagPrefixes"`
TagPrefixes []string `name:"tagPrefixes" short:"tp" brief:"{cDockerTagPrefixesBrief}" v:"required-with:TagName"`
Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"`
Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"`
g.Meta `name:"docker" config:"gfcli.docker"`
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
Tag string `name:"tag" short:"t" brief:"{cDockerTagBrief}"`
Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"`
Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"`
}
type cDockerOutput struct{}
@ -88,74 +83,34 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
// Binary build.
in.Build += " --exit"
if in.Main != "" {
if err = gproc.ShellRun(ctx, fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
if err = gproc.ShellRun(fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
return
}
}
// Shell executing.
if in.Shell != "" && gfile.Exists(in.Shell) {
if err = c.exeDockerShell(ctx, in.Shell); err != nil {
if gfile.Exists(in.Shell) {
if err = gproc.ShellRun(gfile.GetContents(in.Shell)); err != nil {
return
}
}
// Docker build.
var (
dockerBuildOptions string
dockerTags []string
dockerTagBase string
)
if len(in.TagPrefixes) > 0 {
for _, tagPrefix := range in.TagPrefixes {
tagPrefix = gstr.TrimRight(tagPrefix, "/")
dockerTags = append(dockerTags, fmt.Sprintf(`%s/%s`, tagPrefix, in.TagName))
}
dockerBuildOptions := ""
if in.Tag != "" {
dockerBuildOptions = fmt.Sprintf(`-t %s`, in.Tag)
}
if len(dockerTags) == 0 {
dockerTags = []string{""}
if in.Extra != "" {
dockerBuildOptions = fmt.Sprintf(`%s %s`, dockerBuildOptions, in.Extra)
}
for i, dockerTag := range dockerTags {
if i > 0 {
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker tag %s %s`, dockerTagBase, dockerTag))
if err != nil {
return
}
continue
}
dockerTagBase = dockerTag
dockerBuildOptions = ""
if dockerTag != "" {
dockerBuildOptions = fmt.Sprintf(`-t %s`, dockerTag)
}
if in.Extra != "" {
dockerBuildOptions = fmt.Sprintf(`%s %s`, dockerBuildOptions, in.Extra)
}
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker build -f %s . %s`, in.File, dockerBuildOptions))
if err != nil {
return
}
}
// Docker push.
if !in.Push {
if err = gproc.ShellRun(fmt.Sprintf(`docker build -f %s . %s`, in.File, dockerBuildOptions)); err != nil {
return
}
for _, dockerTag := range dockerTags {
if dockerTag == "" {
continue
}
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker push %s`, dockerTag))
if err != nil {
return
}
// Docker push.
if in.Tag == "" || !in.Push {
return
}
if err = gproc.ShellRun(fmt.Sprintf(`docker push %s`, in.Tag)); err != nil {
return
}
return
}
func (c cDocker) exeDockerShell(ctx context.Context, shellFilePath string) error {
if gfile.ExtName(shellFilePath) == "sh" && runtime.GOOS == "windows" {
mlog.Debugf(`ignore shell file "%s", as it cannot be run on windows system`, shellFilePath)
return nil
}
return gproc.ShellRun(ctx, gfile.GetContents(shellFilePath))
}

View File

@ -26,7 +26,7 @@ type cEnvInput struct {
type cEnvOutput struct{}
func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err error) {
result, err := gproc.ShellExec(ctx, "go env")
result, err := gproc.ShellExec("go env")
if err != nil {
mlog.Fatal(err)
}

View File

@ -11,10 +11,6 @@ var (
type cGen struct {
g.Meta `name:"gen" brief:"{cGenBrief}" dc:"{cGenDc}"`
cGenDao
cGenPb
cGenPbEntity
cGenService
}
const (

View File

@ -1,15 +1,801 @@
package cmd
import (
"bytes"
"context"
"fmt"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"github.com/olekukonko/tablewriter"
_ "github.com/gogf/gf/contrib/drivers/mssql/v2"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
//_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
)
const (
defaultDaoPath = `service/internal/dao`
defaultDoPath = `service/internal/do`
defaultEntityPath = `model/entity`
cGenDaoConfig = `gfcli.gen.dao`
cGenDaoUsage = `gf gen dao [OPTION]`
cGenDaoBrief = `automatically generate go files for dao/do/entity`
cGenDaoEg = `
gf gen dao
gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
gf gen dao -p ./model -g user-center -t user,user_detail,user_login
gf gen dao -r user_
`
cGenDaoAd = `
CONFIGURATION SUPPORT
Options are also supported by configuration file.
It's suggested using configuration file instead of command line arguments making producing.
The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml):
gfcli:
gen:
dao:
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
tables: "order,products"
jsonCase: "CamelLower"
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
path: "./my-app"
prefix: "primary_"
tables: "user, userDetail"
`
cGenDaoBriefPath = `directory path for generated files`
cGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
cGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
cGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
cGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
cGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
cGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
cGenDaoBriefWithTime = `add created time for auto produced go files`
cGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
cGenDaoBriefImportPrefix = `custom import prefix for generated go files`
cGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
cGenDaoBriefModelFile = `custom file name for storing generated model content`
cGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
cGenDaoBriefDescriptionTag = `add comment to description tag for each field`
cGenDaoBriefNoJsonTag = `no json tag will be added for each field`
cGenDaoBriefNoModelComment = `no model comment will be added for each field`
cGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
cGenDaoBriefJsonCase = `
generated json tag case for model struct, cases are as follows:
| Case | Example |
|---------------- |--------------------|
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString | default
| Snake | any_kind_of_string |
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
tplVarTableName = `{TplTableName}`
tplVarTableNameCamelCase = `{TplTableNameCamelCase}`
tplVarTableNameCamelLowerCase = `{TplTableNameCamelLowerCase}`
tplVarPackageImports = `{TplPackageImports}`
tplVarImportPrefix = `{TplImportPrefix}`
tplVarStructDefine = `{TplStructDefine}`
tplVarColumnDefine = `{TplColumnDefine}`
tplVarColumnNames = `{TplColumnNames}`
tplVarGroupName = `{TplGroupName}`
tplVarDatetimeStr = `{TplDatetimeStr}`
)
var (
createdAt = gtime.Now()
)
func init() {
gtag.Sets(g.MapStrStr{
`cGenDaoConfig`: cGenDaoConfig,
`cGenDaoUsage`: cGenDaoUsage,
`cGenDaoBrief`: cGenDaoBrief,
`cGenDaoEg`: cGenDaoEg,
`cGenDaoAd`: cGenDaoAd,
`cGenDaoBriefPath`: cGenDaoBriefPath,
`cGenDaoBriefLink`: cGenDaoBriefLink,
`cGenDaoBriefTables`: cGenDaoBriefTables,
`cGenDaoBriefTablesEx`: cGenDaoBriefTablesEx,
`cGenDaoBriefPrefix`: cGenDaoBriefPrefix,
`cGenDaoBriefRemovePrefix`: cGenDaoBriefRemovePrefix,
`cGenDaoBriefStdTime`: cGenDaoBriefStdTime,
`cGenDaoBriefWithTime`: cGenDaoBriefWithTime,
`cGenDaoBriefGJsonSupport`: cGenDaoBriefGJsonSupport,
`cGenDaoBriefImportPrefix`: cGenDaoBriefImportPrefix,
`cGenDaoBriefOverwriteDao`: cGenDaoBriefOverwriteDao,
`cGenDaoBriefModelFile`: cGenDaoBriefModelFile,
`cGenDaoBriefModelFileForDao`: cGenDaoBriefModelFileForDao,
`cGenDaoBriefDescriptionTag`: cGenDaoBriefDescriptionTag,
`cGenDaoBriefNoJsonTag`: cGenDaoBriefNoJsonTag,
`cGenDaoBriefNoModelComment`: cGenDaoBriefNoModelComment,
`cGenDaoBriefGroup`: cGenDaoBriefGroup,
`cGenDaoBriefJsonCase`: cGenDaoBriefJsonCase,
})
}
type (
cGenDao = gendao.CGenDao
cGenDaoInput struct {
g.Meta `name:"dao" config:"{cGenDaoConfig}" usage:"{cGenDaoUsage}" brief:"{cGenDaoBrief}" eg:"{cGenDaoEg}" ad:"{cGenDaoAd}"`
Path string `name:"path" short:"p" brief:"{cGenDaoBriefPath}" d:"internal"`
Link string `name:"link" short:"l" brief:"{cGenDaoBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{cGenDaoBriefTables}"`
TablesEx string `name:"tablesEx" short:"e" brief:"{cGenDaoBriefTablesEx}"`
Group string `name:"group" short:"g" brief:"{cGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{cGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{cGenDaoBriefRemovePrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{cGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{cGenDaoBriefImportPrefix}"`
StdTime bool `name:"stdTime" short:"s" brief:"{cGenDaoBriefStdTime}" orphan:"true"`
WithTime bool `name:"withTime" short:"c" brief:"{cGenDaoBriefWithTime}" orphan:"true"`
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{cGenDaoBriefGJsonSupport}" orphan:"true"`
OverwriteDao bool `name:"overwriteDao" short:"o" brief:"{cGenDaoBriefOverwriteDao}" orphan:"true"`
DescriptionTag bool `name:"descriptionTag" short:"d" brief:"{cGenDaoBriefDescriptionTag}" orphan:"true"`
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{cGenDaoBriefNoJsonTag" orphan:"true"`
NoModelComment bool `name:"noModelComment" short:"m" brief:"{cGenDaoBriefNoModelComment}" orphan:"true"`
}
cGenDaoOutput struct{}
cGenDaoInternalInput struct {
cGenDaoInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
ModName string // ModName specifies the module name of current golang project, which is used for import purpose.
}
)
func (c cGen) Dao(ctx context.Context, in cGenDaoInput) (out *cGenDaoOutput, err error) {
if g.Cfg().Available(ctx) {
v := g.Cfg().MustGet(ctx, cGenDaoConfig)
if v.IsSlice() {
for i := 0; i < len(v.Interfaces()); i++ {
doGenDaoForArray(ctx, i, in)
}
} else {
doGenDaoForArray(ctx, -1, in)
}
} else {
doGenDaoForArray(ctx, -1, in)
}
mlog.Print("done!")
return
}
// doGenDaoForArray implements the "gen dao" command for configuration array.
func doGenDaoForArray(ctx context.Context, index int, in cGenDaoInput) {
var (
err error
db gdb.DB
modName string // Go module name, eg: github.com/gogf/gf.
)
if index >= 0 {
err = g.Cfg().MustGet(
ctx,
fmt.Sprintf(`%s.%d`, cGenDaoConfig, index),
).Scan(&in)
if err != nil {
mlog.Fatalf(`invalid configuration of "%s": %+v`, cGenDaoConfig, err)
}
}
if dirRealPath := gfile.RealPath(in.Path); dirRealPath == "" {
mlog.Fatalf(`path "%s" does not exist`, in.Path)
}
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
if in.ImportPrefix == "" {
if !gfile.Exists("go.mod") {
mlog.Fatal("go.mod does not exist in current working directory")
}
var (
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
modName = gstr.Trim(match[1])
} else {
mlog.Fatal("module name does not found in go.mod")
}
}
// It uses user passed database configuration.
if in.Link != "" {
var (
tempGroup = gtime.TimestampNanoStr()
match, _ = gregex.MatchString(`([a-z]+):(.+)`, in.Link)
)
if len(match) == 3 {
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
Type: gstr.Trim(match[1]),
Link: gstr.Trim(match[2]),
})
if db, err = gdb.Instance(tempGroup); err != nil {
mlog.Debugf(`database initialization failed: %+v`, err)
}
} else {
mlog.Fatalf(`invalid database configuration: %s`, in.Link)
}
} else {
db = g.DB(in.Group)
}
if db == nil {
mlog.Fatal(`database initialization failed, may be invalid database configuration`)
}
var tableNames []string
if in.Tables != "" {
tableNames = gstr.SplitAndTrim(in.Tables, ",")
} else {
tableNames, err = db.Tables(context.TODO())
if err != nil {
mlog.Fatalf("fetching tables failed: %+v", err)
}
}
// Table excluding.
if in.TablesEx != "" {
array := garray.NewStrArrayFrom(tableNames)
for _, v := range gstr.SplitAndTrim(in.TablesEx, ",") {
array.RemoveValue(v)
}
tableNames = array.Slice()
}
// Generating dao & model go files one by one according to given table name.
newTableNames := make([]string, len(tableNames))
for i, tableName := range tableNames {
newTableName := tableName
for _, v := range removePrefixArray {
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
}
newTableName = in.Prefix + newTableName
newTableNames[i] = newTableName
// Dao.
generateDao(ctx, db, cGenDaoInternalInput{
cGenDaoInput: in,
TableName: tableName,
NewTableName: newTableName,
ModName: modName,
})
}
// Do.
generateDo(ctx, db, tableNames, newTableNames, cGenDaoInternalInput{
cGenDaoInput: in,
ModName: modName,
})
// Entity.
generateEntity(ctx, db, tableNames, newTableNames, cGenDaoInternalInput{
cGenDaoInput: in,
ModName: modName,
})
}
// generateDaoContentFile generates the dao and model content of given table.
func generateDao(ctx context.Context, db gdb.DB, in cGenDaoInternalInput) {
// Generating table data preparing.
fieldMap, err := db.TableFields(ctx, in.TableName)
if err != nil {
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
}
var (
dirRealPath = gfile.RealPath(in.Path)
dirPathDao = gfile.Join(in.Path, defaultDaoPath)
tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
importPrefix = in.ImportPrefix
)
if importPrefix == "" {
if dirRealPath == "" {
dirRealPath = in.Path
importPrefix = dirRealPath
importPrefix = gstr.Trim(dirRealPath, "./")
} else {
importPrefix = gstr.Replace(dirRealPath, gfile.Pwd(), "")
}
importPrefix = gstr.Replace(importPrefix, gfile.Separator, "/")
importPrefix = gstr.Join(g.SliceStr{in.ModName, importPrefix, defaultDaoPath}, "/")
importPrefix, _ = gregex.ReplaceString(`\/{2,}`, `/`, gstr.Trim(importPrefix, "/"))
}
fileName := gstr.Trim(tableNameSnakeCase, "-_.")
if len(fileName) > 5 && fileName[len(fileName)-5:] == "_test" {
// Add suffix to avoid the table name which contains "_test",
// which would make the go file a testing file.
fileName += "_table"
}
// dao - index
generateDaoIndex(in, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName)
// dao - internal
generateDaoInternal(in, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName, fieldMap)
}
func generateDo(ctx context.Context, db gdb.DB, tableNames, newTableNames []string, in cGenDaoInternalInput) {
var (
doDirPath = gfile.Join(in.Path, defaultDoPath)
)
in.NoJsonTag = true
in.DescriptionTag = false
in.NoModelComment = false
// Model content.
for i, tableName := range tableNames {
in.TableName = tableName
fieldMap, err := db.TableFields(ctx, tableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
}
var (
newTableName = newTableNames[i]
doFilePath = gfile.Join(doDirPath, gstr.CaseSnake(newTableName)+".go")
structDefinition = generateStructDefinition(generateStructDefinitionInput{
cGenDaoInternalInput: in,
StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap,
IsDo: true,
})
)
// replace all types to interface{}.
structDefinition, _ = gregex.ReplaceStringFuncMatch(
"([A-Z]\\w*?)\\s+([\\w\\*\\.]+?)\\s+(//)",
structDefinition,
func(match []string) string {
// If the type is already a pointer/slice/map, it does nothing.
if !gstr.HasPrefix(match[2], "*") && !gstr.HasPrefix(match[2], "[]") && !gstr.HasPrefix(match[2], "map") {
return fmt.Sprintf(`%s interface{} %s`, match[1], match[3])
}
return match[0]
},
)
modelContent := generateDoContent(
in,
tableName,
gstr.CaseCamel(newTableName),
structDefinition,
)
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
if err != nil {
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
} else {
utils.GoFmt(doFilePath)
mlog.Print("generated:", doFilePath)
}
}
}
func generateEntity(ctx context.Context, db gdb.DB, tableNames, newTableNames []string, in cGenDaoInternalInput) {
var (
entityDirPath = gfile.Join(in.Path, defaultEntityPath)
)
// Model content.
for i, tableName := range tableNames {
fieldMap, err := db.TableFields(ctx, tableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
}
var (
newTableName = newTableNames[i]
entityFilePath = gfile.Join(entityDirPath, gstr.CaseSnake(newTableName)+".go")
entityContent = generateEntityContent(
in,
newTableName,
gstr.CaseCamel(newTableName),
generateStructDefinition(generateStructDefinitionInput{
cGenDaoInternalInput: in,
StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap,
IsDo: false,
}),
)
)
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
if err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
} else {
utils.GoFmt(entityFilePath)
mlog.Print("generated:", entityFilePath)
}
}
}
func getImportPartContent(source string, isDo bool) string {
var (
packageImportsArray = garray.NewStrArray()
)
if isDo {
packageImportsArray.Append(`"github.com/gogf/gf/v2/frame/g"`)
}
// Time package recognition.
if strings.Contains(source, "gtime.Time") {
packageImportsArray.Append(`"github.com/gogf/gf/v2/os/gtime"`)
} else if strings.Contains(source, "time.Time") {
packageImportsArray.Append(`"time"`)
}
// Json type.
if strings.Contains(source, "gjson.Json") {
packageImportsArray.Append(`"github.com/gogf/gf/v2/encoding/gjson"`)
}
// Generate and write content to golang file.
packageImportsStr := ""
if packageImportsArray.Len() > 0 {
packageImportsStr = fmt.Sprintf("import(\n%s\n)", packageImportsArray.Join("\n"))
}
return packageImportsStr
}
func generateEntityContent(in cGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
entityContent := gstr.ReplaceByMap(consts.TemplateGenDaoEntityContent, g.MapStrStr{
tplVarTableName: tableName,
tplVarPackageImports: getImportPartContent(structDefine, false),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
})
entityContent = replaceDefaultVar(in, entityContent)
return entityContent
}
func generateDoContent(in cGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
doContent := gstr.ReplaceByMap(consts.TemplateGenDaoDoContent, g.MapStrStr{
tplVarTableName: tableName,
tplVarPackageImports: getImportPartContent(structDefine, true),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
})
doContent = replaceDefaultVar(in, doContent)
return doContent
}
func generateDaoIndex(in cGenDaoInternalInput, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName string) {
path := gfile.Join(dirPathDao, fileName+".go")
if in.OverwriteDao || !gfile.Exists(path) {
indexContent := gstr.ReplaceByMap(getTplDaoIndexContent(""), g.MapStrStr{
tplVarImportPrefix: importPrefix,
tplVarTableName: in.TableName,
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarTableNameCamelLowerCase: tableNameCamelLowerCase,
})
indexContent = replaceDefaultVar(in, indexContent)
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
}
}
}
func generateDaoInternal(
in cGenDaoInternalInput,
tableNameCamelCase, tableNameCamelLowerCase, importPrefix string,
dirPathDao, fileName string,
fieldMap map[string]*gdb.TableField,
) {
path := gfile.Join(dirPathDao, "internal", fileName+".go")
modelContent := gstr.ReplaceByMap(getTplDaoInternalContent(""), g.MapStrStr{
tplVarImportPrefix: importPrefix,
tplVarTableName: in.TableName,
tplVarGroupName: in.Group,
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarTableNameCamelLowerCase: tableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(fieldMap)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(fieldMap)),
})
modelContent = replaceDefaultVar(in, modelContent)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
}
}
func replaceDefaultVar(in cGenDaoInternalInput, origin string) string {
var tplDatetimeStr string
if in.WithTime {
tplDatetimeStr = fmt.Sprintf(`Created at %s`, createdAt.String())
}
return gstr.ReplaceByMap(origin, g.MapStrStr{
tplVarDatetimeStr: tplDatetimeStr,
})
}
type generateStructDefinitionInput struct {
cGenDaoInternalInput
StructName string // Struct name.
FieldMap map[string]*gdb.TableField // Table field map.
IsDo bool // Is generating DTO struct.
}
func generateStructDefinition(in generateStructDefinitionInput) string {
buffer := bytes.NewBuffer(nil)
array := make([][]string, len(in.FieldMap))
names := sortFieldKeyForDao(in.FieldMap)
for index, name := range names {
field := in.FieldMap[name]
array[index] = generateStructFieldDefinition(field, in)
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
stContent := buffer.String()
// Let's do this hack of table writer for indent!
stContent = gstr.Replace(stContent, " #", "")
stContent = gstr.Replace(stContent, "` ", "`")
stContent = gstr.Replace(stContent, "``", "")
buffer.Reset()
buffer.WriteString(fmt.Sprintf("type %s struct {\n", in.StructName))
if in.IsDo {
buffer.WriteString(fmt.Sprintf("g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName))
}
buffer.WriteString(stContent)
buffer.WriteString("}")
return buffer.String()
}
// generateStructFieldForModel generates and returns the attribute definition for specified field.
func generateStructFieldDefinition(field *gdb.TableField, in generateStructDefinitionInput) []string {
var (
typeName string
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
)
t, _ := gregex.ReplaceString(`\(.+\)`, "", field.Type)
t = gstr.Split(gstr.Trim(t), " ")[0]
t = gstr.ToLower(t)
switch t {
case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob":
typeName = "[]byte"
case "bit", "int", "int2", "tinyint", "small_int", "smallint", "medium_int", "mediumint", "serial":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "uint"
} else {
typeName = "int"
}
case "int4", "int8", "big_int", "bigint", "bigserial":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "uint64"
} else {
typeName = "int64"
}
case "real":
typeName = "float32"
case "float", "double", "decimal", "smallmoney", "numeric":
typeName = "float64"
case "bool":
typeName = "bool"
case "datetime", "timestamp", "date", "time":
if in.StdTime {
typeName = "time.Time"
} else {
typeName = "*gtime.Time"
}
case "json", "jsonb":
if in.GJsonSupport {
typeName = "*gjson.Json"
} else {
typeName = "string"
}
default:
// Automatically detect its data type.
switch {
case strings.Contains(t, "int"):
typeName = "int"
case strings.Contains(t, "text") || strings.Contains(t, "char"):
typeName = "string"
case strings.Contains(t, "float") || strings.Contains(t, "double"):
typeName = "float64"
case strings.Contains(t, "bool"):
typeName = "bool"
case strings.Contains(t, "binary") || strings.Contains(t, "blob"):
typeName = "[]byte"
case strings.Contains(t, "date") || strings.Contains(t, "time"):
if in.StdTime {
typeName = "time.Time"
} else {
typeName = "*gtime.Time"
}
default:
typeName = "string"
}
}
var (
tagKey = "`"
result = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + typeName,
}
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
result = append(result, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
result = append(result, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
for k, v := range result {
if in.NoJsonTag {
v, _ = gregex.ReplaceString(`json:".+"`, ``, v)
}
if !in.DescriptionTag {
v, _ = gregex.ReplaceString(`description:".*"`, ``, v)
}
if in.NoModelComment {
v, _ = gregex.ReplaceString(`//.+`, ``, v)
}
result[k] = v
}
return result
}
// formatComment formats the comment string to fit the golang code without any lines.
func formatComment(comment string) string {
comment = gstr.ReplaceByArray(comment, g.SliceStr{
"\n", " ",
"\r", " ",
})
comment = gstr.Replace(comment, `\n`, " ")
comment = gstr.Trim(comment)
return comment
}
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
var (
field = fieldMap[name]
comment = gstr.Trim(gstr.ReplaceByArray(field.Comment, g.SliceStr{
"\n", " ",
"\r", " ",
}))
)
array[index] = []string{
" #" + gstr.CaseCamel(field.Name),
" # " + "string",
" #" + fmt.Sprintf(`// %s`, comment),
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
defineContent := buffer.String()
// Let's do this hack of table writer for indent!
defineContent = gstr.Replace(defineContent, " #", "")
buffer.Reset()
buffer.WriteString(defineContent)
return buffer.String()
}
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
field := fieldMap[name]
array[index] = []string{
" #" + gstr.CaseCamel(field.Name) + ":",
fmt.Sprintf(` #"%s",`, field.Name),
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
namesContent := buffer.String()
// Let's do this hack of table writer for indent!
namesContent = gstr.Replace(namesContent, " #", "")
buffer.Reset()
buffer.WriteString(namesContent)
return buffer.String()
}
func getTplDaoIndexContent(tplDaoIndexPath string) string {
if tplDaoIndexPath != "" {
return gfile.GetContents(tplDaoIndexPath)
}
return consts.TemplateDaoDaoIndexContent
}
func getTplDaoInternalContent(tplDaoInternalPath string) string {
if tplDaoInternalPath != "" {
return gfile.GetContents(tplDaoInternalPath)
}
return consts.TemplateDaoDaoInternalContent
}
// getJsonTagFromCase call gstr.Case* function to convert the s to specified case.
func getJsonTagFromCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
}
return str
}
func sortFieldKeyForDao(fieldMap map[string]*gdb.TableField) []string {
names := make(map[int]string)
for _, field := range fieldMap {
names[field.Index] = field.Name
}
var (
i = 0
j = 0
result = make([]string, len(names))
)
for {
if len(names) == 0 {
break
}
if val, ok := names[i]; ok {
result[j] = val
j++
delete(names, i)
}
i++
}
return result
}

View File

@ -13,14 +13,13 @@ import (
)
type (
cGenPb struct{}
cGenPbInput struct {
g.Meta `name:"pb" brief:"parse proto files and generate protobuf go files"`
}
cGenPbOutput struct{}
)
func (c cGenPb) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err error) {
func (c cGen) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err error) {
// Necessary check.
if gproc.SearchBinary("protoc") == "" {
mlog.Fatalf(`command "protoc" not found in your environment, please install protoc first to proceed this command`)
@ -57,7 +56,7 @@ func (c cGenPb) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err
parsingCommand += " -I" + goPathSrc
}
mlog.Print(parsingCommand)
if output, err := gproc.ShellExec(ctx, parsingCommand); err != nil {
if output, err := gproc.ShellExec(parsingCommand); err != nil {
mlog.Print(output)
mlog.Fatal(err)
}

View File

@ -19,29 +19,6 @@ import (
"github.com/olekukonko/tablewriter"
)
type (
cGenPbEntity struct{}
cGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{cGenPbEntityConfig}" brief:"{cGenPbEntityBrief}" eg:"{cGenPbEntityEg}" ad:"{cGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{cGenPbEntityBriefPath}"`
Package string `name:"package" short:"k" brief:"{cGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{cGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{cGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{cGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{cGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{cGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{cGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{cGenPbEntityBriefOption}"`
}
cGenPbEntityOutput struct{}
cGenPbEntityInternalInput struct {
cGenPbEntityInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
}
)
const (
cGenPbEntityConfig = `gfcli.gen.pbentity`
cGenPbEntityBrief = `generate entity message files in protobuf3 format`
@ -106,6 +83,28 @@ set it to "none" to ignore json tag generating.
`
)
type (
cGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{cGenPbEntityConfig}" brief:"{cGenPbEntityBrief}" eg:"{cGenPbEntityEg}" ad:"{cGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{cGenPbEntityBriefPath}"`
Package string `name:"package" short:"k" brief:"{cGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{cGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{cGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{cGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{cGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{cGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{cGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{cGenPbEntityBriefOption}"`
}
cGenPbEntityOutput struct{}
cGenPbEntityInternalInput struct {
cGenPbEntityInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
}
)
func init() {
gtag.Sets(g.MapStrStr{
`cGenPbEntityConfig`: cGenPbEntityConfig,
@ -125,7 +124,7 @@ func init() {
})
}
func (c cGenPbEntity) PbEntity(ctx context.Context, in cGenPbEntityInput) (out *cGenPbEntityOutput, err error) {
func (c cGen) PbEntity(ctx context.Context, in cGenPbEntityInput) (out *cGenPbEntityOutput, err error) {
var (
config = g.Cfg()
)
@ -153,10 +152,10 @@ func doGenPbEntityForArray(ctx context.Context, index int, in cGenPbEntityInput)
if index >= 0 {
err = g.Cfg().MustGet(
ctx,
fmt.Sprintf(`%s.%d`, cGenPbEntityConfig, index),
fmt.Sprintf(`%s.%d`, cGenDaoConfig, index),
).Scan(&in)
if err != nil {
mlog.Fatalf(`invalid configuration of "%s": %+v`, cGenPbEntityConfig, err)
mlog.Fatalf(`invalid configuration of "%s": %+v`, cGenDaoConfig, err)
}
}
if in.Package == "" {

View File

@ -1,441 +0,0 @@
package cmd
import (
"context"
"fmt"
"go/parser"
"go/token"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/garray"
"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/os/gtime"
"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/gtag"
)
const (
cGenServiceConfig = `gfcli.gen.service`
cGenServiceUsage = `gf gen service [OPTION]`
cGenServiceBrief = `parse struct and associated functions from packages to generate service go file`
cGenServiceEg = `
gf gen service
gf gen service -f Snake
`
cGenServiceBriefSrcFolder = `source folder path to be parsed. default: internal/logic`
cGenServiceBriefDstFolder = `destination folder path storing automatically generated go files. default: internal/service`
cGenServiceBriefFileNameCase = `
destination file name storing automatically generated go files, cases are as follows:
| Case | Example |
|---------------- |--------------------|
| Lower | anykindofstring |
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString |
| Snake | any_kind_of_string | default
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
cGenServiceBriefWatchFile = `used in file watcher, it generates service go files only if given file is under srcFolder`
cGenServiceBriefStPattern = `regular expression matching struct name for generating service. default: s([A-Z]\\\\w+)`
cGenServiceBriefPackages = `produce go files only for given source packages`
cGenServiceBriefImportPrefix = `custom import prefix to calculate import path for generated importing go file of logic`
cGenServiceBriefOverWrite = `overwrite service go files that already exist in generating folder. default: true`
)
func init() {
gtag.Sets(g.MapStrStr{
`cGenServiceConfig`: cGenServiceConfig,
`cGenServiceUsage`: cGenServiceUsage,
`cGenServiceBrief`: cGenServiceBrief,
`cGenServiceEg`: cGenServiceEg,
`cGenServiceBriefSrcFolder`: cGenServiceBriefSrcFolder,
`cGenServiceBriefDstFolder`: cGenServiceBriefDstFolder,
`cGenServiceBriefFileNameCase`: cGenServiceBriefFileNameCase,
`cGenServiceBriefWatchFile`: cGenServiceBriefWatchFile,
`cGenServiceBriefStPattern`: cGenServiceBriefStPattern,
`cGenServiceBriefPackages`: cGenServiceBriefPackages,
`cGenServiceBriefImportPrefix`: cGenServiceBriefImportPrefix,
`cGenServiceBriefOverWrite`: cGenServiceBriefOverWrite,
})
}
type (
cGenService struct{}
cGenServiceInput struct {
g.Meta `name:"service" config:"{cGenServiceConfig}" usage:"{cGenServiceUsage}" brief:"{cGenServiceBrief}" eg:"{cGenServiceEg}"`
SrcFolder string `short:"s" name:"srcFolder" brief:"{cGenServiceBriefSrcFolder}" d:"internal/logic"`
DstFolder string `short:"d" name:"dstFolder" brief:"{cGenServiceBriefDstFolder}" d:"internal/service"`
DstFileNameCase string `short:"f" name:"dstFileNameCase" brief:"{cGenServiceBriefFileNameCase}" d:"Snake"`
WatchFile string `short:"w" name:"watchFile" brief:"{cGenServiceBriefWatchFile}"`
StPattern string `short:"a" name:"stPattern" brief:"{cGenServiceBriefStPattern}" d:"s([A-Z]\\w+)"`
Packages []string `short:"p" name:"packages" brief:"{cGenServiceBriefPackages}"`
ImportPrefix string `short:"i" name:"importPrefix" brief:"{cGenServiceBriefImportPrefix}"`
OverWrite bool `short:"o" name:"overwrite" brief:"{cGenServiceBriefOverWrite}" d:"true" orphan:"true"`
}
cGenServiceOutput struct{}
)
const (
genServiceFileLockSeconds = 10
)
func (c cGenService) Service(ctx context.Context, in cGenServiceInput) (out *cGenServiceOutput, err error) {
// File lock to avoid multiple processes.
var (
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
flockContent = gfile.GetContents(flockFilePath)
)
if flockContent != "" {
if gtime.Timestamp()-gconv.Int64(flockContent) < genServiceFileLockSeconds {
// If another "gen service" process is running, it just exits.
mlog.Debug(`another "gen service" process is running, exit`)
return
}
}
defer gfile.Remove(flockFilePath)
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
// Watch file handling.
if in.WatchFile != "" {
// It works only if given WatchFile is in SrcFolder.
var (
watchFileDir = gfile.Dir(in.WatchFile)
srcFolderDir = gfile.Dir(watchFileDir)
)
mlog.Debug("watchFileDir:", watchFileDir)
mlog.Debug("logicFolderDir:", srcFolderDir)
if !gstr.HasSuffix(gstr.Replace(srcFolderDir, `\`, `/`), in.SrcFolder) {
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
return
}
var newWorkingDir = gfile.Dir(gfile.Dir(srcFolderDir))
if err = gfile.Chdir(newWorkingDir); err != nil {
mlog.Fatalf(`%+v`, err)
}
mlog.Debug("Chdir:", newWorkingDir)
_ = gfile.Remove(flockFilePath)
var command = fmt.Sprintf(
`%s gen service -packages=%s`,
gfile.SelfName(), gfile.Basename(watchFileDir),
)
err = gproc.ShellRun(ctx, command)
return
}
if !gfile.Exists(in.SrcFolder) {
mlog.Fatalf(`source folder path "%s" does not exist`, in.SrcFolder)
}
if in.ImportPrefix == "" {
if !gfile.Exists("go.mod") {
mlog.Fatal("ImportPrefix is empty and go.mod does not exist in current working directory")
}
var (
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
in.ImportPrefix = fmt.Sprintf(`%s/%s`, gstr.Trim(match[1]), gstr.Replace(in.SrcFolder, `\`, `/`))
}
}
var (
isDirty bool
files []string
fileContent string
initImportSrcPackages []string
inputPackages = in.Packages
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder))
)
srcFolders, err := gfile.ScanDir(in.SrcFolder, "*", false)
if err != nil {
return nil, err
}
for _, srcFolder := range srcFolders {
if !gfile.IsDir(srcFolder) {
continue
}
if files, err = gfile.ScanDir(srcFolder, "*.go", false); err != nil {
return nil, err
}
if len(files) == 0 {
continue
}
var (
// StructName => FunctionDefinitions
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
ok bool
)
for _, file := range files {
fileContent = gfile.GetContents(file)
// Calculate imported packages of source go files.
err = c.calculateImportedPackages(fileContent, srcImportedPackages)
if err != nil {
return nil, err
}
// Calculate functions and interfaces for service generating.
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap, dstPackageName)
if err != nil {
return nil, err
}
}
initImportSrcPackages = append(
initImportSrcPackages,
fmt.Sprintf(`%s/%s`, in.ImportPrefix, gfile.Basename(srcFolder)),
)
// Ignore source packages if input packages given.
if len(inputPackages) > 0 && !gstr.InArray(inputPackages, gfile.Basename(srcFolder)) {
mlog.Debugf(
`ignore source package "%s" as it is not in desired packages: %+v`,
gfile.Basename(srcFolder), inputPackages,
)
continue
}
// Generating go files for service.
if ok, err = c.generateServiceFiles(in, srcPkgInterfaceMap, srcImportedPackages.Slice(), dstPackageName); err != nil {
return
}
if ok {
isDirty = true
}
}
if isDirty {
// Generate initialization go file.
if len(initImportSrcPackages) > 0 {
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
return
}
}
// Replace v1 to v2 for GoFrame.
if err = c.replaceGeneratedServiceContentGFV2(in); err != nil {
return nil, err
}
mlog.Printf(`gofmt go files in "%s"`, in.DstFolder)
utils.GoFmt(in.DstFolder)
}
mlog.Print(`done!`)
return
}
func (c cGenService) calculateImportedPackages(fileContent string, srcImportedPackages *garray.SortedStrArray) (err error) {
f, err := parser.ParseFile(token.NewFileSet(), "", fileContent, parser.ImportsOnly)
if err != nil {
return err
}
for _, s := range f.Imports {
if s.Path != nil {
if s.Name != nil {
// has alias and is not `_`
if pkgAlias := s.Name.String(); pkgAlias != "_" {
srcImportedPackages.Add(pkgAlias + " " + s.Path.Value)
}
} else {
// no alias
srcImportedPackages.Add(s.Path.Value)
}
}
}
return nil
}
func (c cGenService) calculateInterfaceFunctions(
in cGenServiceInput, fileContent string, srcPkgInterfaceMap map[string]*garray.StrArray, dstPackageName string,
) (err error) {
var (
ok bool
matches [][]string
srcPkgInterfaceFuncArray *garray.StrArray
)
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
}
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
}
// Remove package name calls of `dstPackageName` in produced codes.
functionHead, _ = gregex.ReplaceString(fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName), ``, functionHead)
srcPkgInterfaceFuncArray.Append(functionHead)
}
return nil
}
func (c cGenService) generateServiceFiles(
in cGenServiceInput,
srcPkgInterfaceMap map[string]*garray.StrArray,
srcImportedPackages []string,
dstPackageName string,
) (ok bool, err error) {
srcImportedPackagesContent := fmt.Sprintf(
"import (\n%s\n)", gstr.Join(srcImportedPackages, "\n"),
)
for structName, funcArray := range srcPkgInterfaceMap {
var (
filePath = gfile.Join(in.DstFolder, c.getDstFileNameCase(structName, in.DstFileNameCase)+".go")
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceContent, g.MapStrStr{
"{Imports}": srcImportedPackagesContent,
"{StructName}": structName,
"{PackageName}": dstPackageName,
"{FuncDefinition}": funcArray.Join("\n\t"),
})
)
if gfile.Exists(filePath) {
if !in.OverWrite {
mlog.Printf(`not overwrite, ignore generating service go file: %s`, filePath)
continue
}
if !utils.IsFileDoNotEdit(filePath) {
mlog.Printf(`ignore file as it is manually maintained: %s`, filePath)
continue
}
if !c.isToGenerateServiceGoFile(filePath, funcArray) {
mlog.Printf(`not dirty, ignore generating service go file: %s`, filePath)
continue
}
}
ok = true
mlog.Printf(`generating service go file: %s`, filePath)
if err = gfile.PutContents(filePath, generatedContent); err != nil {
return ok, err
}
}
return ok, nil
}
// isToGenerateServiceGoFile checks and returns whether the service content dirty.
func (c cGenService) isToGenerateServiceGoFile(filePath string, funcArray *garray.StrArray) bool {
var (
fileContent = gfile.GetContents(filePath)
generatedFuncArray = garray.NewSortedStrArrayFrom(funcArray.Slice())
contentFuncArray = garray.NewSortedStrArray()
)
if fileContent == "" {
return true
}
match, _ := gregex.MatchString(`interface\s+{([\s\S]+?)}`, fileContent)
if len(match) != 2 {
return false
}
contentFuncArray.Append(gstr.SplitAndTrim(match[1], "\n")...)
if generatedFuncArray.Len() != contentFuncArray.Len() {
return true
}
for i := 0; i < generatedFuncArray.Len(); i++ {
if generatedFuncArray.At(i) != contentFuncArray.At(i) {
mlog.Debugf(`dirty, %s != %s`, generatedFuncArray.At(i), contentFuncArray.At(i))
return true
}
}
return false
}
func (c cGenService) generateInitializationFile(in cGenServiceInput, importSrcPackages []string) (err error) {
var (
srcPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
srcFilePath = gfile.Join(in.SrcFolder, srcPackageName+".go")
srcImports string
generatedContent string
)
if !utils.IsFileDoNotEdit(srcFilePath) {
mlog.Debugf(`ignore file as it is manually maintained: %s`, srcFilePath)
return nil
}
for _, importSrcPackage := range importSrcPackages {
srcImports += fmt.Sprintf(`%s_ "%s"%s`, "\t", importSrcPackage, "\n")
}
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceLogicContent, g.MapStrStr{
"{PackageName}": srcPackageName,
"{Imports}": srcImports,
})
mlog.Printf(`generating init go file: %s`, srcFilePath)
if err = gfile.PutContents(srcFilePath, generatedContent); err != nil {
return err
}
utils.GoFmt(srcFilePath)
return nil
}
func (c cGenService) replaceGeneratedServiceContentGFV2(in cGenServiceInput) (err error) {
return gfile.ReplaceDirFunc(func(path, content string) string {
if gstr.Contains(content, `"github.com/gogf/gf`) && !gstr.Contains(content, `"github.com/gogf/gf/v2`) {
content = gstr.Replace(content, `"github.com/gogf/gf"`, `"github.com/gogf/gf/v2"`)
content = gstr.Replace(content, `"github.com/gogf/gf/`, `"github.com/gogf/gf/v2/`)
return content
}
return content
}, in.DstFolder, "*.go", false)
}
// getDstFileNameCase call gstr.Case* function to convert the s to specified case.
func (c cGenService) getDstFileNameCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Lower"):
return gstr.ToLower(str)
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
}
return gstr.CaseSnake(str)
}

View File

@ -10,7 +10,6 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gtag"
)
@ -49,8 +48,7 @@ func init() {
type cInitInput struct {
g.Meta `name:"init"`
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
}
type cInitOutput struct{}
@ -91,27 +89,6 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
return
}
// Update the GoFrame version.
if in.Update {
mlog.Print("update goframe...")
// go get -u github.com/gogf/gf/v2@latest
updateCommand := `go get -u github.com/gogf/gf/v2@latest`
if in.Name != "." {
updateCommand = fmt.Sprintf(`cd %s && %s`, in.Name, updateCommand)
}
if err = gproc.ShellRun(ctx, updateCommand); err != nil {
mlog.Fatal(err)
}
// go mod tidy
gomModTidyCommand := `go mod tidy`
if in.Name != "." {
gomModTidyCommand = fmt.Sprintf(`cd %s && %s`, in.Name, gomModTidyCommand)
}
if err = gproc.ShellRun(ctx, gomModTidyCommand); err != nil {
mlog.Fatal(err)
}
}
mlog.Print("initialization done! ")
if !in.Mono {
enjoyCommand := `gf run main.go`

View File

@ -13,6 +13,7 @@ import (
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/os/gtimer"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
)
@ -46,7 +47,6 @@ which compiles and runs the go codes asynchronously when codes change.
cRunFileBrief = `building file path.`
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
cRunArgsBrief = `custom arguments for your process`
)
var (
@ -62,7 +62,6 @@ func init() {
`cRunFileBrief`: cRunFileBrief,
`cRunPathBrief`: cRunPathBrief,
`cRunExtraBrief`: cRunExtraBrief,
`cRunArgsBrief`: cRunArgsBrief,
})
}
@ -72,7 +71,6 @@ type (
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
}
cRunOutput struct{}
)
@ -87,7 +85,6 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
File: in.File,
Path: in.Path,
Options: in.Extra,
Args: in.Args,
}
dirty := gtype.NewBool()
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {
@ -102,17 +99,17 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
defer dirty.Set(false)
mlog.Printf(`go file changes: %s`, event.String())
app.Run(ctx)
app.Run()
})
})
if err != nil {
mlog.Fatal(err)
}
go app.Run(ctx)
go app.Run()
select {}
}
func (app *cRunApp) Run(ctx context.Context) {
func (app *cRunApp) Run() {
// Rebuild and run the codes.
renamePath := ""
mlog.Printf("build: %s", app.File)
@ -135,7 +132,7 @@ func (app *cRunApp) Run(ctx context.Context) {
app.File,
)
mlog.Print(buildCommand)
result, err := gproc.ShellExec(ctx, buildCommand)
result, err := gproc.ShellExec(buildCommand)
if err != nil {
mlog.Printf("build error: \n%s%s", result, err.Error())
return
@ -153,11 +150,11 @@ func (app *cRunApp) Run(ctx context.Context) {
if runtime.GOOS == "windows" {
// Special handling for windows platform.
// DO NOT USE "cmd /c" command.
process = gproc.NewProcess(runCommand, nil)
process = gproc.NewProcess(outputPath, gstr.SplitAndTrim(" ", app.Args))
} else {
process = gproc.NewProcessCmd(runCommand, nil)
process = gproc.NewProcessCmd(outputPath, gstr.SplitAndTrim(" ", app.Args))
}
if pid, err := process.Start(ctx); err != nil {
if pid, err := process.Start(); err != nil {
mlog.Printf("build running error: %s", err.Error())
} else {
mlog.Printf("build running pid: %d", pid)

View File

@ -1,363 +0,0 @@
package gendao
import (
"context"
"fmt"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
)
const (
CGenDaoConfig = `gfcli.gen.dao`
CGenDaoUsage = `gf gen dao [OPTION]`
CGenDaoBrief = `automatically generate go files for dao/do/entity`
CGenDaoEg = `
gf gen dao
gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
gf gen dao -p ./model -g user-center -t user,user_detail,user_login
gf gen dao -r user_
`
CGenDaoAd = `
CONFIGURATION SUPPORT
Options are also supported by configuration file.
It's suggested using configuration file instead of command line arguments making producing.
The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml):
gfcli:
gen:
dao:
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
tables: "order,products"
jsonCase: "CamelLower"
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
path: "./my-app"
prefix: "primary_"
tables: "user, userDetail"
`
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
CGenDaoBriefJsonCase = `
generated json tag case for model struct, cases are as follows:
| Case | Example |
|---------------- |--------------------|
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString | default
| Snake | any_kind_of_string |
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
CGenDaoBriefTplDaoIndexPath = `template file path for dao index file`
CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file`
CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file`
CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file`
tplVarTableName = `{TplTableName}`
tplVarTableNameCamelCase = `{TplTableNameCamelCase}`
tplVarTableNameCamelLowerCase = `{TplTableNameCamelLowerCase}`
tplVarPackageImports = `{TplPackageImports}`
tplVarImportPrefix = `{TplImportPrefix}`
tplVarStructDefine = `{TplStructDefine}`
tplVarColumnDefine = `{TplColumnDefine}`
tplVarColumnNames = `{TplColumnNames}`
tplVarGroupName = `{TplGroupName}`
tplVarDatetimeStr = `{TplDatetimeStr}`
tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}`
)
var (
createdAt = gtime.Now()
)
func init() {
gtag.Sets(g.MapStrStr{
`CGenDaoConfig`: CGenDaoConfig,
`CGenDaoUsage`: CGenDaoUsage,
`CGenDaoBrief`: CGenDaoBrief,
`CGenDaoEg`: CGenDaoEg,
`CGenDaoAd`: CGenDaoAd,
`CGenDaoBriefPath`: CGenDaoBriefPath,
`CGenDaoBriefLink`: CGenDaoBriefLink,
`CGenDaoBriefTables`: CGenDaoBriefTables,
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
`CGenDaoBriefDoPath`: CGenDaoBriefDoPath,
`CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath,
`CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport,
`CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix,
`CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao,
`CGenDaoBriefModelFile`: CGenDaoBriefModelFile,
`CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao,
`CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag,
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
`CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath,
`CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath,
`CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath,
})
}
type (
CGenDao struct{}
CGenDaoInput struct {
g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"`
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
TplDaoEntitylPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"`
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"`
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
}
CGenDaoOutput struct{}
CGenDaoInternalInput struct {
CGenDaoInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
ModName string // ModName specifies the module name of current golang project, which is used for import purpose.
}
)
func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) {
if g.Cfg().Available(ctx) {
v := g.Cfg().MustGet(ctx, CGenDaoConfig)
if v.IsSlice() {
for i := 0; i < len(v.Interfaces()); i++ {
doGenDaoForArray(ctx, i, in)
}
} else {
doGenDaoForArray(ctx, -1, in)
}
} else {
doGenDaoForArray(ctx, -1, in)
}
mlog.Print("done!")
return
}
// doGenDaoForArray implements the "gen dao" command for configuration array.
func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
var (
err error
db gdb.DB
modName string // Go module name, eg: github.com/gogf/gf.
)
if index >= 0 {
err = g.Cfg().MustGet(
ctx,
fmt.Sprintf(`%s.%d`, CGenDaoConfig, index),
).Scan(&in)
if err != nil {
mlog.Fatalf(`invalid configuration of "%s": %+v`, CGenDaoConfig, err)
}
}
if dirRealPath := gfile.RealPath(in.Path); dirRealPath == "" {
mlog.Fatalf(`path "%s" does not exist`, in.Path)
}
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
if in.ImportPrefix == "" {
if !gfile.Exists("go.mod") {
mlog.Fatal("go.mod does not exist in current working directory")
}
var (
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
modName = gstr.Trim(match[1])
} else {
mlog.Fatal("module name does not found in go.mod")
}
}
// It uses user passed database configuration.
if in.Link != "" {
var tempGroup = gtime.TimestampNanoStr()
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
Link: in.Link,
})
if db, err = gdb.Instance(tempGroup); err != nil {
mlog.Fatalf(`database initialization failed: %+v`, err)
}
} else {
db = g.DB(in.Group)
}
if db == nil {
mlog.Fatal(`database initialization failed, may be invalid database configuration`)
}
var tableNames []string
if in.Tables != "" {
tableNames = gstr.SplitAndTrim(in.Tables, ",")
} else {
tableNames, err = db.Tables(context.TODO())
if err != nil {
mlog.Fatalf("fetching tables failed: %+v", err)
}
}
// Table excluding.
if in.TablesEx != "" {
array := garray.NewStrArrayFrom(tableNames)
for _, v := range gstr.SplitAndTrim(in.TablesEx, ",") {
array.RemoveValue(v)
}
tableNames = array.Slice()
}
// Generating dao & model go files one by one according to given table name.
newTableNames := make([]string, len(tableNames))
for i, tableName := range tableNames {
newTableName := tableName
for _, v := range removePrefixArray {
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
}
newTableName = in.Prefix + newTableName
newTableNames[i] = newTableName
// Dao.
generateDao(ctx, db, CGenDaoInternalInput{
CGenDaoInput: in,
TableName: tableName,
NewTableName: newTableName,
ModName: modName,
})
}
// Do.
generateDo(ctx, db, tableNames, newTableNames, CGenDaoInternalInput{
CGenDaoInput: in,
ModName: modName,
})
// Entity.
generateEntity(ctx, db, tableNames, newTableNames, CGenDaoInternalInput{
CGenDaoInput: in,
ModName: modName,
})
}
func getImportPartContent(source string, isDo bool) string {
var (
packageImportsArray = garray.NewStrArray()
)
if isDo {
packageImportsArray.Append(`"github.com/gogf/gf/v2/frame/g"`)
}
// Time package recognition.
if strings.Contains(source, "gtime.Time") {
packageImportsArray.Append(`"github.com/gogf/gf/v2/os/gtime"`)
} else if strings.Contains(source, "time.Time") {
packageImportsArray.Append(`"time"`)
}
// Json type.
if strings.Contains(source, "gjson.Json") {
packageImportsArray.Append(`"github.com/gogf/gf/v2/encoding/gjson"`)
}
// Generate and write content to golang file.
packageImportsStr := ""
if packageImportsArray.Len() > 0 {
packageImportsStr = fmt.Sprintf("import(\n%s\n)", packageImportsArray.Join("\n"))
}
return packageImportsStr
}
func replaceDefaultVar(in CGenDaoInternalInput, origin string) string {
var tplCreatedAtDatetimeStr string
var tplDatetimeStr string = createdAt.String()
if in.WithTime {
tplCreatedAtDatetimeStr = fmt.Sprintf(`Created at %s`, tplDatetimeStr)
}
return gstr.ReplaceByMap(origin, g.MapStrStr{
tplVarDatetimeStr: tplDatetimeStr,
tplVarCreatedAtDatetimeStr: tplCreatedAtDatetimeStr,
})
}
func sortFieldKeyForDao(fieldMap map[string]*gdb.TableField) []string {
names := make(map[int]string)
for _, field := range fieldMap {
names[field.Index] = field.Name
}
var (
i = 0
j = 0
result = make([]string, len(names))
)
for {
if len(names) == 0 {
break
}
if val, ok := names[i]; ok {
result[j] = val
j++
delete(names, i)
}
i++
}
return result
}
func getTemplateFromPathOrDefault(filePath string, def string) string {
if filePath != "" {
if contents := gfile.GetContents(filePath); contents != "" {
return contents
}
}
return def
}

View File

@ -1,176 +0,0 @@
package gendao
import (
"bytes"
"context"
"fmt"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter"
)
// generateDaoContentFile generates the dao and model content of given table.
func generateDao(ctx context.Context, db gdb.DB, in CGenDaoInternalInput) {
// Generating table data preparing.
fieldMap, err := db.TableFields(ctx, in.TableName)
if err != nil {
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
}
var (
dirRealPath = gfile.RealPath(in.Path)
dirPathDao = gfile.Join(in.Path, in.DaoPath)
tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
importPrefix = in.ImportPrefix
)
if importPrefix == "" {
if dirRealPath == "" {
dirRealPath = in.Path
importPrefix = dirRealPath
importPrefix = gstr.Trim(dirRealPath, "./")
} else {
importPrefix = gstr.Replace(dirRealPath, gfile.Pwd(), "")
}
importPrefix = gstr.Replace(importPrefix, gfile.Separator, "/")
importPrefix = gstr.Join(g.SliceStr{in.ModName, importPrefix, in.DaoPath}, "/")
importPrefix, _ = gregex.ReplaceString(`\/{2,}`, `/`, gstr.Trim(importPrefix, "/"))
} else {
importPrefix = gstr.Join(g.SliceStr{importPrefix, in.DaoPath}, "/")
}
fileName := gstr.Trim(tableNameSnakeCase, "-_.")
if len(fileName) > 5 && fileName[len(fileName)-5:] == "_test" {
// Add suffix to avoid the table name which contains "_test",
// which would make the go file a testing file.
fileName += "_table"
}
// dao - index
generateDaoIndex(in, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName)
// dao - internal
generateDaoInternal(in, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName, fieldMap)
}
func generateDaoIndex(in CGenDaoInternalInput, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName string) {
path := gfile.Join(dirPathDao, fileName+".go")
if in.OverwriteDao || !gfile.Exists(path) {
indexContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
g.MapStrStr{
tplVarImportPrefix: importPrefix,
tplVarTableName: in.TableName,
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarTableNameCamelLowerCase: tableNameCamelLowerCase,
})
indexContent = replaceDefaultVar(in, indexContent)
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
}
}
}
func generateDaoInternal(
in CGenDaoInternalInput,
tableNameCamelCase, tableNameCamelLowerCase, importPrefix string,
dirPathDao, fileName string,
fieldMap map[string]*gdb.TableField,
) {
path := gfile.Join(dirPathDao, "internal", fileName+".go")
modelContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
g.MapStrStr{
tplVarImportPrefix: importPrefix,
tplVarTableName: in.TableName,
tplVarGroupName: in.Group,
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarTableNameCamelLowerCase: tableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(fieldMap)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(fieldMap)),
})
modelContent = replaceDefaultVar(in, modelContent)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
}
}
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
field := fieldMap[name]
array[index] = []string{
" #" + gstr.CaseCamel(field.Name) + ":",
fmt.Sprintf(` #"%s",`, field.Name),
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
namesContent := buffer.String()
// Let's do this hack of table writer for indent!
namesContent = gstr.Replace(namesContent, " #", "")
buffer.Reset()
buffer.WriteString(namesContent)
return buffer.String()
}
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
var (
field = fieldMap[name]
comment = gstr.Trim(gstr.ReplaceByArray(field.Comment, g.SliceStr{
"\n", " ",
"\r", " ",
}))
)
array[index] = []string{
" #" + gstr.CaseCamel(field.Name),
" # " + "string",
" #" + fmt.Sprintf(`// %s`, comment),
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
defineContent := buffer.String()
// Let's do this hack of table writer for indent!
defineContent = gstr.Replace(defineContent, " #", "")
buffer.Reset()
buffer.WriteString(defineContent)
return buffer.String()
}

View File

@ -1,82 +0,0 @@
package gendao
import (
"context"
"fmt"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
func generateDo(ctx context.Context, db gdb.DB, tableNames, newTableNames []string, in CGenDaoInternalInput) {
var (
doDirPath = gfile.Join(in.Path, in.DoPath)
)
in.NoJsonTag = true
in.DescriptionTag = false
in.NoModelComment = false
// Model content.
for i, tableName := range tableNames {
in.TableName = tableName
fieldMap, err := db.TableFields(ctx, tableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
}
var (
newTableName = newTableNames[i]
doFilePath = gfile.Join(doDirPath, gstr.CaseSnake(newTableName)+".go")
structDefinition = generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
DB: db,
StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap,
IsDo: true,
})
)
// replace all types to interface{}.
structDefinition, _ = gregex.ReplaceStringFuncMatch(
"([A-Z]\\w*?)\\s+([\\w\\*\\.]+?)\\s+(//)",
structDefinition,
func(match []string) string {
// If the type is already a pointer/slice/map, it does nothing.
if !gstr.HasPrefix(match[2], "*") && !gstr.HasPrefix(match[2], "[]") && !gstr.HasPrefix(match[2], "map") {
return fmt.Sprintf(`%s interface{} %s`, match[1], match[3])
}
return match[0]
},
)
modelContent := generateDoContent(
in,
tableName,
gstr.CaseCamel(newTableName),
structDefinition,
)
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
if err != nil {
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
} else {
utils.GoFmt(doFilePath)
mlog.Print("generated:", doFilePath)
}
}
}
func generateDoContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
doContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoDoPath, consts.TemplateGenDaoDoContent),
g.MapStrStr{
tplVarTableName: tableName,
tplVarPackageImports: getImportPartContent(structDefine, true),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
})
doContent = replaceDefaultVar(in, doContent)
return doContent
}

View File

@ -1,61 +0,0 @@
package gendao
import (
"context"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
)
func generateEntity(ctx context.Context, db gdb.DB, tableNames, newTableNames []string, in CGenDaoInternalInput) {
var entityDirPath = gfile.Join(in.Path, in.EntityPath)
// Model content.
for i, tableName := range tableNames {
fieldMap, err := db.TableFields(ctx, tableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
}
var (
newTableName = newTableNames[i]
entityFilePath = gfile.Join(entityDirPath, gstr.CaseSnake(newTableName)+".go")
entityContent = generateEntityContent(
in,
newTableName,
gstr.CaseCamel(newTableName),
generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
DB: db,
StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap,
IsDo: false,
}),
)
)
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
if err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
} else {
utils.GoFmt(entityFilePath)
mlog.Print("generated:", entityFilePath)
}
}
}
func generateEntityContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
entityContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoEntitylPath, consts.TemplateGenDaoEntityContent),
g.MapStrStr{
tplVarTableName: tableName,
tplVarPackageImports: getImportPartContent(structDefine, false),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
})
entityContent = replaceDefaultVar(in, entityContent)
return entityContent
}

View File

@ -1,153 +0,0 @@
package gendao
import (
"bytes"
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter"
)
type generateStructDefinitionInput struct {
CGenDaoInternalInput
DB gdb.DB // Current DB.
StructName string // Struct name.
FieldMap map[string]*gdb.TableField // Table field map.
IsDo bool // Is generating DTO struct.
}
func generateStructDefinition(ctx context.Context, in generateStructDefinitionInput) string {
buffer := bytes.NewBuffer(nil)
array := make([][]string, len(in.FieldMap))
names := sortFieldKeyForDao(in.FieldMap)
for index, name := range names {
field := in.FieldMap[name]
array[index] = generateStructFieldDefinition(ctx, field, in)
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
stContent := buffer.String()
// Let's do this hack of table writer for indent!
stContent = gstr.Replace(stContent, " #", "")
stContent = gstr.Replace(stContent, "` ", "`")
stContent = gstr.Replace(stContent, "``", "")
buffer.Reset()
buffer.WriteString(fmt.Sprintf("type %s struct {\n", in.StructName))
if in.IsDo {
buffer.WriteString(fmt.Sprintf("g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName))
}
buffer.WriteString(stContent)
buffer.WriteString("}")
return buffer.String()
}
// generateStructFieldForModel generates and returns the attribute definition for specified field.
func generateStructFieldDefinition(
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
) []string {
var (
err error
typeName string
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
)
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
if err != nil {
panic(err)
}
switch typeName {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
if in.StdTime {
typeName = "time.Time"
} else {
typeName = "*gtime.Time"
}
case gdb.LocalTypeInt64Bytes:
typeName = "int64"
case gdb.LocalTypeUint64Bytes:
typeName = "uint64"
// Special type handle.
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
if in.GJsonSupport {
typeName = "*gjson.Json"
} else {
typeName = "string"
}
}
var (
tagKey = "`"
result = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + typeName,
}
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
result = append(result, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
result = append(result, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
for k, v := range result {
if in.NoJsonTag {
v, _ = gregex.ReplaceString(`json:".+"`, ``, v)
}
if !in.DescriptionTag {
v, _ = gregex.ReplaceString(`description:".*"`, ``, v)
}
if in.NoModelComment {
v, _ = gregex.ReplaceString(`//.+`, ``, v)
}
result[k] = v
}
return result
}
// formatComment formats the comment string to fit the golang code without any lines.
func formatComment(comment string) string {
comment = gstr.ReplaceByArray(comment, g.SliceStr{
"\n", " ",
"\r", " ",
})
comment = gstr.Replace(comment, `\n`, " ")
comment = gstr.Trim(comment)
return comment
}
// getJsonTagFromCase call gstr.Case* function to convert the s to specified case.
func getJsonTagFromCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
}
return str
}

View File

@ -1,7 +1 @@
package consts
const (
// DoNotEditKey is used in generated files,
// which marks the files will be overwritten by CLI tool.
DoNotEditKey = `DO NOT EDIT`
)

View File

@ -1,6 +1,6 @@
package consts
const TemplateGenDaoIndexContent = `
const TemplateDaoDaoIndexContent = `
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
@ -31,16 +31,15 @@ var (
`
const TemplateGenDaoInternalContent = `
const TemplateDaoDaoInternalContent = `
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr}
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplDatetimeStr}
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)

View File

@ -2,7 +2,7 @@ package consts
const TemplateGenDaoDoContent = `
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr}
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplDatetimeStr}
// =================================================================================
package do

View File

@ -2,7 +2,7 @@ package consts
const TemplateGenDaoEntityContent = `
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr}
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplDatetimeStr}
// =================================================================================
package entity

View File

@ -1,29 +0,0 @@
package consts
const TemplateGenServiceContent = `
// ================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package {PackageName}
{Imports}
type I{StructName} interface {
{FuncDefinition}
}
var local{StructName} I{StructName}
func {StructName}() I{StructName} {
if local{StructName} == nil {
panic("implement not found for interface I{StructName}, forgot register?")
}
return local{StructName}
}
func Register{StructName}(i I{StructName}) {
local{StructName} = i
}
`

View File

@ -1,13 +0,0 @@
package consts
const TemplateGenServiceLogicContent = `
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package {PackageName}
import(
{Imports}
)
`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,44 +1,18 @@
package utils
import (
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"golang.org/x/tools/imports"
"fmt"
"github.com/gogf/gf/v2/os/gproc"
)
// GoFmt formats the source file and adds or removes import statements as necessary.
var (
// gofmtPath is the binary path of command `gofmt`.
gofmtPath = gproc.SearchBinaryPath("gofmt")
)
// GoFmt formats the source file using command `gofmt -w -s PATH`.
func GoFmt(path string) {
replaceFunc := func(path, content string) string {
res, err := imports.Process(path, []byte(content), nil)
if err != nil {
mlog.Printf(`error format "%s" go files: %v`, path, err)
return content
}
return string(res)
}
var err error
if gfile.IsFile(path) {
// File format.
if gfile.ExtName(path) != "go" {
return
}
err = gfile.ReplaceFileFunc(replaceFunc, path)
} else {
// Folder format.
err = gfile.ReplaceDirFunc(replaceFunc, path, "*.go", true)
}
if err != nil {
mlog.Printf(`error format "%s" go files: %v`, path, err)
if gofmtPath != "" {
gproc.ShellExec(fmt.Sprintf(`%s -w -s %s`, gofmtPath, path))
}
}
// IsFileDoNotEdit checks and returns whether file contains `do not edit` key.
func IsFileDoNotEdit(filePath string) bool {
if !gfile.Exists(filePath) {
return true
}
return gstr.Contains(gfile.GetContents(filePath), consts.DoNotEditKey)
}

View File

@ -14,7 +14,6 @@ import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -821,17 +820,3 @@ func (a *Array) Walk(f func(value interface{}) interface{}) *Array {
func (a *Array) IsEmpty() bool {
return a.Len() == 0
}
// DeepCopy implements interface for deep copy of current type.
func (a *Array) DeepCopy() interface{} {
if a == nil {
return nil
}
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]interface{}, len(a.array))
for i, v := range a.array {
newSlice[i] = deepcopy.Copy(v)
}
return NewArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -799,15 +799,3 @@ func (a *IntArray) Walk(f func(value int) int) *IntArray {
func (a *IntArray) IsEmpty() bool {
return a.Len() == 0
}
// DeepCopy implements interface for deep copy of current type.
func (a *IntArray) DeepCopy() interface{} {
if a == nil {
return nil
}
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]int, len(a.array))
copy(newSlice, a.array)
return NewIntArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -812,15 +812,3 @@ func (a *StrArray) Walk(f func(value string) string) *StrArray {
func (a *StrArray) IsEmpty() bool {
return a.Len() == 0
}
// DeepCopy implements interface for deep copy of current type.
func (a *StrArray) DeepCopy() interface{} {
if a == nil {
return nil
}
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]string, len(a.array))
copy(newSlice, a.array)
return NewStrArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -12,7 +12,6 @@ import (
"math"
"sort"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -797,17 +796,3 @@ func (a *SortedArray) getComparator() func(a, b interface{}) int {
}
return a.comparator
}
// DeepCopy implements interface for deep copy of current type.
func (a *SortedArray) DeepCopy() interface{} {
if a == nil {
return nil
}
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]interface{}, len(a.array))
for i, v := range a.array {
newSlice[i] = deepcopy.Copy(v)
}
return NewSortedArrayFrom(newSlice, a.comparator, a.mu.IsSafe())
}

View File

@ -744,15 +744,3 @@ func (a *SortedIntArray) getComparator() func(a, b int) int {
}
return a.comparator
}
// DeepCopy implements interface for deep copy of current type.
func (a *SortedIntArray) DeepCopy() interface{} {
if a == nil {
return nil
}
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]int, len(a.array))
copy(newSlice, a.array)
return NewSortedIntArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -757,15 +757,3 @@ func (a *SortedStrArray) getComparator() func(a, b string) int {
}
return a.comparator
}
// DeepCopy implements interface for deep copy of current type.
func (a *SortedStrArray) DeepCopy() interface{} {
if a == nil {
return nil
}
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]string, len(a.array))
copy(newSlice, a.array)
return NewSortedStrArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -46,8 +46,6 @@ func ExampleNew() {
a.Set(0, 100)
fmt.Println(a.Slice())
fmt.Println(a.At(0))
// Search item and return its index.
fmt.Println(a.Search(5))
@ -68,7 +66,6 @@ func ExampleNew() {
// false
// [0 1 2 3 4 5 6 7 8 9 10 11]
// [100 1 2 3 4 5 6 7 8 9 10 11]
// 100
// 5
// [1 2 3 4 5 6 7 8 9 10 11]
// [1 2 3 4 5 6 7 8 9 10 11]

View File

@ -54,14 +54,6 @@ func ExampleNewIntArraySize() {
// [10 20 15] 3 5
}
func ExampleNewIntArrayRange() {
s := garray.NewIntArrayRange(1, 5, 1)
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
// Output:
// [1 2 3 4 5] 5 5
}
func ExampleNewIntArrayFrom() {
s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30})
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
@ -91,12 +83,9 @@ func ExampleIntArray_Get() {
s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30})
sGet, sBool := s.Get(3)
fmt.Println(sGet, sBool)
sGet, sBool = s.Get(99)
fmt.Println(sGet, sBool)
// Output:
// 30 true
// 0 false
}
func ExampleIntArray_Set() {

View File

@ -25,24 +25,9 @@ func Test_Array_Basic(t *testing.T) {
array := garray.NewArrayFrom(expect)
array2 := garray.NewArrayFrom(expect)
array3 := garray.NewArrayFrom([]interface{}{})
array4 := garray.NewArrayRange(1, 5, 1)
t.Assert(array.Slice(), expect)
t.Assert(array.Interfaces(), expect)
err := array.Set(0, 100)
t.AssertNil(err)
err = array.Set(100, 100)
t.AssertNE(err, nil)
t.Assert(array.IsEmpty(), false)
copyArray := array.DeepCopy()
ca := copyArray.(*garray.Array)
ca.Set(0, 1)
cval, _ := ca.Get(0)
val, _ := array.Get(0)
t.AssertNE(cval, val)
array.Set(0, 100)
v, ok := array.Get(0)
t.Assert(v, 100)
@ -52,10 +37,6 @@ func Test_Array_Basic(t *testing.T) {
t.Assert(v, 1)
t.Assert(ok, true)
v, ok = array.Get(4)
t.Assert(v, nil)
t.Assert(ok, false)
t.Assert(array.Search(100), 0)
t.Assert(array3.Search(100), -1)
t.Assert(array.Contains(100), true)
@ -90,12 +71,6 @@ func Test_Array_Basic(t *testing.T) {
array.InsertAfter(6, 400)
t.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400})
t.Assert(array.Clear().Len(), 0)
err = array.InsertBefore(99, 9900)
t.AssertNE(err, nil)
err = array.InsertAfter(99, 9900)
t.AssertNE(err, nil)
t.Assert(array4.String(), "[1,2,3,4,5]")
})
}
@ -124,11 +99,6 @@ func TestArray_Unique(t *testing.T) {
array := garray.NewArrayFrom(expect)
t.Assert(array.Unique().Slice(), []interface{}{1, 2, 3, 4, 5})
})
gtest.C(t, func(t *gtest.T) {
expect := []interface{}{}
array := garray.NewArrayFrom(expect)
t.Assert(array.Unique().Slice(), []interface{}{})
})
}
func TestArray_PushAndPop(t *testing.T) {
@ -412,21 +382,6 @@ func TestArray_Rand(t *testing.T) {
t.Assert(a1.Contains(i1), true)
t.Assert(a1.Len(), 4)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewArrayFrom(a1)
rand, found := array1.Rand()
t.AssertNil(rand)
t.Assert(found, false)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewArrayFrom(a1)
rand := array1.Rands(1)
t.AssertNil(rand)
})
}
func TestArray_Shuffle(t *testing.T) {
@ -457,12 +412,6 @@ func TestArray_Join(t *testing.T) {
array1 := garray.NewArrayFrom(a1)
t.Assert(array1.Join("."), `0.1."a".\a`)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewArrayFrom(a1)
t.Assert(len(array1.Join(".")), 0)
})
}
func TestArray_String(t *testing.T) {
@ -470,8 +419,6 @@ func TestArray_String(t *testing.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
t.Assert(array1.String(), `[0,1,2,3,4,5,6]`)
array1 = nil
t.Assert(array1.String(), "")
})
}

View File

@ -63,19 +63,6 @@ func Test_IntArray_Basic(t *testing.T) {
array.InsertAfter(6, 400)
t.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 300, 4, 400})
t.Assert(array.Clear().Len(), 0)
err := array.InsertBefore(99, 300)
t.AssertNE(err, nil)
err = array.InsertAfter(99, 400)
t.AssertNE(err, nil)
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayFrom([]int{0, 1, 2, 3})
copyArray := array.DeepCopy().(*garray.IntArray)
copyArray.Set(0, 1)
cval, _ := copyArray.Get(0)
val, _ := array.Get(0)
t.AssertNE(cval, val)
})
}
@ -102,8 +89,6 @@ func TestIntArray_Unique(t *testing.T) {
expect := []int{1, 2, 3, 4, 5, 3, 2, 2, 3, 5, 5}
array := garray.NewIntArrayFrom(expect)
t.Assert(array.Unique().Slice(), []int{1, 2, 3, 4, 5})
array2 := garray.NewIntArrayFrom([]int{})
t.Assert(array2.Unique().Slice(), []int{})
})
}
@ -389,14 +374,6 @@ func TestIntArray_Rand(t *testing.T) {
v, ok := array1.Rand()
t.AssertIN(v, a1)
t.Assert(ok, true)
array2 := garray.NewIntArrayFrom([]int{})
v, ok = array2.Rand()
t.Assert(v, 0)
t.Assert(ok, false)
intSlices := array2.Rands(1)
t.Assert(intSlices, nil)
})
}
@ -443,8 +420,6 @@ func TestIntArray_String(t *testing.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
t.Assert(array1.String(), "[0,1,2,3,4,5,6]")
array1 = nil
t.Assert(array1.String(), "")
})
}

View File

@ -34,10 +34,6 @@ func Test_StrArray_Basic(t *testing.T) {
t.Assert(v, 100)
t.Assert(ok, true)
v, ok = array3.Get(0)
t.Assert(v, "")
t.Assert(ok, false)
t.Assert(array.Search("100"), 0)
t.Assert(array.Contains("100"), true)
@ -65,28 +61,12 @@ func Test_StrArray_Basic(t *testing.T) {
t.Assert(array.Clear().Len(), 0)
t.Assert(array2.Slice(), expect)
t.Assert(array3.Search("100"), -1)
err := array.InsertBefore(99, "300")
t.AssertNE(err, nil)
array.InsertAfter(99, "400")
t.AssertNE(err, nil)
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewStrArrayFrom([]string{"0", "1", "2", "3"})
copyArray := array.DeepCopy().(*garray.StrArray)
copyArray.Set(0, "1")
cval, _ := copyArray.Get(0)
val, _ := array.Get(0)
t.AssertNE(cval, val)
})
}
func TestStrArray_ContainsI(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := garray.NewStrArray()
t.Assert(s.Contains("A"), false)
s.Append("a", "b", "C")
t.Assert(s.Contains("A"), false)
t.Assert(s.Contains("a"), true)
@ -114,8 +94,6 @@ func TestStrArray_Unique(t *testing.T) {
expect := []string{"1", "1", "2", "2", "3", "3", "2", "2"}
array := garray.NewStrArrayFrom(expect)
t.Assert(array.Unique().Slice(), []string{"1", "2", "3"})
array1 := garray.NewStrArrayFrom([]string{})
t.Assert(array1.Unique().Slice(), []string{})
})
}
@ -386,13 +364,6 @@ func TestStrArray_Rand(t *testing.T) {
v, ok := array1.Rand()
t.Assert(ok, true)
t.AssertIN(v, a1)
array2 := garray.NewStrArrayFrom([]string{})
v, ok = array2.Rand()
t.Assert(ok, false)
t.Assert(v, "")
strArray := array2.Rands(1)
t.AssertNil(strArray)
})
}
@ -435,11 +406,6 @@ func TestStrArray_Join(t *testing.T) {
array1 := garray.NewStrArrayFrom(a1)
t.Assert(array1.Join("."), `0.1."a".\a`)
})
gtest.C(t, func(t *gtest.T) {
a1 := []string{}
array1 := garray.NewStrArrayFrom(a1)
t.Assert(array1.Join("."), "")
})
}
func TestStrArray_String(t *testing.T) {
@ -447,9 +413,6 @@ func TestStrArray_String(t *testing.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
t.Assert(array1.String(), `["0","1","2","3","4","5","6"]`)
array1 = nil
t.Assert(array1.String(), "")
})
}

View File

@ -61,18 +61,6 @@ func TestNewSortedArrayFromCopy(t *testing.T) {
})
}
func TestNewSortedArrayRange(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
return gconv.Int(v1) - gconv.Int(v2)
}
array1 := garray.NewSortedArrayRange(1, 5, 1, func1)
t.Assert(array1.Len(), 5)
t.Assert(array1, []interface{}{1, 2, 3, 4, 5})
})
}
func TestSortedArray_SetArray(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
@ -118,26 +106,10 @@ func TestSortedArray_Get(t *testing.T) {
v, ok = array1.Get(1)
t.Assert(v, "c")
t.Assert(ok, true)
v, ok = array1.Get(99)
t.Assert(v, nil)
t.Assert(ok, false)
})
}
func TestSortedArray_At(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
v := array1.At(2)
t.Assert(v, "f")
})
}
func TestSortedArray_Remove(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
@ -489,11 +461,6 @@ func TestSortedArray_Rand(t *testing.T) {
t.Assert(ok, true)
t.AssertIN(i1, []interface{}{"a", "d", "c"})
t.Assert(array1.Len(), 3)
array2 := garray.NewSortedArrayFrom([]interface{}{}, func1)
v, ok := array2.Rand()
t.Assert(ok, false)
t.Assert(v, nil)
})
}
@ -512,10 +479,6 @@ func TestSortedArray_Rands(t *testing.T) {
i1 = array1.Rands(4)
t.Assert(len(i1), 4)
array2 := garray.NewSortedArrayFrom([]interface{}{}, func1)
v := array2.Rands(1)
t.Assert(v, nil)
})
}
@ -535,12 +498,6 @@ func TestSortedArray_Join(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
t.Assert(array1.Join("."), `"a".0.1.\a`)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
t.Assert(array1.Join("."), "")
})
}
func TestSortedArray_String(t *testing.T) {
@ -548,9 +505,6 @@ func TestSortedArray_String(t *testing.T) {
a1 := []interface{}{0, 1, "a", "b"}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
t.Assert(array1.String(), `[0,1,"a","b"]`)
array1 = nil
t.Assert(array1.String(), "")
})
}
@ -587,11 +541,6 @@ func TestSortedArray_Unique(t *testing.T) {
array1.Unique()
t.Assert(array1.Len(), 5)
t.Assert(array1, []interface{}{1, 2, 3, 4, 5})
array2 := garray.NewSortedArrayFrom([]interface{}{}, gutil.ComparatorInt)
array2.Unique()
t.Assert(array2.Len(), 0)
t.Assert(array2, []interface{}{})
})
}
@ -929,22 +878,3 @@ func TestSortedArray_Walk(t *testing.T) {
}), g.Slice{"key-1", "key-2"})
})
}
func TestSortedArray_IsEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom([]interface{}{}, gutil.ComparatorString)
t.Assert(array.IsEmpty(), true)
})
}
func TestSortedArray_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom([]interface{}{1, 2, 3, 4, 5}, gutil.ComparatorString)
copyArray := array.DeepCopy().(*garray.SortedArray)
array.Add(6)
copyArray.Add(7)
cval, _ := copyArray.Get(5)
val, _ := array.Get(5)
t.AssertNE(cval, val)
})
}

View File

@ -19,26 +19,6 @@ import (
"github.com/gogf/gf/v2/util/gconv"
)
func TestNewSortedIntArrayComparator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1, 4, 5, 6}
array1 := garray.NewSortedIntArrayComparator(func(a, b int) int {
return a - b
}, true)
array1.Append(a1...)
t.Assert(array1.Len(), 7)
t.Assert(array1.Interfaces(), []int{0, 1, 2, 3, 4, 5, 6})
})
}
func TestNewSortedIntArrayRange(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array1 := garray.NewSortedIntArrayRange(1, 5, 1)
t.Assert(array1.Len(), 5)
t.Assert(array1.Interfaces(), []int{1, 2, 3, 4, 5})
})
}
func TestNewSortedIntArrayFrom(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1, 4, 5, 6}
@ -57,17 +37,6 @@ func TestNewSortedIntArrayFromCopy(t *testing.T) {
})
}
func TestSortedIntArray_At(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1}
array1 := garray.NewSortedIntArrayFrom(a1)
v := array1.At(1)
t.Assert(v, 1)
})
}
func TestSortedIntArray_SetArray(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3}
@ -109,10 +78,6 @@ func TestSortedIntArray_Get(t *testing.T) {
v, ok = array1.Get(3)
t.Assert(v, 5)
t.Assert(ok, true)
v, ok = array1.Get(99)
t.Assert(v, 0)
t.Assert(ok, false)
})
}
@ -329,9 +294,6 @@ func TestSortedIntArray_Join(t *testing.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
t.Assert(array1.Join("."), `1.3.5`)
array2 := garray.NewSortedIntArrayFrom([]int{})
t.Assert(array2.Join("."), "")
})
}
@ -340,9 +302,6 @@ func TestSortedIntArray_String(t *testing.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
t.Assert(array1.String(), `[1,3,5]`)
array1 = nil
t.Assert(array1.String(), "")
})
}
@ -447,11 +406,6 @@ func TestSortedIntArray_Rand(t *testing.T) {
ns1, ok := array1.Rand()
t.AssertIN(ns1, a1)
t.Assert(ok, true)
array2 := garray.NewSortedIntArrayFrom([]int{})
ns2, ok := array2.Rand()
t.Assert(ns2, 0)
t.Assert(ok, false)
})
}
@ -465,10 +419,6 @@ func TestSortedIntArray_Rands(t *testing.T) {
ns2 := array1.Rands(6)
t.Assert(len(ns2), 6)
array2 := garray.NewSortedIntArrayFrom([]int{})
val := array2.Rands(1)
t.Assert(val, nil)
})
}
@ -500,10 +450,6 @@ func TestSortedIntArray_Unique(t *testing.T) {
array1.Unique()
t.Assert(array1.Len(), 5)
t.Assert(array1, []int{1, 2, 3, 4, 5})
array2 := garray.NewSortedIntArrayFrom([]int{})
array2.Unique()
t.Assert(array2.Len(), 0)
})
}
@ -785,22 +731,3 @@ func TestSortedIntArray_Walk(t *testing.T) {
}), g.Slice{11, 12})
})
}
func TestSortedIntArray_IsEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom([]int{})
t.Assert(array.IsEmpty(), true)
})
}
func TestSortedIntArray_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom([]int{1, 2, 3, 4, 5})
copyArray := array.DeepCopy().(*garray.SortedIntArray)
array.Add(6)
copyArray.Add(7)
cval, _ := copyArray.Get(5)
val, _ := array.Get(5)
t.AssertNE(cval, val)
})
}

View File

@ -9,7 +9,6 @@
package garray_test
import (
"github.com/gogf/gf/v2/text/gstr"
"testing"
"time"
@ -20,18 +19,6 @@ import (
"github.com/gogf/gf/v2/util/gconv"
)
func TestNewSortedStrArrayComparator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
s1 := garray.NewSortedStrArrayComparator(func(a, b string) int {
return gstr.Compare(a, b)
})
s1.Add(a1...)
t.Assert(s1.Len(), 4)
t.Assert(s1, []string{"a", "b", "c", "d"})
})
}
func TestNewSortedStrArrayFrom(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
@ -71,9 +58,6 @@ func TestSortedStrArray_ContainsI(t *testing.T) {
t.Assert(s.Contains("A"), false)
t.Assert(s.Contains("a"), true)
t.Assert(s.ContainsI("A"), true)
s = garray.NewSortedStrArray()
t.Assert(s.Contains("A"), false)
})
}
@ -101,10 +85,6 @@ func TestSortedStrArray_Get(t *testing.T) {
v, ok = array1.Get(0)
t.Assert(v, "a")
t.Assert(ok, true)
v, ok = array1.Get(99)
t.Assert(v, "")
t.Assert(ok, false)
})
}
@ -381,11 +361,6 @@ func TestSortedStrArray_Rand(t *testing.T) {
v, ok := array1.Rand()
t.AssertIN(v, []string{"e", "a", "d"})
t.Assert(ok, true)
array2 := garray.NewSortedStrArrayFrom([]string{})
v, ok = array2.Rand()
t.Assert(v, "")
t.Assert(ok, false)
})
}
@ -400,10 +375,6 @@ func TestSortedStrArray_Rands(t *testing.T) {
s1 = array1.Rands(4)
t.Assert(len(s1), 4)
array2 := garray.NewSortedStrArrayFrom([]string{})
val := array2.Rands(1)
t.Assert(val, nil)
})
}
@ -420,11 +391,6 @@ func TestSortedStrArray_Join(t *testing.T) {
array1 := garray.NewSortedStrArrayFrom(a1)
t.Assert(array1.Join("."), `"b".\c.a`)
})
gtest.C(t, func(t *gtest.T) {
array1 := garray.NewSortedStrArrayFrom([]string{})
t.Assert(array1.Join("."), "")
})
}
func TestSortedStrArray_String(t *testing.T) {
@ -432,9 +398,6 @@ func TestSortedStrArray_String(t *testing.T) {
a1 := []string{"e", "a", "d"}
array1 := garray.NewSortedStrArrayFrom(a1)
t.Assert(array1.String(), `["a","d","e"]`)
array1 = nil
t.Assert(array1.String(), "")
})
}
@ -506,11 +469,6 @@ func TestSortedStrArray_Unique(t *testing.T) {
array1.Unique()
t.Assert(array1.Len(), 3)
t.Assert(array1, []string{"1", "2", "3"})
array2 := garray.NewSortedStrArrayFrom([]string{})
array2.Unique()
t.Assert(array2.Len(), 0)
t.Assert(array2, []string{})
})
}
@ -797,15 +755,3 @@ func TestSortedStrArray_Walk(t *testing.T) {
}), g.Slice{"key-1", "key-2"})
})
}
func TestSortedStrArray_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArrayFrom([]string{"a", "b", "c", "d"})
copyArray := array.DeepCopy().(*garray.SortedStrArray)
array.Add("e")
copyArray.Add("f")
cval, _ := copyArray.Get(4)
val, _ := array.Get(4)
t.AssertNE(cval, val)
})
}

View File

@ -12,7 +12,6 @@ import (
"bytes"
"container/list"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/util/gconv"
@ -547,27 +546,3 @@ func (l *List) UnmarshalValue(value interface{}) (err error) {
l.PushBacks(array)
return err
}
// DeepCopy implements interface for deep copy of current type.
func (l *List) DeepCopy() interface{} {
if l == nil {
return nil
}
l.mu.RLock()
defer l.mu.RUnlock()
if l.list == nil {
return nil
}
var (
length = l.list.Len()
values = make([]interface{}, length)
)
if length > 0 {
for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
values[i] = deepcopy.Copy(e.Value)
}
}
return NewFrom(values, l.mu.IsSafe())
}

View File

@ -755,13 +755,3 @@ func TestList_UnmarshalValue(t *testing.T) {
t.Assert(tlist.List.FrontAll(), []interface{}{1, 2, 3})
})
}
func TestList_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := NewFrom([]interface{}{1, 2, "a", `"b"`, `\c`})
copyList := l.DeepCopy()
cl := copyList.(*List)
cl.PopBack()
t.AssertNE(l.Size(), cl.Size())
})
}

View File

@ -8,14 +8,12 @@ package gmap
import (
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/util/gconv"
)
// AnyAnyMap wraps map type `map[interface{}]interface{}` and provides more map features.
type AnyAnyMap struct {
mu rwmutex.RWMutex
data map[interface{}]interface{}
@ -74,7 +72,7 @@ func (m *AnyAnyMap) Map() map[interface{}]interface{} {
return data
}
// MapCopy returns a shallow copy of the underlying data of the hash map.
// MapCopy returns a copy of the underlying data of the hash map.
func (m *AnyAnyMap) MapCopy() map[interface{}]interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
@ -499,18 +497,3 @@ func (m *AnyAnyMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *AnyAnyMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[interface{}]interface{}, len(m.data))
for k, v := range m.data {
data[k] = deepcopy.Copy(v)
}
return NewFrom(data, m.mu.IsSafe())
}

View File

@ -9,7 +9,6 @@ package gmap
import (
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -500,17 +499,3 @@ func (m *IntAnyMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *IntAnyMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[int]interface{}, len(m.data))
for k, v := range m.data {
data[k] = deepcopy.Copy(v)
}
return NewIntAnyMapFrom(data, m.mu.IsSafe())
}

View File

@ -470,17 +470,3 @@ func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *IntIntMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[int]int, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewIntIntMapFrom(data, m.mu.IsSafe())
}

View File

@ -470,17 +470,3 @@ func (m *IntStrMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *IntStrMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[int]string, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewIntStrMapFrom(data, m.mu.IsSafe())
}

View File

@ -9,7 +9,6 @@ package gmap
import (
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -486,17 +485,3 @@ func (m *StrAnyMap) UnmarshalValue(value interface{}) (err error) {
m.data = gconv.Map(value)
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *StrAnyMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[string]interface{}, len(m.data))
for k, v := range m.data {
data[k] = deepcopy.Copy(v)
}
return NewStrAnyMapFrom(data, m.mu.IsSafe())
}

View File

@ -474,17 +474,3 @@ func (m *StrIntMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *StrIntMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[string]int, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewStrIntMapFrom(data, m.mu.IsSafe())
}

View File

@ -463,17 +463,3 @@ func (m *StrStrMap) UnmarshalValue(value interface{}) (err error) {
m.data = gconv.MapStrStr(value)
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *StrStrMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[string]string, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewStrStrMapFrom(data, m.mu.IsSafe())
}

View File

@ -12,7 +12,6 @@ import (
"github.com/gogf/gf/v2/container/glist"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -591,22 +590,3 @@ func (m *ListMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *ListMap) DeepCopy() interface{} {
if m == nil {
return nil
}
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[interface{}]interface{}, len(m.data))
if m.list != nil {
var node *gListMapNode
m.list.IteratorAsc(func(e *glist.Element) bool {
node = e.Value.(*gListMapNode)
data[node.key] = deepcopy.Copy(node.value)
return true
})
}
return NewListMapFrom(data, m.mu.IsSafe())
}

View File

@ -602,12 +602,8 @@ func ExampleAnyAnyMap_String() {
fmt.Println(m.String())
var m1 *gmap.Map = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":"v1"}
// 0
}
func ExampleAnyAnyMap_MarshalJSON() {

View File

@ -601,12 +601,8 @@ func ExampleIntAnyMap_String() {
fmt.Println(m.String())
var m1 *gmap.IntAnyMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"1":"v1"}
// 0
}
func ExampleIntAnyMap_MarshalJSON() {

View File

@ -529,12 +529,8 @@ func ExampleIntIntMap_String() {
fmt.Println(m.String())
var m1 *gmap.IntIntMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"1":1}
// 0
}
func ExampleIntIntMap_MarshalJSON() {

View File

@ -599,12 +599,8 @@ func ExampleStrAnyMap_String() {
fmt.Println(m.String())
var m1 *gmap.StrAnyMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":"v1"}
// 0
}
func ExampleStrAnyMap_MarshalJSON() {

View File

@ -8,10 +8,11 @@ package gmap_test
import (
"fmt"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/container/gmap"
)
func ExampleStrIntMap_Iterator() {
@ -534,12 +535,8 @@ func ExampleStrIntMap_String() {
fmt.Println(m.String())
var m1 *gmap.StrIntMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":1}
// 0
}
func ExampleStrIntMap_MarshalJSON() {

View File

@ -531,12 +531,8 @@ func ExampleStrStrMap_String() {
fmt.Println(m.String())
var m1 *gmap.StrStrMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":"v1"}
// 0
}
func ExampleStrStrMap_MarshalJSON() {

View File

@ -90,7 +90,7 @@ func ExampleNewFrom() {
}
func ExampleNewHashMap() {
m := gmap.NewHashMap()
m := gmap.New()
m.Set("key1", "val1")
fmt.Println(m)
@ -105,7 +105,7 @@ func ExampleNewHashMapFrom() {
m.Set("key1", "val1")
fmt.Println(m)
n := gmap.NewHashMapFrom(m.MapCopy(), true)
n := gmap.NewFrom(m.MapCopy(), true)
fmt.Println(n)
// Output:

View File

@ -171,9 +171,6 @@ func Test_AnyAnyMap_Merge(t *testing.T) {
m2.Set(2, "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{1: 1, 2: "2"})
m3 := gmap.NewAnyAnyMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -299,10 +296,6 @@ func Test_AnyAnyMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.AssertNil(k3)
t.AssertNil(v3)
})
}
@ -334,11 +327,6 @@ func Test_AnyAnyMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -377,17 +365,3 @@ func TestAnyAnyMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), "v2")
})
}
func Test_AnyAnyMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
"k1": "v1",
"k2": "v2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.AnyAnyMap)
n.Set("k1", "val1")
t.AssertNE(m.Get("k1"), n.Get("k1"))
})
}

View File

@ -82,12 +82,6 @@ func Test_IntAnyMap_Basic(t *testing.T) {
m2 := gmap.NewIntAnyMapFrom(map[int]interface{}{1: 1, 2: "2"})
t.Assert(m2.Map(), map[int]interface{}{1: 1, 2: "2"})
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap(true)
m.Set(1, 1)
t.Assert(m.Map(), map[int]interface{}{1: 1})
})
}
func Test_IntAnyMap_Set_Fun(t *testing.T) {
@ -177,9 +171,6 @@ func Test_IntAnyMap_Merge(t *testing.T) {
m2.Set(2, "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[int]interface{}{1: 1, 2: "2"})
m3 := gmap.NewIntAnyMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -280,10 +271,6 @@ func Test_IntAnyMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, 0)
t.AssertNil(v3)
})
}
@ -315,11 +302,6 @@ func Test_IntAnyMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -358,17 +340,3 @@ func TestIntAnyMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get(2), "v2")
})
}
func Test_IntAnyMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMapFrom(g.MapIntAny{
1: "v1",
2: "v2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.IntAnyMap)
n.Set(1, "val1")
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -86,12 +86,6 @@ func Test_IntIntMap_Basic(t *testing.T) {
m2 := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2})
t.Assert(m2.Map(), map[int]int{1: 1, 2: 2})
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap(true)
m.Set(1, 1)
t.Assert(m.Map(), map[int]int{1: 1})
})
}
func Test_IntIntMap_Set_Fun(t *testing.T) {
@ -108,11 +102,6 @@ func Test_IntIntMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock(2, getInt), false)
t.Assert(m.SetIfNotExistFuncLock(4, getInt), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(nil)
t.Assert(m.GetOrSetFuncLock(1, getInt), getInt())
})
}
func Test_IntIntMap_Batch(t *testing.T) {
@ -188,9 +177,6 @@ func Test_IntIntMap_Merge(t *testing.T) {
m2.Set(2, 2)
m1.Merge(m2)
t.Assert(m1.Map(), map[int]int{1: 1, 2: 2})
m3 := gmap.NewIntIntMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -291,10 +277,6 @@ func Test_IntIntMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, 0)
t.Assert(v3, 0)
})
}
@ -326,11 +308,6 @@ func Test_IntIntMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -369,17 +346,3 @@ func TestIntIntMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get(2), "2")
})
}
func Test_IntIntMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(g.MapIntInt{
1: 1,
2: 2,
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.IntIntMap)
n.Set(1, 2)
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -63,7 +63,6 @@ func Test_IntStrMap_Basic(t *testing.T) {
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
t.Assert(m.GetOrSet(1, "a"), "a")
t.Assert(m.GetOrSet(2, "b"), "b")
t.Assert(m.SetIfNotExist(2, "b"), false)
@ -91,29 +90,6 @@ func Test_IntStrMap_Basic(t *testing.T) {
m2 := gmap.NewIntStrMapFrom(map[int]string{1: "a", 2: "b"})
t.Assert(m2.Map(), map[int]string{1: "a", 2: "b"})
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap(true)
m.Set(1, "val1")
t.Assert(m.Map(), map[int]string{1: "val1"})
})
}
func TestIntStrMap_MapStrAny(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.GetOrSetFunc(1, getStr)
m.GetOrSetFuncLock(2, getStr)
t.Assert(m.MapStrAny(), g.MapStrAny{"1": "z", "2": "z"})
})
}
func TestIntStrMap_Sets(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(nil)
m.Sets(g.MapIntStr{1: "z", 2: "z"})
t.Assert(len(m.Map()), 2)
})
}
func Test_IntStrMap_Set_Fun(t *testing.T) {
@ -121,8 +97,6 @@ func Test_IntStrMap_Set_Fun(t *testing.T) {
m := gmap.NewIntStrMap()
m.GetOrSetFunc(1, getStr)
m.GetOrSetFuncLock(2, getStr)
t.Assert(m.GetOrSetFunc(1, getStr), "z")
t.Assert(m.GetOrSetFuncLock(2, getStr), "z")
t.Assert(m.Get(1), "z")
t.Assert(m.Get(2), "z")
t.Assert(m.SetIfNotExistFunc(1, getStr), false)
@ -131,16 +105,6 @@ func Test_IntStrMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock(2, getStr), false)
t.Assert(m.SetIfNotExistFuncLock(4, getStr), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(nil)
t.Assert(m.GetOrSetFuncLock(1, getStr), "z")
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(nil)
t.Assert(m.SetIfNotExistFuncLock(1, getStr), true)
})
}
func Test_IntStrMap_Batch(t *testing.T) {
@ -212,10 +176,6 @@ func Test_IntStrMap_Merge(t *testing.T) {
m2.Set(2, "b")
m1.Merge(m2)
t.Assert(m1.Map(), map[int]string{1: "a", 2: "b"})
m3 := gmap.NewIntStrMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -315,10 +275,6 @@ func Test_IntStrMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, 0)
t.Assert(v3, "")
})
}
@ -350,11 +306,6 @@ func Test_IntStrMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -393,55 +344,3 @@ func TestIntStrMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get(2), "v2")
})
}
func TestIntStrMap_Replace(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "v1",
2: "v2",
3: "v3",
})
t.Assert(m.Get(1), "v1")
t.Assert(m.Get(2), "v2")
t.Assert(m.Get(3), "v3")
m.Replace(g.MapIntStr{
1: "v2",
2: "v3",
3: "v1",
})
t.Assert(m.Get(1), "v2")
t.Assert(m.Get(2), "v3")
t.Assert(m.Get(3), "v1")
})
}
func TestIntStrMap_String(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "v1",
2: "v2",
3: "v3",
})
t.Assert(m.String(), "{\"1\":\"v1\",\"2\":\"v2\",\"3\":\"v3\"}")
m = nil
t.Assert(len(m.String()), 0)
})
}
func Test_IntStrMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "val1",
2: "val2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.IntStrMap)
n.Set(1, "v1")
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -169,10 +169,6 @@ func Test_StrAnyMap_Merge(t *testing.T) {
m2.Set("b", "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[string]interface{}{"a": 1, "b": "2"})
m3 := gmap.NewStrAnyMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -287,10 +283,6 @@ func Test_StrAnyMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, "")
t.Assert(v3, "")
})
}
@ -322,11 +314,6 @@ func Test_StrAnyMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -365,17 +352,3 @@ func TestStrAnyMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), "v2")
})
}
func Test_StrAnyMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMapFrom(g.MapStrAny{
"key1": "val1",
"key2": "val2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.StrAnyMap)
n.Set("key1", "v1")
t.AssertNE(m.Get("key1"), n.Get("key1"))
})
}

View File

@ -100,11 +100,6 @@ func Test_StrIntMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock("b", getInt), false)
t.Assert(m.SetIfNotExistFuncLock("d", getInt), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMapFrom(nil)
t.Assert(m.GetOrSetFuncLock("a", getInt), 123)
})
}
func Test_StrIntMap_Batch(t *testing.T) {
@ -178,9 +173,6 @@ func Test_StrIntMap_Merge(t *testing.T) {
m2.Set("b", 2)
m1.Merge(m2)
t.Assert(m1.Map(), map[string]int{"a": 1, "b": 2})
m3 := gmap.NewStrIntMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -295,10 +287,6 @@ func Test_StrIntMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, "")
t.Assert(v3, 0)
})
}
@ -330,11 +318,6 @@ func Test_StrIntMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -373,17 +356,3 @@ func TestStrIntMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), 2)
})
}
func Test_StrIntMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMapFrom(g.MapStrInt{
"key1": 1,
"key2": 2,
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.StrIntMap)
n.Set("key1", 2)
t.AssertNE(m.Get("key1"), n.Get("key1"))
})
}

View File

@ -98,12 +98,6 @@ func Test_StrStrMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock("b", getStr), false)
t.Assert(m.SetIfNotExistFuncLock("d", getStr), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMapFrom(nil)
t.Assert(m.GetOrSetFuncLock("b", getStr), "z")
})
}
func Test_StrStrMap_Batch(t *testing.T) {
@ -176,9 +170,6 @@ func Test_StrStrMap_Merge(t *testing.T) {
m2.Set("b", "b")
m1.Merge(m2)
t.Assert(m1.Map(), map[string]string{"a": "a", "b": "b"})
m3 := gmap.NewStrStrMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -293,10 +284,6 @@ func Test_StrStrMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, "")
t.Assert(v3, "")
})
}
@ -328,11 +315,6 @@ func Test_StrStrMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -371,17 +353,3 @@ func TestStrStrMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), "v2")
})
}
func Test_StrStrMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMapFrom(g.MapStrStr{
"key1": "val1",
"key2": "val2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.StrStrMap)
n.Set("key1", "v1")
t.AssertNE(m.Get("key1"), n.Get("key1"))
})
}

View File

@ -154,9 +154,6 @@ func Test_ListMap_Basic_Merge(t *testing.T) {
m2.Set("key2", "val2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
m3 := gmap.NewListMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -269,10 +266,6 @@ func Test_ListMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.AssertNil(k3)
t.AssertNil(v3)
})
}
@ -304,11 +297,6 @@ func Test_ListMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -347,44 +335,3 @@ func TestListMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("2"), "v2")
})
}
func TestListMap_String(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "")
m.Set(2, "2")
t.Assert(m.String(), "{\"1\":\"\",\"2\":\"2\"}")
m1 := gmap.NewListMapFrom(nil)
t.Assert(m1.String(), "{}")
})
}
func TestListMap_MarshalJSON(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "")
m.Set(2, "2")
res, err := m.MarshalJSON()
t.Assert(res, []byte("{\"1\":\"\",\"2\":\"2\"}"))
t.AssertNil(err)
m1 := gmap.NewListMapFrom(nil)
res, err = m1.MarshalJSON()
t.Assert(res, []byte("{}"))
t.AssertNil(err)
})
}
func TestListMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "1")
m.Set(2, "2")
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.ListMap)
n.Set(1, "val1")
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -85,7 +85,6 @@ func Test_Gpool(t *testing.T) {
assertIndex = 0
p2.Close()
time.Sleep(3 * time.Second)
t.AssertNE(p2.Put(1), nil)
})
gtest.C(t, func(t *gtest.T) {
@ -96,27 +95,4 @@ func Test_Gpool(t *testing.T) {
t.Assert(err3, errors.New("pool is empty"))
t.Assert(v3, nil)
})
gtest.C(t, func(t *gtest.T) {
p := gpool.New(time.Millisecond*200, nil, func(i interface{}) {})
p.Put(1)
time.Sleep(time.Millisecond * 100)
p.Put(2)
time.Sleep(time.Millisecond * 200)
})
gtest.C(t, func(t *gtest.T) {
s := make([]int, 0)
p := gpool.New(time.Millisecond*200, nil, func(i interface{}) {
s = append(s, i.(int))
})
for i := 0; i < 5; i++ {
p.Put(i)
time.Sleep(time.Millisecond * 50)
}
val, err := p.Get()
t.Assert(val, 2)
t.AssertNil(err)
t.Assert(p.Size(), 2)
})
}

View File

@ -62,12 +62,4 @@ func TestQueue_Close(t *testing.T) {
t.Assert(q1.Len(), 2)
q1.Close()
})
gtest.C(t, func(t *gtest.T) {
q1 := gqueue.New(2)
q1.Push(1)
q1.Push(2)
time.Sleep(time.Millisecond)
t.Assert(q1.Len(), 2)
q1.Close()
})
}

View File

@ -183,43 +183,3 @@ func Test_Issue1394(t *testing.T) {
})
}
func TestRing_RLockIteratorNext(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
r := gring.New(10)
for i := 0; i < 10; i++ {
r.Set(i).Next()
}
iterVal := 0
r.RLockIteratorNext(func(value interface{}) bool {
if value.(int) == 0 {
iterVal = value.(int)
return false
}
return true
})
t.Assert(iterVal, 0)
})
}
func TestRing_RLockIteratorPrev(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
r := gring.New(10)
for i := 0; i < 10; i++ {
r.Set(i).Next()
}
iterVal := 0
r.RLockIteratorPrev(func(value interface{}) bool {
if value.(int) == 0 {
iterVal = value.(int)
return false
}
return true
})
t.Assert(iterVal, 0)
})
}

View File

@ -510,17 +510,3 @@ func (set *Set) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (set *Set) DeepCopy() interface{} {
if set == nil {
return nil
}
set.mu.RLock()
defer set.mu.RUnlock()
data := make([]interface{}, 0)
for k, _ := range set.data {
data = append(data, k)
}
return NewFrom(data, set.mu.IsSafe())
}

View File

@ -469,21 +469,3 @@ func (set *IntSet) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (set *IntSet) DeepCopy() interface{} {
if set == nil {
return nil
}
set.mu.RLock()
defer set.mu.RUnlock()
var (
slice = make([]int, len(set.data))
index = 0
)
for k := range set.data {
slice[index] = k
index++
}
return NewIntSetFrom(slice, set.mu.IsSafe())
}

View File

@ -228,7 +228,6 @@ func (set *StrSet) String() string {
i = 0
buffer = bytes.NewBuffer(nil)
)
buffer.WriteByte('[')
for k, _ := range set.data {
buffer.WriteString(`"` + gstr.QuoteMeta(k, `"\`) + `"`)
if i != l-1 {
@ -236,7 +235,6 @@ func (set *StrSet) String() string {
}
i++
}
buffer.WriteByte(']')
return buffer.String()
}
@ -499,21 +497,3 @@ func (set *StrSet) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (set *StrSet) DeepCopy() interface{} {
if set == nil {
return nil
}
set.mu.RLock()
defer set.mu.RUnlock()
var (
slice = make([]string, len(set.data))
index = 0
)
for k := range set.data {
slice[index] = k
index++
}
return NewStrSetFrom(slice, set.mu.IsSafe())
}

View File

@ -126,16 +126,11 @@ func TestSet_Equal(t *testing.T) {
s1 := gset.NewSet()
s2 := gset.NewSet()
s3 := gset.NewSet()
s4 := gset.NewSet()
s1.Add(1, 2, 3)
s2.Add(1, 2, 3)
s3.Add(1, 2, 3, 4)
s4.Add(4, 5, 6)
t.Assert(s1.Equal(s2), true)
t.Assert(s1.Equal(s3), false)
t.Assert(s1.Equal(s4), false)
s5 := s1
t.Assert(s1.Equal(s5), true)
})
}
@ -152,9 +147,6 @@ func TestSet_IsSubsetOf(t *testing.T) {
t.Assert(s1.IsSubsetOf(s3), true)
t.Assert(s2.IsSubsetOf(s1), false)
t.Assert(s3.IsSubsetOf(s2), false)
s4 := s1
t.Assert(s1.IsSubsetOf(s4), true)
})
}
@ -183,13 +175,6 @@ func TestSet_Diff(t *testing.T) {
t.Assert(s3.Contains(2), true)
t.Assert(s3.Contains(3), false)
t.Assert(s3.Contains(4), false)
s4 := s1
s5 := s1.Diff(s2, s4)
t.Assert(s5.Contains(1), true)
t.Assert(s5.Contains(2), true)
t.Assert(s5.Contains(3), false)
t.Assert(s5.Contains(4), false)
})
}
@ -262,10 +247,6 @@ func TestSet_Join(t *testing.T) {
t.Assert(strings.Contains(str1, `\c`), true)
t.Assert(strings.Contains(str1, `a`), true)
})
gtest.C(t, func(t *gtest.T) {
s1 := gset.Set{}
t.Assert(s1.Join(","), "")
})
}
func TestSet_String(t *testing.T) {
@ -276,13 +257,6 @@ func TestSet_String(t *testing.T) {
t.Assert(strings.Contains(str1, "["), true)
t.Assert(strings.Contains(str1, "]"), true)
t.Assert(strings.Contains(str1, "a2"), true)
s1 = nil
t.Assert(s1.String(), "")
s2 := gset.New()
s2.Add(1)
t.Assert(s2.String(), "[1]")
})
}
@ -311,7 +285,6 @@ func TestSet_Sum(t *testing.T) {
func TestSet_Pop(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
t.Assert(s.Pop(), nil)
s.Add(1, 2, 3, 4)
t.Assert(s.Size(), 4)
t.AssertIN(s.Pop(), []int{1, 2, 3, 4})
@ -381,7 +354,6 @@ func TestSet_AddIfNotExist(t *testing.T) {
t.Assert(s.AddIfNotExist(2), true)
t.Assert(s.Contains(2), true)
t.Assert(s.AddIfNotExist(2), false)
t.Assert(s.AddIfNotExist(nil), false)
t.Assert(s.Contains(2), true)
})
}
@ -398,7 +370,6 @@ func TestSet_AddIfNotExistFunc(t *testing.T) {
t.Assert(s.Contains(2), true)
t.Assert(s.AddIfNotExistFunc(2, func() bool { return true }), false)
t.Assert(s.Contains(2), true)
t.Assert(s.AddIfNotExistFunc(nil, func() bool { return false }), false)
})
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
@ -415,10 +386,6 @@ func TestSet_AddIfNotExistFunc(t *testing.T) {
s.Add(1)
wg.Wait()
})
gtest.C(t, func(t *gtest.T) {
s := gset.Set{}
t.Assert(s.AddIfNotExistFunc(1, func() bool { return true }), true)
})
}
func TestSet_Walk(t *testing.T) {
@ -457,12 +424,6 @@ func TestSet_AddIfNotExistFuncLock(t *testing.T) {
}()
wg.Wait()
})
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
t.Assert(s.AddIfNotExistFuncLock(nil, func() bool { return true }), false)
s1 := gset.Set{}
t.Assert(s1.AddIfNotExistFuncLock(1, func() bool { return true }), true)
})
}
func TestSet_UnmarshalValue(t *testing.T) {
@ -501,18 +462,3 @@ func TestSet_UnmarshalValue(t *testing.T) {
t.Assert(v.Set.Contains("k4"), false)
})
}
func TestSet_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
set := gset.New()
set.Add(1, 2, 3)
copySet := set.DeepCopy().(*gset.Set)
copySet.Add(4)
t.AssertNE(set.Size(), copySet.Size())
t.AssertNE(set.String(), copySet.String())
set = nil
t.AssertNil(set.DeepCopy())
})
}

View File

@ -106,16 +106,11 @@ func TestIntSet_Equal(t *testing.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
s3 := gset.NewIntSet()
s4 := gset.NewIntSet()
s1.Add(1, 2, 3)
s2.Add(1, 2, 3)
s3.Add(1, 2, 3, 4)
s4.Add(4, 5, 6)
t.Assert(s1.Equal(s2), true)
t.Assert(s1.Equal(s3), false)
t.Assert(s1.Equal(s4), false)
s5 := s1
t.Assert(s1.Equal(s5), true)
})
}
@ -132,9 +127,6 @@ func TestIntSet_IsSubsetOf(t *testing.T) {
t.Assert(s1.IsSubsetOf(s3), true)
t.Assert(s2.IsSubsetOf(s1), false)
t.Assert(s3.IsSubsetOf(s2), false)
s4 := s1
t.Assert(s1.IsSubsetOf(s4), true)
})
}
@ -163,13 +155,6 @@ func TestIntSet_Diff(t *testing.T) {
t.Assert(s3.Contains(2), true)
t.Assert(s3.Contains(3), false)
t.Assert(s3.Contains(4), false)
s4 := s1
s5 := s1.Diff(s2, s4)
t.Assert(s5.Contains(1), true)
t.Assert(s5.Contains(2), true)
t.Assert(s5.Contains(3), false)
t.Assert(s5.Contains(4), false)
})
}
@ -227,7 +212,6 @@ func TestIntSet_Merge(t *testing.T) {
func TestIntSet_Join(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
t.Assert(s1.Join(","), "")
s1.Add(1, 2, 3)
s3 := s1.Join(",")
t.Assert(strings.Contains(s3, "1"), true)
@ -246,8 +230,6 @@ func TestIntSet_String(t *testing.T) {
t.Assert(strings.Contains(s3, "1"), true)
t.Assert(strings.Contains(s3, "2"), true)
t.Assert(strings.Contains(s3, "3"), true)
s1 = nil
t.Assert(s1.String(), "")
})
}
@ -266,7 +248,6 @@ func TestIntSet_Sum(t *testing.T) {
func TestIntSet_Pop(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet()
t.Assert(s.Pop(), 0)
s.Add(4, 2, 3)
t.Assert(s.Size(), 3)
t.AssertIN(s.Pop(), []int{4, 2, 3})
@ -310,10 +291,6 @@ func TestIntSet_AddIfNotExist(t *testing.T) {
t.Assert(s.AddIfNotExist(2), false)
t.Assert(s.Contains(2), true)
})
gtest.C(t, func(t *gtest.T) {
s := gset.IntSet{}
t.Assert(s.AddIfNotExist(1), true)
})
}
func TestIntSet_AddIfNotExistFunc(t *testing.T) {
@ -344,10 +321,6 @@ func TestIntSet_AddIfNotExistFunc(t *testing.T) {
s.Add(1)
wg.Wait()
})
gtest.C(t, func(t *gtest.T) {
s := gset.IntSet{}
t.Assert(s.AddIfNotExistFunc(1, func() bool { return true }), true)
})
}
func TestIntSet_AddIfNotExistFuncLock(t *testing.T) {
@ -373,10 +346,6 @@ func TestIntSet_AddIfNotExistFuncLock(t *testing.T) {
}()
wg.Wait()
})
gtest.C(t, func(t *gtest.T) {
s := gset.IntSet{}
t.Assert(s.AddIfNotExistFuncLock(1, func() bool { return true }), true)
})
}
func TestIntSet_Json(t *testing.T) {
@ -457,18 +426,3 @@ func TestIntSet_UnmarshalValue(t *testing.T) {
t.Assert(v.Set.Contains(4), false)
})
}
func TestIntSet_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
set := gset.NewIntSet()
set.Add(1, 2, 3)
copySet := set.DeepCopy().(*gset.IntSet)
copySet.Add(4)
t.AssertNE(set.Size(), copySet.Size())
t.AssertNE(set.String(), copySet.String())
set = nil
t.AssertNil(set.DeepCopy())
})
}

View File

@ -69,7 +69,6 @@ func TestStrSet_ContainsI(t *testing.T) {
t.Assert(s.Contains("A"), false)
t.Assert(s.Contains("a"), true)
t.Assert(s.ContainsI("A"), true)
t.Assert(s.ContainsI("d"), false)
})
}
@ -117,16 +116,11 @@ func TestStrSet_Equal(t *testing.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
s3 := gset.NewStrSet()
s4 := gset.NewStrSet()
s1.Add("1", "2", "3")
s2.Add("1", "2", "3")
s3.Add("1", "2", "3", "4")
s4.Add("4", "5", "6")
t.Assert(s1.Equal(s2), true)
t.Assert(s1.Equal(s3), false)
t.Assert(s1.Equal(s4), false)
s5 := s1
t.Assert(s1.Equal(s5), true)
})
}
@ -143,9 +137,6 @@ func TestStrSet_IsSubsetOf(t *testing.T) {
t.Assert(s1.IsSubsetOf(s3), true)
t.Assert(s2.IsSubsetOf(s1), false)
t.Assert(s3.IsSubsetOf(s2), false)
s4 := s1
t.Assert(s1.IsSubsetOf(s4), true)
})
}
@ -174,13 +165,6 @@ func TestStrSet_Diff(t *testing.T) {
t.Assert(s3.Contains("2"), true)
t.Assert(s3.Contains("3"), false)
t.Assert(s3.Contains("4"), false)
s4 := s1
s5 := s1.Diff(s2, s4)
t.Assert(s5.Contains("1"), true)
t.Assert(s5.Contains("2"), true)
t.Assert(s5.Contains("3"), false)
t.Assert(s5.Contains("4"), false)
})
}
@ -255,7 +239,6 @@ func TestStrSet_Join(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
t.Assert(s1.Join(","), "")
s1.Add("a", `"b"`, `\c`)
str1 := s1.Join(",")
t.Assert(strings.Contains(str1, `"b"`), true)
@ -270,8 +253,6 @@ func TestStrSet_String(t *testing.T) {
str1 := s1.String()
t.Assert(strings.Contains(str1, "b"), true)
t.Assert(strings.Contains(str1, "d"), false)
s1 = nil
t.Assert(s1.String(), "")
})
gtest.C(t, func(t *gtest.T) {
@ -319,9 +300,6 @@ func TestStrSet_Pop(t *testing.T) {
t.Assert(s.Size(), 3)
t.AssertIN(s.Pop(), a)
t.Assert(s.Size(), 2)
s1 := gset.StrSet{}
t.Assert(s1.Pop(), "")
})
}
@ -359,10 +337,6 @@ func TestStrSet_AddIfNotExist(t *testing.T) {
t.Assert(s.AddIfNotExist("2"), false)
t.Assert(s.Contains("2"), true)
})
gtest.C(t, func(t *gtest.T) {
s := gset.StrSet{}
t.Assert(s.AddIfNotExist("1"), true)
})
}
func TestStrSet_AddIfNotExistFunc(t *testing.T) {
@ -393,10 +367,6 @@ func TestStrSet_AddIfNotExistFunc(t *testing.T) {
s.Add("1")
wg.Wait()
})
gtest.C(t, func(t *gtest.T) {
s := gset.StrSet{}
t.Assert(s.AddIfNotExistFunc("1", func() bool { return true }), true)
})
}
func TestStrSet_AddIfNotExistFuncLock(t *testing.T) {
@ -422,10 +392,6 @@ func TestStrSet_AddIfNotExistFuncLock(t *testing.T) {
}()
wg.Wait()
})
gtest.C(t, func(t *gtest.T) {
s := gset.StrSet{}
t.Assert(s.AddIfNotExistFuncLock("1", func() bool { return true }), true)
})
}
func TestStrSet_Json(t *testing.T) {
@ -511,18 +477,3 @@ func TestStrSet_UnmarshalValue(t *testing.T) {
t.Assert(v.Set.Contains("4"), false)
})
}
func TestStrSet_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
set := gset.NewStrSet()
set.Add("1", "2", "3")
copySet := set.DeepCopy().(*gset.StrSet)
copySet.Add("4")
t.AssertNE(set.Size(), copySet.Size())
t.AssertNE(set.String(), copySet.String())
set = nil
t.AssertNil(set.DeepCopy())
})
}

View File

@ -96,11 +96,3 @@ func (v *Bool) UnmarshalValue(value interface{}) error {
v.Set(gconv.Bool(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Bool) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewBool(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Byte) UnmarshalValue(value interface{}) error {
v.Set(gconv.Byte(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Byte) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewByte(v.Val())
}

View File

@ -30,7 +30,7 @@ func NewBytes(value ...[]byte) *Bytes {
return t
}
// Clone clones and returns a new shallow copy object for []byte type.
// Clone clones and returns a new concurrent-safe object for []byte type.
func (v *Bytes) Clone() *Bytes {
return NewBytes(v.Val())
}
@ -83,14 +83,3 @@ func (v *Bytes) UnmarshalValue(value interface{}) error {
v.Set(gconv.Bytes(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Bytes) DeepCopy() interface{} {
if v == nil {
return nil
}
oldBytes := v.Val()
newBytes := make([]byte, len(oldBytes))
copy(newBytes, oldBytes)
return NewBytes(newBytes)
}

View File

@ -87,11 +87,3 @@ func (v *Float32) UnmarshalValue(value interface{}) error {
v.Set(gconv.Float32(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Float32) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewFloat32(v.Val())
}

View File

@ -87,11 +87,3 @@ func (v *Float64) UnmarshalValue(value interface{}) error {
v.Set(gconv.Float64(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Float64) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewFloat64(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Int) UnmarshalValue(value interface{}) error {
v.Set(gconv.Int(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Int) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewInt(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Int32) UnmarshalValue(value interface{}) error {
v.Set(gconv.Int32(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Int32) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewInt32(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Int64) UnmarshalValue(value interface{}) error {
v.Set(gconv.Int64(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Int64) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewInt64(v.Val())
}

View File

@ -9,7 +9,6 @@ package gtype
import (
"sync/atomic"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
)
@ -72,11 +71,3 @@ func (v *Interface) UnmarshalValue(value interface{}) error {
v.Set(value)
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Interface) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewInterface(deepcopy.Copy(v.Val()))
}

View File

@ -8,9 +8,8 @@ package gtype
import (
"bytes"
"sync/atomic"
"github.com/gogf/gf/v2/util/gconv"
"sync/atomic"
)
// String is a struct for concurrent-safe operation for type string.
@ -70,11 +69,3 @@ func (v *String) UnmarshalValue(value interface{}) error {
v.Set(gconv.String(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *String) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewString(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Uint) UnmarshalValue(value interface{}) error {
v.Set(gconv.Uint(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Uint) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewUint(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Uint32) UnmarshalValue(value interface{}) error {
v.Set(gconv.Uint32(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Uint32) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewUint32(v.Val())
}

View File

@ -75,11 +75,3 @@ func (v *Uint64) UnmarshalValue(value interface{}) error {
v.Set(gconv.Uint64(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Uint64) DeepCopy() interface{} {
if v == nil {
return nil
}
return NewUint64(v.Val())
}

View File

@ -27,19 +27,7 @@ func Test_Bool(t *testing.T) {
t.AssertEQ(iClone1.Set(true), false)
t.AssertEQ(iClone1.Val(), true)
t.AssertEQ(iClone1.Cas(false, true), false)
t.AssertEQ(iClone1.String(), "true")
t.AssertEQ(iClone1.Cas(true, false), true)
t.AssertEQ(iClone1.String(), "false")
copyVal := i1.DeepCopy()
iClone.Set(true)
t.AssertNE(copyVal, iClone.Val())
iClone = nil
copyVal = iClone.DeepCopy()
t.AssertNil(copyVal)
// empty param test
// 空参测试
i2 := gtype.NewBool()
t.AssertEQ(i2.Val(), false)
})

View File

@ -34,21 +34,9 @@ func Test_Byte(t *testing.T) {
wg.Wait()
t.AssertEQ(byte(addTimes), i.Val())
// empty param test
// 空参测试
i1 := gtype.NewByte()
t.AssertEQ(i1.Val(), byte(0))
i2 := gtype.NewByte(byte(64))
t.AssertEQ(i2.String(), "64")
t.AssertEQ(i2.Cas(byte(63), byte(65)), false)
t.AssertEQ(i2.Cas(byte(64), byte(65)), true)
copyVal := i2.DeepCopy()
i2.Set(byte(65))
t.AssertNE(copyVal, iClone.Val())
i2 = nil
copyVal = i2.DeepCopy()
t.AssertNil(copyVal)
})
}

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