diff --git a/.github/workflows/ci-main.sh b/.github/workflows/ci-main.sh index 58a9f9adf..f32f34f3a 100644 --- a/.github/workflows/ci-main.sh +++ b/.github/workflows/ci-main.sh @@ -7,27 +7,25 @@ for file in `find . -name go.mod`; do dirpath=$(dirname $file) echo $dirpath + # ignore mssql tests as its docker service failed + # TODO remove this ignoring codes after the mssql docker service OK + if [ "mssql" = $(basename $dirpath) ]; then + continue 1 + fi + if [[ $file =~ "/testdata/" ]]; then echo "ignore testdata path $file" continue 1 fi - # package kuhecm needs golang >= v1.19 + # package kuhecm was moved to sub ci procedure. if [ "kubecm" = $(basename $dirpath) ]; then continue 1 - if ! go version|grep -qE "go1.[2-9][0-9]"; then - echo "ignore kubecm as go version: $(go version)" - continue 1 - fi fi # package consul needs golang >= v1.19 if [ "consul" = $(basename $dirpath) ]; then continue 1 - if ! go version|grep -qE "go1.[2-9][0-9]"; then - echo "ignore consul as go version: $(go version)" - continue 1 - fi fi # package etcd needs golang >= v1.19 diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index 7d8b8f3aa..2f4b98bf6 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -32,7 +32,7 @@ env: jobs: code-test: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 # Service containers to run with `code-test` services: @@ -58,6 +58,11 @@ jobs: - 6379:6379 # MySQL backend server. + # docker run -d --name mysql \ + # -p 3306:3306 \ + # -e MYSQL_DATABASE=test \ + # -e MYSQL_ROOT_PASSWORD=12345678 \ + # loads/mysql:5.7 mysql: image: loads/mysql:5.7 env: @@ -185,7 +190,7 @@ jobs: strategy: matrix: - go-version: [ "1.21", "1.22" ] + go-version: ["1.22", "1.23" ] goarch: ["386", "amd64" ] steps: @@ -215,7 +220,19 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - cache-dependency-path: '**/go.sum' + cache-dependency-path: '**/go.sum' + + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + version: "29.x" + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install the protocol compiler plugins for Go + run: | + go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest + export PATH="$PATH:$(go env GOPATH)/bin" - name: Before Script run: bash .github/workflows/before_script.sh diff --git a/.github/workflows/ci-sub.yml b/.github/workflows/ci-sub.yml index 096fbf7d4..977516b21 100644 --- a/.github/workflows/ci-sub.yml +++ b/.github/workflows/ci-sub.yml @@ -37,7 +37,7 @@ jobs: strategy: matrix: - go-version: [ "1.21", "1.22" ] + go-version: [ "1.22", "1.23" ] goarch: [ "386","amd64" ] steps: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..b0c313801 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,92 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "master", "develop" ] + pull_request: + branches: [ "master", "develop" ] + schedule: + - cron: '43 20 * * 0' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: go + build-mode: autobuild + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index d0bf402e1..9ab2d274f 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -12,15 +12,15 @@ jobs: name: Deploy to GitHub Pages runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: doc-build - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 cache: npm - name: Set Up Golang Environment - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1.22.5 cache: false @@ -31,7 +31,7 @@ jobs: - name: Build website run: npm run build - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./build diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 3e2892b1b..456fd7d6d 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -1,17 +1,8 @@ -# Tencent is pleased to support the open source community by making Polaris available. +# Copyright GoFrame Author(https://goframe.org). All Rights Reserved. # -# Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. -# -# Licensed under the BSD 3-Clause License (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://opensource.org/licenses/BSD-3-Clause -# -# Unless required by applicable law or agreed to in writing, software distributed -# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -# CONDITIONS OF ANY KIND, either express or implied. See the License for the -# specific language governing permissions and limitations under the License. +# This Source Code Form is subject to the terms of the MIT License. +# If a copy of the MIT was not distributed with this file, +# You can obtain one at https://github.com/gogf/gf. name: GolangCI-Lint on: @@ -36,7 +27,7 @@ jobs: golangci: strategy: matrix: - go-version: [ '1.21.4','1.22' ] + go-version: [ '1.22', '1.23' ] name: golangci-lint runs-on: ubuntu-latest steps: @@ -50,5 +41,5 @@ jobs: uses: golangci/golangci-lint-action@v6 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.58.2 + version: v1.62.2 args: --timeout 3m0s diff --git a/.github/workflows/sonarcloud.yaml b/.github/workflows/sonarcloud.yaml new file mode 100644 index 000000000..d24d89cd5 --- /dev/null +++ b/.github/workflows/sonarcloud.yaml @@ -0,0 +1,53 @@ +name: Sonarcloud Scan + +on: + schedule: + # Weekly on Saturdays. + - cron: '30 1 * * 6' + push: + branches: [ master ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Declare default permissions as read only. +permissions: read + +jobs: + analysis: + name: Scorecards analysis + runs-on: ubuntu-22.04 + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Used to receive a badge. (Upcoming feature) + id-token: write + # Needs for private repositories. + contents: read + actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: "Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2.2.1 + with: + sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 1c8cc1fb0..b5318f47e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ bin/ cmd/gf/main cmd/gf/gf temp/ +example/log go.work go.work.sum !cmd/gf/go.work diff --git a/.golangci.yml b/.golangci.yml index 11c072949..35b2998c8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -125,7 +125,7 @@ linters-settings: # Checks the number of lines in a function. # If lower than 0, disable the check. # Default: 60 - lines: 330 + lines: 340 # Checks the number of statements in a function. # If lower than 0, disable the check. # Default: 40 @@ -180,6 +180,9 @@ linters-settings: # https://golangci-lint.run/usage/linters/#govet govet: + # Report about shadowed variables. + # Default: false + # check-shadowing: true # Settings per analyzer. settings: # Analyzer name, run `go tool vet help` to see all analyzers. diff --git a/README.MD b/README.MD index 8dfa539e4..47d93bce5 100644 --- a/README.MD +++ b/README.MD @@ -1,7 +1,7 @@ -# GoFrame +
- + [![Go Reference](https://pkg.go.dev/badge/github.com/gogf/gf/v2.svg)](https://pkg.go.dev/github.com/gogf/gf/v2) [![GoFrame CI](https://github.com/gogf/gf/actions/workflows/ci-main.yml/badge.svg)](https://github.com/gogf/gf/actions/workflows/ci-main.yml) @@ -20,86 +20,26 @@
-`GoFrame` is a modular, powerful, high-performance and enterprise-class application development framework of Golang. +A powerful framework for faster, easier, and more efficient project development. -# Features - -- modular, loosely coupled design -- rich components, out-of-the-box -- automatic codes generating for efficiency -- simple and easy to use, detailed documentation -- interface designed components, with high scalability -- fully supported tracing and error stack feature -- specially developed and powerful ORM component -- robust engineering design specifications -- convenient development CLI tool provide -- OpenTelemetry observability features support -- OpenAPIV3 documentation generating, automatically -- much, much more...ready to explore? - -# Installation - -Enter your repo. directory and execute following command: - -## primary module - -```bash -go get -u -v github.com/gogf/gf/v2 -``` - -## cli tool - -```bash -go install github.com/gogf/gf/cmd/gf/v2@latest -``` - -# Limitation - -``` -golang version >= 1.21 -``` # Documentation -- Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf) -- Chinese Pages Document(中文镜像文档): [https://pages.goframe.org](https://pages.goframe.org) -- Chinese Offline Document(中文离线文档): [https://github.com/gogf/goframe.org-pdf](https://github.com/gogf/goframe.org-pdf) +- GoFrame Official Site: [https://goframe.org](https://goframe.org) +- GoFrame Official Site(en): [https://goframe.org/en](https://goframe.org/en) +- GoFrame Mirror Site(中文): [https://goframe.org.cn](https://goframe.org.cn) +- GoFrame Mirror Site(github pages): [https://pages.goframe.org](https://pages.goframe.org) - GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2) + +# Contributors + +💖 [Thanks to all the contributors who made GoFrame possible](https://github.com/gogf/gf/graphs/contributors) 💖 + + + + + # License `GoFrame` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever. - -# Part Of Users - -- [Tencent](https://www.tencent.com/) -- [ZTE](https://www.zte.com.cn/china/) -- [Ant Financial Services](https://www.antfin.com/) -- [VIVO](https://www.vivo.com/) -- [MedLinker](https://www.medlinker.com/) -- [KuCoin](https://www.kucoin.io/) -- [LeYouJia](https://www.leyoujia.com/) -- [IGG](https://igg.com) -- [37](https://www.37.com) -- [XiMaLaYa](https://www.ximalaya.com) -- [ZYBang](https://www.zybang.com/) - -> We list part of the users here, if your company or products are using `GoFrame`, please let us know [here](https://goframe.org/pages/viewpage.action?pageId=1114415). - -# Contributors - -This project exists thanks to all the people who contribute. [[Contributors](https://github.com/gogf/gf/graphs/contributors)]. - - -# Donators - -If you love `GoFrame`, why not [buy developer a cup of coffee](https://goframe.org/pages/viewpage.action?pageId=1115633)? - -# Sponsors - -We appreciate any kind of sponsorship for `GoFrame` development. If you've got some interesting, please contact WeChat `389961817` / Email `john@goframe.org`. - -# Thanks - -JetBrains -Atlassian diff --git a/cmd/gf/Makefile b/cmd/gf/Makefile index e82397130..ae7d69716 100644 --- a/cmd/gf/Makefile +++ b/cmd/gf/Makefile @@ -1,3 +1,4 @@ +.DEFAULT_GOAL := pack pack: pack.template-single pack.template-mono pack.template-mono-app @@ -17,6 +18,9 @@ pack.template-mono: @cd temp && gf pack template-mono ../internal/packed/template-mono.go -n=packed -y @rm -fr temp +# Note: +# command `sed` only works on MacOS. +# use `grep -irl 'template-single' temp| xargs sed -i'' -e 's/template-single/template-mono-app/g'` on other platforms. pack.template-mono-app: @rm -fr temp @mkdir temp || exit 0 @@ -27,6 +31,6 @@ pack.template-mono-app: @rm -fr temp/template-mono-app/.gitignore @rm -fr temp/template-mono-app/go.mod @rm -fr temp/template-mono-app/go.sum - @sed -i 's/template-single/template-mono-app/g' temp/template-mono-app/main.go + @grep -irl 'template-single' temp| xargs sed -i '' -e 's/template-single/template-mono-app/g' @cd temp && gf pack template-mono-app ../internal/packed/template-mono-app.go -n=packed -y @rm -fr temp \ No newline at end of file diff --git a/cmd/gf/gfcmd/gfcmd.go b/cmd/gf/gfcmd/gfcmd.go index 9869e6ae5..4a8dd0622 100644 --- a/cmd/gf/gfcmd/gfcmd.go +++ b/cmd/gf/gfcmd/gfcmd.go @@ -73,7 +73,7 @@ func (c *Command) Run(ctx context.Context) { func GetCommand(ctx context.Context) (*Command, error) { root, err := gcmd.NewFromObject(cmd.GF) if err != nil { - panic(err) + return nil, err } err = root.AddObject( cmd.Up, diff --git a/cmd/gf/go.mod b/cmd/gf/go.mod index a8d4038f1..8b3d4d5b6 100644 --- a/cmd/gf/go.mod +++ b/cmd/gf/go.mod @@ -3,36 +3,36 @@ module github.com/gogf/gf/cmd/gf/v2 go 1.18 require ( - github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.2 - github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.2 - github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2 - github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.2 - github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.2 - github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.2 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.1 + github.com/gogf/gf/v2 v2.8.1 github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f github.com/olekukonko/tablewriter v0.0.5 golang.org/x/mod v0.17.0 - golang.org/x/tools v0.18.0 + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d ) require ( aead.dev/minisign v0.2.0 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/glebarez/go-sqlite v1.21.2 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -43,17 +43,18 @@ require ( github.com/paulmach/orb v0.7.1 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sijms/go-ora/v2 v2.7.10 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/net v0.25.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect modernc.org/mathutil v1.5.0 // indirect diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index 8ccde0d55..e66bcfaa1 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -6,8 +6,8 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xO github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/ClickHouse/clickhouse-go/v2 v2.0.15 h1:lLAZliqrZEygkxosLaW1qHyeTb4Ho7fVCZ0WKCpLocU= github.com/ClickHouse/clickhouse-go/v2 v2.0.15/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk= @@ -22,16 +22,16 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= @@ -50,15 +50,15 @@ github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EO github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= @@ -97,8 +97,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= @@ -118,19 +118,21 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= @@ -139,8 +141,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -157,19 +159,19 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 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= diff --git a/cmd/gf/internal/cmd/cmd.go b/cmd/gf/internal/cmd/cmd.go index bd5e8922e..4a39fd17b 100644 --- a/cmd/gf/internal/cmd/cmd.go +++ b/cmd/gf/internal/cmd/cmd.go @@ -59,7 +59,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error) answer := "n" // No argument or option, do installation checks. if data, isInstalled := service.Install.IsInstalled(); !isInstalled { - mlog.Print("hi, it seams it's the first time you installing gf cli.") + mlog.Print("hi, it seems it's the first time you installing gf cli.") answer = gcmd.Scanf("do you want to install gf(%s) binary to your system? [y/n]: ", gf.VERSION) } else if !data.IsSelf { mlog.Print("hi, you have installed gf cli.") diff --git a/cmd/gf/internal/cmd/cmd_build.go b/cmd/gf/internal/cmd/cmd_build.go index edb7c382e..2454da574 100644 --- a/cmd/gf/internal/cmd/cmd_build.go +++ b/cmd/gf/internal/cmd/cmd_build.go @@ -138,11 +138,6 @@ type cBuildInput struct { type cBuildOutput struct{} func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) { - // print used go env - if in.DumpENV { - _, _ = Env.Index(ctx, cEnvInput{}) - } - mlog.SetHeaderPrint(true) mlog.Debugf(`build command input: %+v`, in) @@ -217,7 +212,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e if !gfile.Exists(in.PackDst) { // Remove the go file that is automatically packed resource. defer func() { - _ = gfile.Remove(in.PackDst) + _ = gfile.RemoveFile(in.PackDst) mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst) }() } @@ -241,6 +236,10 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e } else { genv.MustSet("CGO_ENABLED", "0") } + // print used go env + if in.DumpENV { + _, _ = Env.Index(ctx, cEnvInput{}) + } for system, item := range platformMap { if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) { continue diff --git a/cmd/gf/internal/cmd/cmd_doc.go b/cmd/gf/internal/cmd/cmd_doc.go index 9b1b855ed..78501a8a1 100644 --- a/cmd/gf/internal/cmd/cmd_doc.go +++ b/cmd/gf/internal/cmd/cmd_doc.go @@ -8,6 +8,7 @@ package cmd import ( "context" + "fmt" "io" "net/http" "os" @@ -22,8 +23,12 @@ import ( ) const ( + GitName = "gf-site" + BranchName = "gh-pages" + + SiteFileName = GitName + "-" + BranchName // DocURL is the download address of the document - DocURL = "https://github.com/gogf/gf/archive/refs/heads/gh-pages.zip" + DocURL = "https://github.com/gogf/" + GitName + "/archive/refs/heads/" + BranchName + ".zip" ) var ( @@ -70,12 +75,13 @@ func (c cDoc) Index(ctx context.Context, in cDocInput) (out *cDocOutput, err err mlog.Print("Failed to download document:", err) return } - s := g.Server() - s.SetServerRoot(docs.DocDir) - s.SetPort(in.Port) - s.SetDumpRouterMap(false) - mlog.Printf("Access address http://127.0.0.1:%d", in.Port) - s.Run() + + http.Handle("/", http.FileServer(http.Dir(docs.DocDir))) + mlog.Printf("Access address http://127.0.0.1:%d in %s", in.Port, docs.DocDir) + err = http.ListenAndServe(fmt.Sprintf(":%d", in.Port), nil) + if err != nil { + return nil, err + } return } @@ -89,7 +95,7 @@ type DocSetting struct { // NewDocSetting new DocSetting func NewDocSetting(ctx context.Context, in cDocInput) *DocSetting { - fileName := "gf-doc-md.zip" + fileName := SiteFileName + ".zip" tempDir := in.Path if tempDir == "" { tempDir = gfile.Temp("goframe/docs") @@ -99,17 +105,17 @@ func NewDocSetting(ctx context.Context, in cDocInput) *DocSetting { return &DocSetting{ TempDir: filepath.FromSlash(tempDir), - DocDir: filepath.FromSlash(path.Join(tempDir, "gf-gh-pages")), + DocDir: filepath.FromSlash(path.Join(tempDir, SiteFileName)), DocURL: in.Proxy + DocURL, DocZipFile: filepath.FromSlash(path.Join(tempDir, fileName)), } } -// Clean clean the temporary directory +// Clean cleans the temporary directory func (d *DocSetting) Clean() error { if _, err := os.Stat(d.TempDir); err == nil { - err = gfile.Remove(d.TempDir) + err = gfile.RemoveAll(d.TempDir) if err != nil { mlog.Print("Failed to delete temporary directory:", err) return err @@ -168,7 +174,7 @@ func (d *DocSetting) DownloadDoc() error { err := gcompress.UnZipFile(d.DocZipFile, d.TempDir) if err != nil { mlog.Print("Failed to unzip the file, please run again:", err) - gfile.Remove(d.DocZipFile) + _ = gfile.RemoveFile(d.DocZipFile) return err } diff --git a/cmd/gf/internal/cmd/cmd_run.go b/cmd/gf/internal/cmd/cmd_run.go index 8c30c4e34..490a93a8b 100644 --- a/cmd/gf/internal/cmd/cmd_run.go +++ b/cmd/gf/internal/cmd/cmd_run.go @@ -93,6 +93,12 @@ type ( ) func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err error) { + if !gfile.Exists(in.File) { + mlog.Fatalf(`given file "%s" not found`, in.File) + } + if !gfile.IsFile(in.File) { + mlog.Fatalf(`given "%s" is not a file`, in.File) + } // Necessary check. if gproc.SearchBinary("go") == "" { mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`) @@ -205,7 +211,7 @@ func (app *cRunApp) End(ctx context.Context, sig os.Signal, outputPath string) { mlog.Debugf("kill process error: %s", err.Error()) } } - if err := gfile.Remove(outputPath); err != nil { + if err := gfile.RemoveFile(outputPath); err != nil { mlog.Printf("delete binary file error: %s", err.Error()) } else { mlog.Printf("deleted binary file: %s", outputPath) diff --git a/cmd/gf/internal/cmd/cmd_up.go b/cmd/gf/internal/cmd/cmd_up.go index ab9963bd8..2bef38896 100644 --- a/cmd/gf/internal/cmd/cmd_up.go +++ b/cmd/gf/internal/cmd/cmd_up.go @@ -142,8 +142,9 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV } for _, pkg := range packages { mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version) - // go get -u - command := fmt.Sprintf(`cd %s && go get -u %s@latest`, dirPath, pkg.Name) + mlog.Printf(`running command: go get %s@latest`, pkg.Name) + // go get @latest + command := fmt.Sprintf(`cd %s && go get %s@latest`, dirPath, pkg.Name) if err = gproc.ShellRun(ctx, command); err != nil { return } @@ -191,7 +192,7 @@ func (c cUp) doUpgradeCLI(ctx context.Context) (err error) { defer func() { mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath()) mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath) - _ = gfile.Remove(localSaveFilePath) + _ = gfile.RemoveFile(localSaveFilePath) }() // It fails if file not exist or its size is less than 1MB. diff --git a/cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go b/cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go index 5958e238e..dd920b663 100644 --- a/cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go +++ b/cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go @@ -691,3 +691,151 @@ func Test_Gen_Dao_Issue3459(t *testing.T) { } }) } + +// https://github.com/gogf/gf/issues/3749 +func Test_Gen_Dao_Issue3749(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + err error + db = testDB + table = "table_user" + sqlContent = fmt.Sprintf( + gtest.DataContent(`issue`, `3749`, `user.tpl.sql`), + table, + ) + ) + dropTableWithDb(db, table) + array := gstr.SplitAndTrim(sqlContent, ";") + for _, v := range array { + if _, err = db.Exec(ctx, v); err != nil { + t.AssertNil(err) + } + } + defer dropTableWithDb(db, table) + + var ( + path = gfile.Temp(guid.S()) + group = "test" + in = gendao.CGenDaoInput{ + Path: path, + Link: link, + Group: group, + } + ) + + err = gutil.FillStructWithDefault(&in) + t.AssertNil(err) + + err = gfile.Mkdir(path) + t.AssertNil(err) + + // for go mod import path auto retrieve. + err = gfile.Copy( + gtest.DataPath("gendao", "go.mod.txt"), + gfile.Join(path, "go.mod"), + ) + t.AssertNil(err) + + _, err = gendao.CGenDao{}.Dao(ctx, in) + t.AssertNil(err) + defer gfile.Remove(path) + + // files + files, err := gfile.ScanDir(path, "*.go", true) + t.AssertNil(err) + t.Assert(files, []string{ + filepath.FromSlash(path + "/dao/internal/table_user.go"), + filepath.FromSlash(path + "/dao/table_user.go"), + filepath.FromSlash(path + "/model/do/table_user.go"), + filepath.FromSlash(path + "/model/entity/table_user.go"), + }) + // content + testPath := gtest.DataPath(`issue`, `3749`) + expectFiles := []string{ + filepath.FromSlash(testPath + "/dao/internal/table_user.go"), + filepath.FromSlash(testPath + "/dao/table_user.go"), + filepath.FromSlash(testPath + "/model/do/table_user.go"), + filepath.FromSlash(testPath + "/model/entity/table_user.go"), + } + for i, _ := range files { + t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) + } + }) +} + +func Test_Gen_Dao_Sqlite3(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + err error + table = "table_user" + path = gfile.Temp(guid.S()) + linkSqlite3 = fmt.Sprintf("sqlite::@file(%s/db.sqlite3)", path) + sqlContent = fmt.Sprintf( + gtest.DataContent(`gendao`, `sqlite3`, `user.sqlite3.sql`), + table, + ) + ) + err = gfile.Mkdir(path) + t.AssertNil(err) + defer gfile.Remove(path) + + dbSqlite3, err := gdb.New(gdb.ConfigNode{ + Link: linkSqlite3, + }) + t.AssertNil(err) + + array := gstr.SplitAndTrim(sqlContent, ";") + for _, v := range array { + if v == "" { + continue + } + if _, err = dbSqlite3.Exec(ctx, v); err != nil { + t.AssertNil(err) + } + } + + var ( + group = "test" + in = gendao.CGenDaoInput{ + Path: path, + Link: linkSqlite3, + Group: group, + Tables: table, + } + ) + err = gutil.FillStructWithDefault(&in) + t.AssertNil(err) + + // for go mod import path auto retrieve. + err = gfile.Copy( + gtest.DataPath("gendao", "go.mod.txt"), + gfile.Join(path, "go.mod"), + ) + t.AssertNil(err) + + _, err = gendao.CGenDao{}.Dao(ctx, in) + t.AssertNil(err) + defer gfile.Remove(path) + + // files + files, err := gfile.ScanDir(path, "*.go", true) + t.AssertNil(err) + t.Assert(files, []string{ + filepath.FromSlash(path + "/dao/internal/table_user.go"), + filepath.FromSlash(path + "/dao/table_user.go"), + filepath.FromSlash(path + "/model/do/table_user.go"), + filepath.FromSlash(path + "/model/entity/table_user.go"), + }) + // content + testPath := gtest.DataPath("gendao", "generated_user_sqlite3") + expectFiles := []string{ + filepath.FromSlash(testPath + "/dao/internal/table_user.go"), + filepath.FromSlash(testPath + "/dao/table_user.go"), + filepath.FromSlash(testPath + "/model/do/table_user.go"), + filepath.FromSlash(testPath + "/model/entity/table_user.go"), + } + for i, _ := range files { + t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) + } + }) +} diff --git a/cmd/gf/internal/cmd/cmd_z_unit_gen_pb_test.go b/cmd/gf/internal/cmd/cmd_z_unit_gen_pb_test.go new file mode 100644 index 000000000..f1ec5be5c --- /dev/null +++ b/cmd/gf/internal/cmd/cmd_z_unit_gen_pb_test.go @@ -0,0 +1,50 @@ +// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package cmd + +import ( + "path/filepath" + "testing" + + "github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpb" + "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/guid" +) + +func TestGenPbIssue3882(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + outputPath = gfile.Temp(guid.S()) + outputApiPath = filepath.Join(outputPath, "api") + outputCtrlPath = filepath.Join(outputPath, "controller") + + protobufFolder = gtest.DataPath("issue", "3882") + in = genpb.CGenPbInput{ + Path: protobufFolder, + OutputApi: outputApiPath, + OutputCtrl: outputCtrlPath, + } + err error + ) + err = gfile.Mkdir(outputApiPath) + t.AssertNil(err) + err = gfile.Mkdir(outputCtrlPath) + t.AssertNil(err) + defer gfile.Remove(outputPath) + + _, err = genpb.CGenPb{}.Pb(ctx, in) + t.AssertNil(err) + + var ( + genContent = gfile.GetContents(filepath.Join(outputApiPath, "issue3882.pb.go")) + exceptText = `dc:"Some comment on field with 'one' 'two' 'three' in the comment."` + ) + t.Assert(gstr.Contains(genContent, exceptText), true) + }) +} diff --git a/cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go b/cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go index 4a105697d..851dc2a7e 100644 --- a/cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go +++ b/cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go @@ -52,6 +52,8 @@ func Test_Gen_Pbentity_Default(t *testing.T) { NameCase: "", JsonCase: "", Option: "", + TypeMapping: nil, + FieldMapping: nil, } ) err = gutil.FillStructWithDefault(&in) @@ -115,6 +117,8 @@ func Test_Gen_Pbentity_NameCase_SnakeScreaming(t *testing.T) { NameCase: "SnakeScreaming", JsonCase: "", Option: "", + TypeMapping: nil, + FieldMapping: nil, } ) err = gutil.FillStructWithDefault(&in) @@ -179,6 +183,8 @@ func Test_Issue_3545(t *testing.T) { NameCase: "", JsonCase: "", Option: "", + TypeMapping: nil, + FieldMapping: nil, } ) err = gutil.FillStructWithDefault(&in) @@ -208,3 +214,74 @@ func Test_Issue_3545(t *testing.T) { } }) } + +// https://github.com/gogf/gf/issues/3685 +func Test_Issue_3685(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + err error + db = testDB + table = "table_user" + sqlContent = fmt.Sprintf( + gtest.DataContent(`issue`, `3685`, `user.tpl.sql`), + table, + ) + ) + dropTableWithDb(db, table) + array := gstr.SplitAndTrim(sqlContent, ";") + for _, v := range array { + if _, err = db.Exec(ctx, v); err != nil { + t.AssertNil(err) + } + } + defer dropTableWithDb(db, table) + + var ( + path = gfile.Temp(guid.S()) + in = genpbentity.CGenPbEntityInput{ + Path: path, + Package: "", + Link: link, + Tables: "", + Prefix: "", + RemovePrefix: "", + RemoveFieldPrefix: "", + NameCase: "", + JsonCase: "", + Option: "", + TypeMapping: map[genpbentity.DBFieldTypeName]genpbentity.CustomAttributeType{ + "json": { + Type: "google.protobuf.Value", + Import: "google/protobuf/struct.proto", + }, + }, + FieldMapping: nil, + } + ) + err = gutil.FillStructWithDefault(&in) + t.AssertNil(err) + + err = gfile.Mkdir(path) + t.AssertNil(err) + defer gfile.Remove(path) + + _, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in) + t.AssertNil(err) + + // files + files, err := gfile.ScanDir(path, "*.proto", false) + t.AssertNil(err) + t.Assert(files, []string{ + path + filepath.FromSlash("/table_user.proto"), + }) + + // contents + testPath := gtest.DataPath("issue", "3685") + expectFiles := []string{ + testPath + filepath.FromSlash("/table_user.proto"), + } + for i := range files { + t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i])) + } + }) +} diff --git a/cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go b/cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go index 4491a3fcb..e2362bbb5 100644 --- a/cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go +++ b/cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go @@ -22,9 +22,9 @@ func Test_Gen_Service_Default(t *testing.T) { var ( path = gfile.Temp(guid.S()) dstFolder = path + filepath.FromSlash("/service") - apiFolder = gtest.DataPath("genservice", "logic") + srvFolder = gtest.DataPath("genservice", "logic") in = genservice.CGenServiceInput{ - SrcFolder: apiFolder, + SrcFolder: srvFolder, DstFolder: dstFolder, DstFileNameCase: "Snake", WatchFile: "", @@ -46,11 +46,11 @@ func Test_Gen_Service_Default(t *testing.T) { // logic file var ( - genApi = apiFolder + filepath.FromSlash("/logic.go") - genApiExpect = apiFolder + filepath.FromSlash("/logic_expect.go") + genSrv = srvFolder + filepath.FromSlash("/logic.go") + genSrvExpect = srvFolder + filepath.FromSlash("/logic_expect.go") ) - defer gfile.Remove(genApi) - t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect)) + defer gfile.Remove(genSrv) + t.Assert(gfile.GetContents(genSrv), gfile.GetContents(genSrvExpect)) // files files, err := gfile.ScanDir(dstFolder, "*.go", true) @@ -73,3 +73,83 @@ func Test_Gen_Service_Default(t *testing.T) { } }) } + +// https://github.com/gogf/gf/issues/3328 +func Test_Issue3328(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + path = gfile.Temp(guid.S()) + dstFolder = path + filepath.FromSlash("/service") + srvFolder = gtest.DataPath("issue", "3328", "logic") + logicGoPath = srvFolder + filepath.FromSlash("/logic.go") + in = genservice.CGenServiceInput{ + SrcFolder: srvFolder, + DstFolder: dstFolder, + DstFileNameCase: "Snake", + WatchFile: "", + StPattern: "", + Packages: nil, + ImportPrefix: "", + Clear: false, + } + ) + gfile.Remove(logicGoPath) + defer gfile.Remove(logicGoPath) + + err := gutil.FillStructWithDefault(&in) + t.AssertNil(err) + + err = gfile.Mkdir(path) + t.AssertNil(err) + defer gfile.Remove(path) + + _, err = genservice.CGenService{}.Service(ctx, in) + t.AssertNil(err) + + files, err := gfile.ScanDir(srvFolder, "*", true) + for _, file := range files { + if file == logicGoPath { + if gfile.IsDir(logicGoPath) { + t.Fatalf("%s should not is folder", logicGoPath) + } + } + } + }) +} + +// https://github.com/gogf/gf/issues/3835 +func Test_Issue3835(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + path = gfile.Temp(guid.S()) + dstFolder = path + filepath.FromSlash("/service") + srvFolder = gtest.DataPath("issue", "3835", "logic") + in = genservice.CGenServiceInput{ + SrcFolder: srvFolder, + DstFolder: dstFolder, + DstFileNameCase: "Snake", + WatchFile: "", + StPattern: "", + Packages: nil, + ImportPrefix: "", + Clear: false, + } + ) + err := gutil.FillStructWithDefault(&in) + t.AssertNil(err) + + err = gfile.Mkdir(path) + t.AssertNil(err) + defer gfile.Remove(path) + + _, err = genservice.CGenService{}.Service(ctx, in) + t.AssertNil(err) + + // contents + var ( + genFile = dstFolder + filepath.FromSlash("/issue_3835.go") + expectFile = gtest.DataPath("issue", "3835", "service", "issue_3835.go") + ) + t.Assert(gfile.GetContents(genFile), gfile.GetContents(expectFile)) + }) +} diff --git a/cmd/gf/internal/cmd/genctrl/genctrl.go b/cmd/gf/internal/cmd/genctrl/genctrl.go index d6788620a..87d87766e 100644 --- a/cmd/gf/internal/cmd/genctrl/genctrl.go +++ b/cmd/gf/internal/cmd/genctrl/genctrl.go @@ -128,7 +128,7 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion, return } } - defer gfile.Remove(flockFilePath) + defer gfile.RemoveFile(flockFilePath) _ = gfile.PutContents(flockFilePath, gtime.TimestampStr()) // check this updated file is an api file. diff --git a/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl.go b/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl.go index edaeb51a3..d966338f8 100644 --- a/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl.go +++ b/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl.go @@ -89,7 +89,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion( if err = gfile.PutContents(moduleFilePath, gstr.TrimLeft(content)); err != nil { return err } - mlog.Printf(`generated: %s`, moduleFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePath)) } if !gfile.Exists(moduleFilePathNew) { content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerNewEmpty, g.MapStrStr{ @@ -99,7 +99,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion( if err = gfile.PutContents(moduleFilePathNew, gstr.TrimLeft(content)); err != nil { return err } - mlog.Printf(`generated: %s`, moduleFilePathNew) + mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePathNew)) } filePaths, err := gfile.ScanDir(dstModuleFolderPath, "*.go", false) if err != nil { @@ -161,7 +161,7 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite return err } } - mlog.Printf(`generated: %s`, methodFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(methodFilePath)) return } @@ -221,7 +221,7 @@ func (c *controllerGenerator) doGenerateCtrlMergeItem(dstModuleFolderPath string if err = gfile.PutContentsAppend(ctrlFilePath, ctrlFileItem.controllers.String()); err != nil { return err } - mlog.Printf(`generated: %s`, ctrlFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(ctrlFilePath)) } return } diff --git a/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go b/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go index 73d562648..af328f8dd 100644 --- a/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go +++ b/cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go @@ -49,7 +49,7 @@ func (c *controllerClearer) doClear(dstModuleFolderPath string, item apiItem) (e `remove unimplemented and of no api definitions controller file: %s`, methodFilePath, ) - err = gfile.Remove(methodFilePath) + err = gfile.RemoveFile(methodFilePath) } } return diff --git a/cmd/gf/internal/cmd/genctrl/genctrl_generate_interface.go b/cmd/gf/internal/cmd/genctrl/genctrl_generate_interface.go index c0ba77e1f..c678c0194 100644 --- a/cmd/gf/internal/cmd/genctrl/genctrl_generate_interface.go +++ b/cmd/gf/internal/cmd/genctrl/genctrl_generate_interface.go @@ -94,7 +94,7 @@ func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module st "{Interfaces}": gstr.TrimRightStr(interfaceDefinition, "\n", 2), })) err = gfile.PutContents(moduleFilePath, interfaceContent) - mlog.Printf(`generated: %s`, moduleFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePath)) return } diff --git a/cmd/gf/internal/cmd/genctrl/genctrl_generate_sdk.go b/cmd/gf/internal/cmd/genctrl/genctrl_generate_sdk.go index e045ae0d9..b5a82afb6 100644 --- a/cmd/gf/internal/cmd/genctrl/genctrl_generate_sdk.go +++ b/cmd/gf/internal/cmd/genctrl/genctrl_generate_sdk.go @@ -65,7 +65,7 @@ func (c *apiSdkGenerator) doGenerateSdkPkgFile(sdkFolderPath string) (err error) "{PkgName}": pkgName, })) err = gfile.PutContents(pkgFilePath, fileContent) - mlog.Printf(`generated: %s`, pkgFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(pkgFilePath)) return } @@ -130,9 +130,9 @@ func (c *apiSdkGenerator) doGenerateSdkIClient( if isDirty { err = gfile.PutContents(iClientFilePath, fileContent) if isExist { - mlog.Printf(`updated: %s`, iClientFilePath) + mlog.Printf(`updated: %s`, gfile.RealPath(iClientFilePath)) } else { - mlog.Printf(`generated: %s`, iClientFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(iClientFilePath)) } } return @@ -183,7 +183,7 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer( implementerFileContent += "\n" } err = gfile.PutContents(implementerFilePath, implementerFileContent) - mlog.Printf(`generated: %s`, implementerFilePath) + mlog.Printf(`generated: %s`, gfile.RealPath(implementerFilePath)) return } diff --git a/cmd/gf/internal/cmd/gendao/gendao.go b/cmd/gf/internal/cmd/gendao/gendao.go index 7a048016e..a19d0c5a1 100644 --- a/cmd/gf/internal/cmd/gendao/gendao.go +++ b/cmd/gf/internal/cmd/gendao/gendao.go @@ -208,9 +208,11 @@ type ( NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"` Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"` - TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` - FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` - genItems *CGenDaoInternalGenItems + TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"` + FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"` + + // internal usage purpose. + genItems *CGenDaoInternalGenItems } CGenDaoOutput struct{} diff --git a/cmd/gf/internal/cmd/gendao/gendao_clear.go b/cmd/gf/internal/cmd/gendao/gendao_clear.go index ad05918c3..181804641 100644 --- a/cmd/gf/internal/cmd/gendao/gendao_clear.go +++ b/cmd/gf/internal/cmd/gendao/gendao_clear.go @@ -40,7 +40,7 @@ func doClearItem(item CGenDaoInternalGenItem, allGeneratedFilePaths []string) { } for _, filePath := range generatedFilePaths { if !gstr.InArray(allGeneratedFilePaths, filePath) { - if err := gfile.Remove(filePath); err != nil { + if err := gfile.RemoveFile(filePath); err != nil { mlog.Print(err) } } diff --git a/cmd/gf/internal/cmd/gendao/gendao_dao.go b/cmd/gf/internal/cmd/gendao/gendao_dao.go index 3d3b8a4d6..1c2363347 100644 --- a/cmd/gf/internal/cmd/gendao/gendao_dao.go +++ b/cmd/gf/internal/cmd/gendao/gendao_dao.go @@ -58,8 +58,8 @@ func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) { mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err) } var ( - tableNameCamelCase = gstr.CaseCamel(strings.ToLower(in.NewTableName)) - tableNameCamelLowerCase = gstr.CaseCamelLower(strings.ToLower(in.NewTableName)) + tableNameCamelCase = formatFieldName(in.NewTableName, FieldNameCaseCamel) + tableNameCamelLowerCase = formatFieldName(in.NewTableName, FieldNameCaseCamelLower) tableNameSnakeCase = gstr.CaseSnake(in.NewTableName) importPrefix = in.ImportPrefix ) @@ -123,7 +123,7 @@ func generateDaoIndex(in generateDaoIndexInput) { mlog.Fatalf("writing content to '%s' failed: %v", path, err) } else { utils.GoFmt(path) - mlog.Print("generated:", path) + mlog.Print("generated:", gfile.RealPath(path)) } } } @@ -157,7 +157,7 @@ func generateDaoInternal(in generateDaoInternalInput) { mlog.Fatalf("writing content to '%s' failed: %v", path, err) } else { utils.GoFmt(path) - mlog.Print("generated:", path) + mlog.Print("generated:", gfile.RealPath(path)) } } @@ -179,7 +179,7 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldP } array[index] = []string{ - " #" + gstr.CaseCamel(strings.ToLower(newFiledName)) + ":", + " #" + formatFieldName(newFiledName, FieldNameCaseCamel) + ":", fmt.Sprintf(` #"%s",`, field.Name), } } @@ -219,7 +219,7 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeF newFiledName = gstr.TrimLeftStr(newFiledName, v, 1) } array[index] = []string{ - " #" + gstr.CaseCamel(strings.ToLower(newFiledName)), + " #" + formatFieldName(newFiledName, FieldNameCaseCamel), " # " + "string", " #" + fmt.Sprintf(`// %s`, comment), } diff --git a/cmd/gf/internal/cmd/gendao/gendao_do.go b/cmd/gf/internal/cmd/gendao/gendao_do.go index 16a4c15eb..7a3cb542c 100644 --- a/cmd/gf/internal/cmd/gendao/gendao_do.go +++ b/cmd/gf/internal/cmd/gendao/gendao_do.go @@ -40,7 +40,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) { structDefinition, _ = generateStructDefinition(ctx, generateStructDefinitionInput{ CGenDaoInternalInput: in, TableName: tableName, - StructName: gstr.CaseCamel(strings.ToLower(newTableName)), + StructName: formatFieldName(newTableName, FieldNameCaseCamel), FieldMap: fieldMap, IsDo: true, }) @@ -61,7 +61,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) { ctx, in, tableName, - gstr.CaseCamel(strings.ToLower(newTableName)), + formatFieldName(newTableName, FieldNameCaseCamel), structDefinition, ) in.genItems.AppendGeneratedFilePath(doFilePath) @@ -70,7 +70,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) { mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err) } else { utils.GoFmt(doFilePath) - mlog.Print("generated:", doFilePath) + mlog.Print("generated:", gfile.RealPath(doFilePath)) } } } diff --git a/cmd/gf/internal/cmd/gendao/gendao_entity.go b/cmd/gf/internal/cmd/gendao/gendao_entity.go index 7a36bf428..9d38db428 100644 --- a/cmd/gf/internal/cmd/gendao/gendao_entity.go +++ b/cmd/gf/internal/cmd/gendao/gendao_entity.go @@ -36,7 +36,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) { structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{ CGenDaoInternalInput: in, TableName: tableName, - StructName: gstr.CaseCamel(strings.ToLower(newTableName)), + StructName: formatFieldName(newTableName, FieldNameCaseCamel), FieldMap: fieldMap, IsDo: false, }) @@ -44,7 +44,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) { ctx, in, newTableName, - gstr.CaseCamel(strings.ToLower(newTableName)), + formatFieldName(newTableName, FieldNameCaseCamel), structDefinition, appendImports, ) @@ -55,7 +55,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) { mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err) } else { utils.GoFmt(entityFilePath) - mlog.Print("generated:", entityFilePath) + mlog.Print("generated:", gfile.RealPath(entityFilePath)) } } } diff --git a/cmd/gf/internal/cmd/gendao/gendao_structure.go b/cmd/gf/internal/cmd/gendao/gendao_structure.go index e9acc8bff..01f334cb9 100644 --- a/cmd/gf/internal/cmd/gendao/gendao_structure.go +++ b/cmd/gf/internal/cmd/gendao/gendao_structure.go @@ -99,7 +99,7 @@ func generateStructFieldDefinition( } localTypeNameStr = string(localTypeName) switch localTypeName { - case gdb.LocalTypeDate, gdb.LocalTypeDatetime: + case gdb.LocalTypeDate, gdb.LocalTypeTime, gdb.LocalTypeDatetime: if in.StdTime { localTypeNameStr = "time.Time" } else { @@ -140,7 +140,7 @@ func generateStructFieldDefinition( } attrLines = []string{ - " #" + gstr.CaseCamel(strings.ToLower(newFiledName)), + " #" + formatFieldName(newFiledName, FieldNameCaseCamel), " #" + localTypeNameStr, } attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag)) @@ -167,6 +167,43 @@ func generateStructFieldDefinition( return attrLines, appendImport } +type FieldNameCase string + +const ( + FieldNameCaseCamel FieldNameCase = "CaseCamel" + FieldNameCaseCamelLower FieldNameCase = "CaseCamelLower" +) + +// formatFieldName formats and returns a new field name that is used for golang codes generating. +func formatFieldName(fieldName string, nameCase FieldNameCase) string { + // For normal databases like mysql, pgsql, sqlite, + // field/table names of that are in normal case. + var newFieldName = fieldName + if isAllUpper(fieldName) { + // For special databases like dm, oracle, + // field/table names of that are in upper case. + newFieldName = strings.ToLower(fieldName) + } + switch nameCase { + case FieldNameCaseCamel: + return gstr.CaseCamel(newFieldName) + case FieldNameCaseCamelLower: + return gstr.CaseCamelLower(newFieldName) + default: + return "" + } +} + +// isAllUpper checks and returns whether given `fieldName` all letters are upper case. +func isAllUpper(fieldName string) bool { + for _, b := range fieldName { + if b >= 'a' && b <= 'z' { + return false + } + } + return true +} + // formatComment formats the comment string to fit the golang code without any lines. func formatComment(comment string) string { comment = gstr.ReplaceByArray(comment, g.SliceStr{ diff --git a/cmd/gf/internal/cmd/genpb/genpb.go b/cmd/gf/internal/cmd/genpb/genpb.go index e1c4f8836..023cdb984 100644 --- a/cmd/gf/internal/cmd/genpb/genpb.go +++ b/cmd/gf/internal/cmd/genpb/genpb.go @@ -94,6 +94,9 @@ func (c CGenPb) Pb(ctx context.Context, in CGenPbInput) (out *CGenPbOutput, err mlog.Fatalf(`no proto files found in folder "%s"`, in.Path) } + var originPwd = gfile.Pwd() + defer gfile.Chdir(originPwd) + if err = gfile.Chdir(protoPath); err != nil { mlog.Fatal(err) } diff --git a/cmd/gf/internal/cmd/genpb/genpb_tag.go b/cmd/gf/internal/cmd/genpb/genpb_tag.go index 5bc401a6e..f8cfad7e5 100644 --- a/cmd/gf/internal/cmd/genpb/genpb_tag.go +++ b/cmd/gf/internal/cmd/genpb/genpb_tag.go @@ -12,6 +12,7 @@ import ( "github.com/gogf/gf/cmd/gf/v2/internal/utility/utils" "github.com/gogf/gf/v2/container/gmap" + "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" @@ -90,8 +91,12 @@ func (c CGenPb) tagCommentIntoListMap(comment string, lineTagMap *gmap.ListMap) lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent) } else { var ( - tagName = "dc" - tagContent = comment + tagName = "dc" + // Convert backticks and double quotes to single quotes. + tagContent = gstr.ReplaceByMap(comment, g.MapStrStr{ + "`": `'`, + `"`: `'`, + }) ) lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent) } diff --git a/cmd/gf/internal/cmd/genpbentity/genpbentity.go b/cmd/gf/internal/cmd/genpbentity/genpbentity.go index 0c375593d..29a660b08 100644 --- a/cmd/gf/internal/cmd/genpbentity/genpbentity.go +++ b/cmd/gf/internal/cmd/genpbentity/genpbentity.go @@ -11,6 +11,7 @@ import ( "context" "fmt" "path/filepath" + "regexp" "strings" "github.com/gogf/gf/cmd/gf/v2/internal/utility/utils" @@ -18,6 +19,7 @@ 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/container/garray" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" @@ -43,6 +45,9 @@ type ( NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"` JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"none"` Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"` + + TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenPbEntityBriefTypeMapping}" orphan:"true"` + FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenPbEntityBriefFieldMapping}" orphan:"true"` } CGenPbEntityOutput struct{} @@ -52,6 +57,13 @@ type ( TableName string // TableName specifies the table name of the table. NewTableName string // NewTableName specifies the prefix-stripped name of the table. } + + DBTableFieldName = string + DBFieldTypeName = string + CustomAttributeType struct { + Type string `brief:"custom attribute type name"` + Import string `brief:"custom import for this type"` + } ) const ( @@ -69,7 +81,7 @@ gf gen pbentity -r user_ CGenPbEntityAd = ` CONFIGURATION SUPPORT Options are also supported by configuration file. - It's suggested using configuration file instead of command line arguments making producing. + It's suggested using configuration file instead of command line arguments making producing. The configuration node name is "gf.gen.pbentity", which also supports multiple databases, for example(config.yaml): gfcli: gen: @@ -88,6 +100,13 @@ CONFIGURATION SUPPORT option go_package = "protobuf/demos"; option java_package = "protobuf/demos"; option php_namespace = "protobuf/demos"; + typeMapping: + json: + type: google.protobuf.Value + import: google/protobuf/struct.proto + jsonb: + type: google.protobuf.Value + import: google/protobuf/struct.proto ` CGenPbEntityBriefPath = `directory path for generated files storing` CGenPbEntityBriefPackage = `package path for all entity proto files` @@ -106,7 +125,7 @@ it's not necessary and the default value is "default" case for message attribute names, default is "Camel": | Case | Example | |---------------- |--------------------| -| Camel | AnyKindOfString | +| Camel | AnyKindOfString | | CamelLower | anyKindOfString | default | Snake | any_kind_of_string | | SnakeScreaming | ANY_KIND_OF_STRING | @@ -119,8 +138,95 @@ case for message attribute names, default is "Camel": case for message json tag, cases are the same as "nameCase", default "CamelLower". set it to "none" to ignore json tag generating. ` + + CGenPbEntityBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table` + CGenPbEntityBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table` ) +var defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{ + // gdb.LocalTypeString + "string": { + Type: "string", + }, + // gdb.LocalTypeTime + // "time": { + // Type: "google.protobuf.Duration", + // Import: "google/protobuf/duration.proto", + // }, + // gdb.LocalTypeDate + "date": { + Type: "google.protobuf.Timestamp", + Import: "google/protobuf/timestamp.proto", + }, + // gdb.LocalTypeDatetime + "datetime": { + Type: "google.protobuf.Timestamp", + Import: "google/protobuf/timestamp.proto", + }, + // gdb.LocalTypeInt + "int": { + Type: "int32", + }, + // gdb.LocalTypeUint + "uint": { + Type: "uint32", + }, + // gdb.LocalTypeInt64 + "int64": { + Type: "int64", + }, + // gdb.LocalTypeUint64 + "uint64": { + Type: "uint64", + }, + // gdb.LocalTypeIntSlice + "[]int": { + Type: "repeated int32", + }, + // gdb.LocalTypeInt64Slice + "[]int64": { + Type: "repeated int64", + }, + // gdb.LocalTypeUint64Slice + "[]uint64": { + Type: "repeated uint64", + }, + // gdb.LocalTypeInt64Bytes + "int64-bytes": { + Type: "repeated int64", + }, + // gdb.LocalTypeUint64Bytes + "uint64-bytes": { + Type: "repeated uint64", + }, + // gdb.LocalTypeFloat32 + "float32": { + Type: "float", + }, + // gdb.LocalTypeFloat64 + "float64": { + Type: "double", + }, + // gdb.LocalTypeBytes + "[]byte": { + Type: "bytes", + }, + // gdb.LocalTypeBool + "bool": { + Type: "bool", + }, + // gdb.LocalTypeJson + // "json": { + // Type: "google.protobuf.Value", + // Import: "google/protobuf/struct.proto", + // }, + // gdb.LocalTypeJsonb + // "jsonb": { + // Type: "google.protobuf.Value", + // Import: "google/protobuf/struct.proto", + // }, +} + func init() { gtag.Sets(g.MapStrStr{ `CGenPbEntityConfig`: CGenPbEntityConfig, @@ -138,6 +244,8 @@ func init() { `CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase, `CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase, `CGenPbEntityBriefOption`: CGenPbEntityBriefOption, + `CGenPbEntityBriefTypeMapping`: CGenPbEntityBriefTypeMapping, + `CGenPbEntityBriefFieldMapping`: CGenPbEntityBriefFieldMapping, }) } @@ -210,6 +318,16 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput) mlog.Fatalf("fetching tables failed: \n %v", err) } } + // merge default typeMapping to input typeMapping. + if in.TypeMapping == nil { + in.TypeMapping = defaultTypeMapping + } else { + for key, typeMapping := range defaultTypeMapping { + if _, ok := in.TypeMapping[key]; !ok { + in.TypeMapping[key] = typeMapping + } + } + } for _, tableName := range tableNames { newTableName := tableName @@ -234,18 +352,24 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp // Change the `newTableName` if `Prefix` is given. newTableName := in.Prefix + in.NewTableName var ( - imports string - tableNameCamelCase = gstr.CaseCamel(newTableName) - tableNameSnakeCase = gstr.CaseSnake(newTableName) - entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in) - fileName = gstr.Trim(tableNameSnakeCase, "-_.") - path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto")) + tableNameCamelCase = gstr.CaseCamel(newTableName) + tableNameSnakeCase = gstr.CaseSnake(newTableName) + entityMessageDefine, appendImports = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in) + fileName = gstr.Trim(tableNameSnakeCase, "-_.") + path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto")) ) - if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") { - imports = `import "google/protobuf/timestamp.proto";` + packageImportStr := "" + var packageImportsArray = garray.NewStrArray() + if len(appendImports) > 0 { + for _, appendImport := range appendImports { + packageImportStr = fmt.Sprintf(`import "%s";`, appendImport) + if packageImportsArray.Search(packageImportStr) == -1 { + packageImportsArray.Append(packageImportStr) + } + } } entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{ - "{Imports}": imports, + "{Imports}": packageImportsArray.Join("\n"), "{PackageName}": gfile.Basename(in.Package), "{GoPackage}": in.Package, "{OptionContent}": in.Option, @@ -254,19 +378,24 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp if err := gfile.PutContents(path, strings.TrimSpace(entityContent)); err != nil { mlog.Fatalf("writing content to '%s' failed: %v", path, err) } else { - mlog.Print("generated:", path) + mlog.Print("generated:", gfile.RealPath(path)) } } // generateEntityMessageDefinition generates and returns the message definition for specified table. -func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in CGenPbEntityInternalInput) string { +func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in CGenPbEntityInternalInput) (string, []string) { var ( - buffer = bytes.NewBuffer(nil) - array = make([][]string, len(fieldMap)) - names = sortFieldKeyForPbEntity(fieldMap) + appendImports []string + buffer = bytes.NewBuffer(nil) + array = make([][]string, len(fieldMap)) + names = sortFieldKeyForPbEntity(fieldMap) ) for index, name := range names { - array[index] = generateMessageFieldForPbEntity(index+1, fieldMap[name], in) + var imports string + array[index], imports = generateMessageFieldForPbEntity(index+1, fieldMap[name], in) + if imports != "" { + appendImports = append(appendImports, imports) + } } tw := tablewriter.NewWriter(buffer) tw.SetBorder(false) @@ -277,48 +406,38 @@ func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb tw.Render() stContent := buffer.String() // Let's do this hack of table writer for indent! - stContent = gstr.Replace(stContent, " #", "") + stContent = regexp.MustCompile(`\s+\n`).ReplaceAllString(gstr.Replace(stContent, " #", ""), "\n") buffer.Reset() buffer.WriteString(fmt.Sprintf("message %s {\n", entityName)) buffer.WriteString(stContent) buffer.WriteString("}") - return buffer.String() + return buffer.String(), appendImports } // generateMessageFieldForPbEntity generates and returns the message definition for specified field. -func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) []string { +func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) (attrLines []string, appendImport string) { var ( - localTypeName gdb.LocalType - comment string - jsonTagStr string - err error - ctx = gctx.GetInitCtx() + localTypeNameStr string + localTypeName gdb.LocalType + comment string + jsonTagStr string + err error + ctx = gctx.GetInitCtx() ) - localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil) - if err != nil { - panic(err) + + if in.TypeMapping != nil && len(in.TypeMapping) > 0 { + localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil) + if err != nil { + panic(err) + } + if localTypeName != "" { + if typeMapping, ok := in.TypeMapping[strings.ToLower(string(localTypeName))]; ok { + localTypeNameStr = typeMapping.Type + appendImport = typeMapping.Import + } + } } - var typeMapping = map[gdb.LocalType]string{ - gdb.LocalTypeString: "string", - gdb.LocalTypeDate: "google.protobuf.Timestamp", - gdb.LocalTypeDatetime: "google.protobuf.Timestamp", - gdb.LocalTypeInt: "int32", - gdb.LocalTypeUint: "uint32", - gdb.LocalTypeInt64: "int64", - gdb.LocalTypeUint64: "uint64", - gdb.LocalTypeIntSlice: "repeated int32", - gdb.LocalTypeInt64Slice: "repeated int64", - gdb.LocalTypeUint64Slice: "repeated uint64", - gdb.LocalTypeInt64Bytes: "repeated int64", - gdb.LocalTypeUint64Bytes: "repeated uint64", - gdb.LocalTypeFloat32: "float", - gdb.LocalTypeFloat64: "double", - gdb.LocalTypeBytes: "bytes", - gdb.LocalTypeBool: "bool", - gdb.LocalTypeJson: "string", - gdb.LocalTypeJsonb: "string", - } - localTypeNameStr := typeMapping[localTypeName] + if localTypeNameStr == "" { localTypeNameStr = "string" } @@ -351,12 +470,19 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb newFiledName = gstr.TrimLeftStr(newFiledName, v, 1) } + if in.FieldMapping != nil && len(in.FieldMapping) > 0 { + if typeMapping, ok := in.FieldMapping[fmt.Sprintf("%s.%s", in.TableName, newFiledName)]; ok { + localTypeNameStr = typeMapping.Type + appendImport = typeMapping.Import + } + } + return []string{ " #" + localTypeNameStr, " #" + formatCase(newFiledName, in.NameCase), " #= " + gconv.String(index) + jsonTagStr + ";", " #" + fmt.Sprintf(`// %s`, comment), - } + }, appendImport } func getTplPbEntityContent(tplEntityPath string) string { diff --git a/cmd/gf/internal/cmd/genservice/genservice.go b/cmd/gf/internal/cmd/genservice/genservice.go index 5b9ae7efc..e02ed91ea 100644 --- a/cmd/gf/internal/cmd/genservice/genservice.go +++ b/cmd/gf/internal/cmd/genservice/genservice.go @@ -114,7 +114,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe return } } - defer gfile.Remove(flockFilePath) + defer gfile.RemoveFile(flockFilePath) _ = gfile.PutContents(flockFilePath, gtime.TimestampStr()) // It works only if given WatchFile is in SrcFolder. @@ -253,7 +253,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe utils.IsFileDoNotEdit(relativeFilePath) { mlog.Printf(`remove no longer used service file: %s`, relativeFilePath) - if err = gfile.Remove(file); err != nil { + if err = gfile.RemoveFile(file); err != nil { return nil, err } } @@ -289,7 +289,7 @@ func (c CGenService) checkAndUpdateMain(srcFolder string) (err error) { var ( logicPackageName = gstr.ToLower(gfile.Basename(srcFolder)) logicFilePath = gfile.Join(srcFolder, logicPackageName+".go") - importPath = utils.GetImportPath(logicFilePath) + importPath = utils.GetImportPath(srcFolder) importStr = fmt.Sprintf(`_ "%s"`, importPath) mainFilePath = gfile.Join(gfile.Dir(gfile.Dir(gfile.Dir(logicFilePath))), "main.go") mainFileContent = gfile.GetContents(mainFilePath) diff --git a/cmd/gf/internal/cmd/genservice/genservice_ast_parse.go b/cmd/gf/internal/cmd/genservice/genservice_ast_parse.go index 6a7785ffa..c4205cc58 100644 --- a/cmd/gf/internal/cmd/genservice/genservice_ast_parse.go +++ b/cmd/gf/internal/cmd/genservice/genservice_ast_parse.go @@ -12,6 +12,7 @@ import ( "go/token" "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/text/gstr" ) type pkgItem struct { @@ -78,12 +79,19 @@ func (c CGenService) parseImportPackages(node *ast.ImportSpec) (packages pkgItem path = node.Path.Value rawImport string ) + if node.Name != nil { alias = node.Name.Name - rawImport = alias + " " + path + rawImport = node.Name.Name + " " + path } else { rawImport = path } + + // if the alias is empty, it will further retrieve the real alias. + if alias == "" { + alias = c.getRealAlias(path) + } + return pkgItem{ Alias: alias, Path: path, @@ -91,6 +99,33 @@ func (c CGenService) parseImportPackages(node *ast.ImportSpec) (packages pkgItem } } +// getRealAlias retrieves the real alias of the package. +// If package is "github.com/gogf/gf", the alias is "gf". +// If package is "github.com/gogf/gf/v2", the alias is "gf" instead of "v2". +func (c CGenService) getRealAlias(importPath string) (pkgName string) { + importPath = gstr.Trim(importPath, `"`) + parts := gstr.Split(importPath, "/") + if len(parts) == 0 { + return + } + + pkgName = parts[len(parts)-1] + + if !gstr.HasPrefix(pkgName, "v") { + return pkgName + } + + if len(parts) < 2 { + return pkgName + } + + if gstr.IsNumeric(gstr.SubStr(pkgName, 1)) { + pkgName = parts[len(parts)-2] + } + + return pkgName +} + // parseFuncReceiverTypeName retrieves the receiver type of the function. // For example: // diff --git a/cmd/gf/internal/cmd/testdata/build/varmap/go.mod b/cmd/gf/internal/cmd/testdata/build/varmap/go.mod index 745729204..c8c721416 100644 --- a/cmd/gf/internal/cmd/testdata/build/varmap/go.mod +++ b/cmd/gf/internal/cmd/testdata/build/varmap/go.mod @@ -2,11 +2,11 @@ module github.com/gogf/gf/cmd/gf/cmd/gf/testdata/vardump/v2 go 1.18 -require github.com/gogf/gf/v2 v2.6.1 +require github.com/gogf/gf/v2 v2.8.1 require ( - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect ) replace github.com/gogf/gf/v2 => ../../../../../../../ diff --git a/cmd/gf/internal/cmd/testdata/build/varmap/go.sum b/cmd/gf/internal/cmd/testdata/build/varmap/go.sum index 4e5a51bb8..4f2c0c5da 100644 --- a/cmd/gf/internal/cmd/testdata/build/varmap/go.sum +++ b/cmd/gf/internal/cmd/testdata/build/varmap/go.sum @@ -1,27 +1,29 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/dao/internal/table_user.go b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/dao/internal/table_user.go new file mode 100644 index 000000000..3c84716f2 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/dao/internal/table_user.go @@ -0,0 +1,83 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// TableUserDao is the data access object for table table_user. +type TableUserDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of current DAO. + columns TableUserColumns // columns contains all the column names of Table for convenient usage. +} + +// TableUserColumns defines and stores column names for table table_user. +type TableUserColumns struct { + Id string // + Passport string // + Password string // + Nickname string // + CreatedAt string // + UpdatedAt string // +} + +// tableUserColumns holds the columns for table table_user. +var tableUserColumns = TableUserColumns{ + Id: "id", + Passport: "passport", + Password: "password", + Nickname: "nickname", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewTableUserDao creates and returns a new DAO object for table data access. +func NewTableUserDao() *TableUserDao { + return &TableUserDao{ + group: "test", + table: "table_user", + columns: tableUserColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of current DAO. +func (dao *TableUserDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of current dao. +func (dao *TableUserDao) Table() string { + return dao.table +} + +// Columns returns all column names of current dao. +func (dao *TableUserDao) Columns() TableUserColumns { + return dao.columns +} + +// Group returns the configuration group name of database of current dao. +func (dao *TableUserDao) Group() string { + return dao.group +} + +// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. +func (dao *TableUserDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rollbacks the transaction and returns the error from function f if it returns non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note that, you should not Commit or Rollback the transaction in function f +// as it is automatically handled by this function. +func (dao *TableUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/dao/table_user.go b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/dao/table_user.go new file mode 100644 index 000000000..9bc9cff6f --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/dao/table_user.go @@ -0,0 +1,27 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "for-gendao-test/pkg/dao/internal" +) + +// internalTableUserDao is internal type for wrapping internal DAO implements. +type internalTableUserDao = *internal.TableUserDao + +// tableUserDao is the data access object for table table_user. +// You can define custom methods on it to extend its functionality as you wish. +type tableUserDao struct { + internalTableUserDao +} + +var ( + // TableUser is globally public accessible object for table table_user operations. + TableUser = tableUserDao{ + internal.NewTableUserDao(), + } +) + +// Fill with you ideas below. diff --git a/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/model/do/table_user.go b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/model/do/table_user.go new file mode 100644 index 000000000..75fcb5db1 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/model/do/table_user.go @@ -0,0 +1,21 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// TableUser is the golang structure of table table_user for DAO operations like Where/Data. +type TableUser struct { + g.Meta `orm:"table:table_user, do:true"` + Id interface{} // + Passport interface{} // + Password interface{} // + Nickname interface{} // + CreatedAt *gtime.Time // + UpdatedAt *gtime.Time // +} diff --git a/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/model/entity/table_user.go b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/model/entity/table_user.go new file mode 100644 index 000000000..67ff1831a --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/gendao/generated_user_sqlite3/model/entity/table_user.go @@ -0,0 +1,19 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// TableUser is the golang structure for table table_user. +type TableUser struct { + Id int `json:"id" orm:"id" ` // + Passport string `json:"passport" orm:"passport" ` // + Password string `json:"password" orm:"password" ` // + Nickname string `json:"nickname" orm:"nickname" ` // + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" ` // + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" ` // +} diff --git a/cmd/gf/internal/cmd/testdata/gendao/sqlite3/user.sqlite3.sql b/cmd/gf/internal/cmd/testdata/gendao/sqlite3/user.sqlite3.sql new file mode 100644 index 000000000..16c602a12 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/gendao/sqlite3/user.sqlite3.sql @@ -0,0 +1,8 @@ +create table `%s`( + id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, + passport VARCHAR(45) NOT NULL DEFAULT passport, + password VARCHAR(128) NOT NULL DEFAULT password, + nickname VARCHAR(45), + created_at TIMESTAMP, + updated_at TIMESTAMP +) \ No newline at end of file diff --git a/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user.proto b/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user.proto index e5074b491..874a55a05 100644 --- a/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user.proto +++ b/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user.proto @@ -11,11 +11,11 @@ option go_package = "unittest"; import "google/protobuf/timestamp.proto"; message TableUser { - uint32 Id = 1; // User ID - string Passport = 2; // User Passport - string Password = 3; // User Password - string Nickname = 4; // User Nickname - string Score = 5; // Total score amount. - google.protobuf.Timestamp CreateAt = 6; // Created Time - google.protobuf.Timestamp UpdateAt = 7; // Updated Time + uint32 Id = 1; // User ID + string Passport = 2; // User Passport + string Password = 3; // User Password + string Nickname = 4; // User Nickname + string Score = 5; // Total score amount. + google.protobuf.Timestamp CreateAt = 6; // Created Time + google.protobuf.Timestamp UpdateAt = 7; // Updated Time } \ No newline at end of file diff --git a/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user_snake_screaming.proto b/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user_snake_screaming.proto index 365999ece..9613131da 100644 --- a/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user_snake_screaming.proto +++ b/cmd/gf/internal/cmd/testdata/genpbentity/generated/table_user_snake_screaming.proto @@ -11,11 +11,11 @@ option go_package = "unittest"; import "google/protobuf/timestamp.proto"; message TableUser { - uint32 ID = 1; // User ID - string PASSPORT = 2; // User Passport - string PASSWORD = 3; // User Password - string NICKNAME = 4; // User Nickname - string SCORE = 5; // Total score amount. - google.protobuf.Timestamp CREATE_AT = 6; // Created Time - google.protobuf.Timestamp UPDATE_AT = 7; // Updated Time + uint32 ID = 1; // User ID + string PASSPORT = 2; // User Passport + string PASSWORD = 3; // User Password + string NICKNAME = 4; // User Nickname + string SCORE = 5; // Total score amount. + google.protobuf.Timestamp CREATE_AT = 6; // Created Time + google.protobuf.Timestamp UPDATE_AT = 7; // Updated Time } \ No newline at end of file diff --git a/cmd/gf/internal/cmd/testdata/issue/3328/logic/.gitkeep b/cmd/gf/internal/cmd/testdata/issue/3328/logic/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/cmd/gf/internal/cmd/testdata/issue/3545/table_user.proto b/cmd/gf/internal/cmd/testdata/issue/3545/table_user.proto index 6282f3a61..2b95b4056 100644 --- a/cmd/gf/internal/cmd/testdata/issue/3545/table_user.proto +++ b/cmd/gf/internal/cmd/testdata/issue/3545/table_user.proto @@ -11,11 +11,11 @@ option go_package = "github.com/gogf/gf/cmd/gf/v2/internal/cmd/api/pbentity"; import "google/protobuf/timestamp.proto"; message TableUser { - uint32 Id = 1; // User ID - string Passport = 2; // User Passport - string Password = 3; // User Password - string Nickname = 4; // User Nickname - string Score = 5; // Total score amount. - google.protobuf.Timestamp CreateAt = 6; // Created Time - google.protobuf.Timestamp UpdateAt = 7; // Updated Time + uint32 Id = 1; // User ID + string Passport = 2; // User Passport + string Password = 3; // User Password + string Nickname = 4; // User Nickname + string Score = 5; // Total score amount. + google.protobuf.Timestamp CreateAt = 6; // Created Time + google.protobuf.Timestamp UpdateAt = 7; // Updated Time } \ No newline at end of file diff --git a/cmd/gf/internal/cmd/testdata/issue/3685/table_user.proto b/cmd/gf/internal/cmd/testdata/issue/3685/table_user.proto new file mode 100644 index 000000000..803cfa81f --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3685/table_user.proto @@ -0,0 +1,23 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +syntax = "proto3"; + +package pbentity; + +option go_package = "github.com/gogf/gf/cmd/gf/v2/internal/cmd/api/pbentity"; + +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; + +message TableUser { + uint32 Id = 1; // User ID + string Passport = 2; // User Passport + string Password = 3; // User Password + string Nickname = 4; // User Nickname + string Score = 5; // Total score amount. + google.protobuf.Value Data = 6; // User Data + google.protobuf.Timestamp CreateAt = 7; // Created Time + google.protobuf.Timestamp UpdateAt = 8; // Updated Time +} \ No newline at end of file diff --git a/cmd/gf/internal/cmd/testdata/issue/3685/user.tpl.sql b/cmd/gf/internal/cmd/testdata/issue/3685/user.tpl.sql new file mode 100644 index 000000000..87493a6f8 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3685/user.tpl.sql @@ -0,0 +1,11 @@ +CREATE TABLE `%s` ( + `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID', + `passport` varchar(45) NOT NULL COMMENT 'User Passport', + `password` varchar(45) NOT NULL COMMENT 'User Password', + `nickname` varchar(45) NOT NULL COMMENT 'User Nickname', + `score` decimal(10,2) unsigned DEFAULT NULL COMMENT 'Total score amount.', + `data` json DEFAULT NULL COMMENT 'User Data', + `create_at` datetime DEFAULT NULL COMMENT 'Created Time', + `update_at` datetime DEFAULT NULL COMMENT 'Updated Time', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; \ No newline at end of file diff --git a/cmd/gf/internal/cmd/testdata/issue/3749/dao/internal/table_user.go b/cmd/gf/internal/cmd/testdata/issue/3749/dao/internal/table_user.go new file mode 100644 index 000000000..871b7d657 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3749/dao/internal/table_user.go @@ -0,0 +1,85 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// TableUserDao is the data access object for table table_user. +type TableUserDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of current DAO. + columns TableUserColumns // columns contains all the column names of Table for convenient usage. +} + +// TableUserColumns defines and stores column names for table table_user. +type TableUserColumns struct { + Id string // User ID + ParentId string // + Passport string // User Passport + PassWord string // User Password + Nickname2 string // User Nickname + CreateAt string // Created Time + UpdateAt string // Updated Time +} + +// tableUserColumns holds the columns for table table_user. +var tableUserColumns = TableUserColumns{ + Id: "Id", + ParentId: "parentId", + Passport: "PASSPORT", + PassWord: "PASS_WORD", + Nickname2: "NICKNAME2", + CreateAt: "create_at", + UpdateAt: "update_at", +} + +// NewTableUserDao creates and returns a new DAO object for table data access. +func NewTableUserDao() *TableUserDao { + return &TableUserDao{ + group: "test", + table: "table_user", + columns: tableUserColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of current DAO. +func (dao *TableUserDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of current dao. +func (dao *TableUserDao) Table() string { + return dao.table +} + +// Columns returns all column names of current dao. +func (dao *TableUserDao) Columns() TableUserColumns { + return dao.columns +} + +// Group returns the configuration group name of database of current dao. +func (dao *TableUserDao) Group() string { + return dao.group +} + +// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. +func (dao *TableUserDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rollbacks the transaction and returns the error from function f if it returns non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note that, you should not Commit or Rollback the transaction in function f +// as it is automatically handled by this function. +func (dao *TableUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/cmd/gf/internal/cmd/testdata/issue/3749/dao/table_user.go b/cmd/gf/internal/cmd/testdata/issue/3749/dao/table_user.go new file mode 100644 index 000000000..9bc9cff6f --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3749/dao/table_user.go @@ -0,0 +1,27 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "for-gendao-test/pkg/dao/internal" +) + +// internalTableUserDao is internal type for wrapping internal DAO implements. +type internalTableUserDao = *internal.TableUserDao + +// tableUserDao is the data access object for table table_user. +// You can define custom methods on it to extend its functionality as you wish. +type tableUserDao struct { + internalTableUserDao +} + +var ( + // TableUser is globally public accessible object for table table_user operations. + TableUser = tableUserDao{ + internal.NewTableUserDao(), + } +) + +// Fill with you ideas below. diff --git a/cmd/gf/internal/cmd/testdata/issue/3749/model/do/table_user.go b/cmd/gf/internal/cmd/testdata/issue/3749/model/do/table_user.go new file mode 100644 index 000000000..6fe512a44 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3749/model/do/table_user.go @@ -0,0 +1,22 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// TableUser is the golang structure of table table_user for DAO operations like Where/Data. +type TableUser struct { + g.Meta `orm:"table:table_user, do:true"` + Id interface{} // User ID + ParentId interface{} // + Passport interface{} // User Passport + PassWord interface{} // User Password + Nickname2 interface{} // User Nickname + CreateAt *gtime.Time // Created Time + UpdateAt *gtime.Time // Updated Time +} diff --git a/cmd/gf/internal/cmd/testdata/issue/3749/model/entity/table_user.go b/cmd/gf/internal/cmd/testdata/issue/3749/model/entity/table_user.go new file mode 100644 index 000000000..effe0ce2c --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3749/model/entity/table_user.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// TableUser is the golang structure for table table_user. +type TableUser struct { + Id uint `json:"id" orm:"Id" ` // User ID + ParentId string `json:"parentId" orm:"parentId" ` // + Passport string `json:"pASSPORT" orm:"PASSPORT" ` // User Passport + PassWord string `json:"pASSWORD" orm:"PASS_WORD" ` // User Password + Nickname2 string `json:"nICKNAME2" orm:"NICKNAME2" ` // User Nickname + CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` // Created Time + UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` // Updated Time +} diff --git a/cmd/gf/internal/cmd/testdata/issue/3749/user.tpl.sql b/cmd/gf/internal/cmd/testdata/issue/3749/user.tpl.sql new file mode 100644 index 000000000..59896315c --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3749/user.tpl.sql @@ -0,0 +1,10 @@ +CREATE TABLE `%s` ( + `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID', + `parentId` varchar(45) NOT NULL COMMENT '', + `PASSPORT` varchar(45) NOT NULL COMMENT 'User Passport', + `PASS_WORD` varchar(45) NOT NULL COMMENT 'User Password', + `NICKNAME2` varchar(45) NOT NULL COMMENT 'User Nickname', + `create_at` datetime DEFAULT NULL COMMENT 'Created Time', + `update_at` datetime DEFAULT NULL COMMENT 'Updated Time', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/cmd/gf/internal/cmd/testdata/issue/3835/logic/issue3835/issue3835.go b/cmd/gf/internal/cmd/testdata/issue/3835/logic/issue3835/issue3835.go new file mode 100644 index 000000000..888b5a994 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3835/logic/issue3835/issue3835.go @@ -0,0 +1,23 @@ +package issue3835 + +import ( + "context" + + "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/issue/3835/service" + "github.com/gogf/gf/contrib/drivers/mysql/v2" +) + +func init() { + service.RegisterItest(New()) +} + +type sItest struct { +} + +func New() *sItest { + return &sItest{} +} + +func (s *sItest) F(ctx context.Context) (d mysql.Driver, err error) { + return mysql.Driver{}, nil +} diff --git a/cmd/gf/internal/cmd/testdata/issue/3835/logic/logic.go b/cmd/gf/internal/cmd/testdata/issue/3835/logic/logic.go new file mode 100644 index 000000000..acb117df3 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3835/logic/logic.go @@ -0,0 +1,9 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package logic + +import ( + _ "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/issue/3835/logic/issue3835" +) diff --git a/cmd/gf/internal/cmd/testdata/issue/3835/service/issue_3835.go b/cmd/gf/internal/cmd/testdata/issue/3835/service/issue_3835.go new file mode 100644 index 000000000..7ae835570 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3835/service/issue_3835.go @@ -0,0 +1,33 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + + "github.com/gogf/gf/contrib/drivers/mysql/v2" +) + +type ( + IItest interface { + F(ctx context.Context) (d mysql.Driver, err error) + } +) + +var ( + localItest IItest +) + +func Itest() IItest { + if localItest == nil { + panic("implement not found for interface IItest, forgot register?") + } + return localItest +} + +func RegisterItest(i IItest) { + localItest = i +} diff --git a/cmd/gf/internal/cmd/testdata/issue/3882/issue3882.proto b/cmd/gf/internal/cmd/testdata/issue/3882/issue3882.proto new file mode 100644 index 000000000..b37d037e6 --- /dev/null +++ b/cmd/gf/internal/cmd/testdata/issue/3882/issue3882.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package test; + +option go_package = "github.com/gogf/gf/cmd/gf/test"; + +message SomeMessage { + // Some comment on field with "one" `two` 'three' in the comment. + string field = 1; +} \ No newline at end of file diff --git a/cmd/gf/internal/packed/template-mono-app.go b/cmd/gf/internal/packed/template-mono-app.go index 3df41147c..46fb81ca9 100644 --- a/cmd/gf/internal/packed/template-mono-app.go +++ b/cmd/gf/internal/packed/template-mono-app.go @@ -3,7 +3,7 @@ package packed import "github.com/gogf/gf/v2/os/gres" func init() { - if err := gres.Add("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"); err != nil { + if err := gres.Add("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"); err != nil { panic("add binary content to resource manager failed: " + err.Error()) } } diff --git a/cmd/gf/internal/packed/template-mono.go b/cmd/gf/internal/packed/template-mono.go index 67c325d75..97f98f20c 100644 --- a/cmd/gf/internal/packed/template-mono.go +++ b/cmd/gf/internal/packed/template-mono.go @@ -3,7 +3,7 @@ package packed import "github.com/gogf/gf/v2/os/gres" func init() { - if err := gres.Add("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"); err != nil { + if err := gres.Add("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"); err != nil { panic("add binary content to resource manager failed: " + err.Error()) } } diff --git a/cmd/gf/internal/packed/template-single.go b/cmd/gf/internal/packed/template-single.go index 37510b84f..c95abb834 100644 --- a/cmd/gf/internal/packed/template-single.go +++ b/cmd/gf/internal/packed/template-single.go @@ -3,7 +3,7 @@ package packed import "github.com/gogf/gf/v2/os/gres" func init() { - if err := gres.Add("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"); err != nil { + if err := gres.Add("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"); err != nil { panic("add binary content to resource manager failed: " + err.Error()) } } diff --git a/cmd/gf/internal/utility/utils/utils.go b/cmd/gf/internal/utility/utils/utils.go index 66625079a..94047db19 100644 --- a/cmd/gf/internal/utility/utils/utils.go +++ b/cmd/gf/internal/utility/utils/utils.go @@ -75,28 +75,24 @@ func ReplaceGeneratedContentGFV2(folderPath string) (err error) { }, folderPath, "*.go", true) } -// GetImportPath calculates and returns the golang import path for given `filePath`. +// GetImportPath calculates and returns the golang import path for given `dirPath`. // Note that it needs a `go.mod` in current working directory or parent directories to detect the path. -func GetImportPath(filePath string) string { +func GetImportPath(dirPath string) string { // If `filePath` does not exist, create it firstly to find the import path. - var realPath = gfile.RealPath(filePath) + var realPath = gfile.RealPath(dirPath) if realPath == "" { - _ = gfile.Mkdir(filePath) - realPath = gfile.RealPath(filePath) + _ = gfile.Mkdir(dirPath) + realPath = gfile.RealPath(dirPath) } var ( newDir = gfile.Dir(realPath) oldDir string - suffix string + suffix = gfile.Basename(dirPath) goModName = "go.mod" goModPath string importPath string ) - - if gfile.IsDir(filePath) { - suffix = gfile.Basename(filePath) - } for { goModPath = gfile.Join(newDir, goModName) if gfile.Exists(goModPath) { diff --git a/container/glist/glist_z_unit_test.go b/container/glist/glist_z_unit_test.go index 36984790f..d530f0973 100644 --- a/container/glist/glist_z_unit_test.go +++ b/container/glist/glist_z_unit_test.go @@ -291,7 +291,7 @@ func TestRemove(t *testing.T) { }) } -func TestIssue4103(t *testing.T) { +func Test_Issue4103(t *testing.T) { l1 := New() l1.PushBack(1) l1.PushBack(2) @@ -312,7 +312,7 @@ func TestIssue4103(t *testing.T) { } } -func TestIssue6349(t *testing.T) { +func Test_Issue6349(t *testing.T) { l := New() l.PushBack(1) l.PushBack(2) diff --git a/container/gtree/gtree.go b/container/gtree/gtree.go index 284ffbd4f..185c7c020 100644 --- a/container/gtree/gtree.go +++ b/container/gtree/gtree.go @@ -13,66 +13,77 @@ import "github.com/gogf/gf/v2/container/gvar" // iTree defines the interface for basic operations of a tree. type iTree interface { - // Set inserts node into the tree. + // Set sets key-value pair into the tree. Set(key interface{}, value interface{}) // Sets batch sets key-values to the tree. Sets(data map[interface{}]interface{}) // SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true. - // It returns false if `key` exists, and `value` would be ignored. + // It returns false if `key` exists, and such setting key-value pair operation would be ignored. SetIfNotExist(key interface{}, value interface{}) bool // SetIfNotExistFunc sets value with return value of callback function `f`, and then returns true. - // It returns false if `key` exists, and `value` would be ignored. + // It returns false if `key` exists, and such setting key-value pair operation would be ignored. SetIfNotExistFunc(key interface{}, f func() interface{}) bool // SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true. - // It returns false if `key` exists, and `value` would be ignored. + // It returns false if `key` exists, and such setting key-value pair operation would be ignored. + // // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that - // it executes function `f` with mutex.Lock of the hash map. + // it executes function `f` within mutex.Lock of the hash map. SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool - // Get searches the node in the tree by `key` and returns its value or nil if key is not found in tree. + // Get searches the `key` in the tree and returns its associated `value` or nil if key is not found in tree. + // + // Note that, the `nil` value from Get function cannot be used to determine key existence, please use Contains + // function to do so. Get(key interface{}) (value interface{}) - // GetOrSet returns the value by key, - // or sets value with given `value` if it does not exist and then returns this value. + // GetOrSet returns its `value` of `key`, or sets value with given `value` if it does not exist and then returns + // this value. GetOrSet(key interface{}, value interface{}) interface{} - // GetOrSetFunc returns the value by key, - // or sets value with returned value of callback function `f` if it does not exist - // and then returns this value. + // GetOrSetFunc returns its `value` of `key`, or sets value with returned value of callback function `f` if it does + // not exist and then returns this value. GetOrSetFunc(key interface{}, f func() interface{}) interface{} - // GetOrSetFuncLock returns the value by key, - // or sets value with returned value of callback function `f` if it does not exist - // and then returns this value. - // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` - // with mutex.Lock of the hash map. + // GetOrSetFuncLock returns its `value` of `key`, or sets value with returned value of callback function `f` if it + // does not exist and then returns this value. + // + // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` within mutex.Lock of the + // hash map. GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} // GetVar returns a gvar.Var with the value by given `key`. - // The returned gvar.Var is un-concurrent safe. + // Note that, the returned gvar.Var is un-concurrent safe. + // + // Also see function Get. GetVar(key interface{}) *gvar.Var // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. - // The returned gvar.Var is un-concurrent safe. + // Note that, the returned gvar.Var is un-concurrent safe. + // + // Also see function GetOrSet. GetVarOrSet(key interface{}, value interface{}) *gvar.Var // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. - // The returned gvar.Var is un-concurrent safe. + // Note that, the returned gvar.Var is un-concurrent safe. + // + // Also see function GetOrSetFunc. GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. - // The returned gvar.Var is un-concurrent safe. + // Note that, the returned gvar.Var is un-concurrent safe. + // + // Also see function GetOrSetFuncLock. GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var // Search searches the tree with given `key`. // Second return parameter `found` is true if key was found, otherwise false. Search(key interface{}) (value interface{}, found bool) - // Contains checks whether `key` exists in the tree. + // Contains checks and returns whether given `key` exists in the tree. Contains(key interface{}) bool // Size returns number of nodes in the tree. @@ -81,23 +92,23 @@ type iTree interface { // IsEmpty returns true if tree does not contain any nodes. IsEmpty() bool - // Remove removes the node from the tree by key. - // Key should adhere to the comparator's type assertion, otherwise method panics. + // Remove removes the node from the tree by `key`, and returns its associated value of `key`. + // The given `key` should adhere to the comparator's type assertion, otherwise method panics. Remove(key interface{}) (value interface{}) - // Removes batch deletes values of the tree by `keys`. + // Removes batch deletes key-value pairs from the tree by `keys`. Removes(keys []interface{}) // Clear removes all nodes from the tree. Clear() - // Keys returns all keys in asc order. + // Keys returns all keys from the tree in order by its comparator. Keys() []interface{} - // Values returns all values in asc order based on the key. + // Values returns all values from the true in order by its comparator based on the key. Values() []interface{} - // Replace the data of the tree with given `data`. + // Replace clears the data of the tree and sets the nodes by given `data`. Replace(data map[interface{}]interface{}) // Print prints the tree to stdout. @@ -109,32 +120,66 @@ type iTree interface { // MarshalJSON implements the interface MarshalJSON for json.Marshal. MarshalJSON() (jsonBytes []byte, err error) + // Map returns all key-value pairs as map. Map() map[interface{}]interface{} + + // MapStrAny returns all key-value items as map[string]any. MapStrAny() map[string]interface{} // Iterator is alias of IteratorAsc. + // + // Also see IteratorAsc. Iterator(f func(key, value interface{}) bool) // IteratorFrom is alias of IteratorAscFrom. + // + // Also see IteratorAscFrom. IteratorFrom(key interface{}, match bool, f func(key, value interface{}) bool) // IteratorAsc iterates the tree readonly in ascending order with given callback function `f`. - // If `f` returns true, then it continues iterating; or false to stop. + // If callback function `f` returns true, then it continues iterating; or false to stop. IteratorAsc(f func(key, value interface{}) bool) // IteratorAscFrom iterates the tree readonly in ascending order with given callback function `f`. - // The parameter `key` specifies the start entry for iterating. The `match` specifies whether - // starting iterating if the `key` is fully matched, or else using index searching iterating. - // If `f` returns true, then it continues iterating; or false to stop. + // + // The parameter `key` specifies the start entry for iterating. + // The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using + // index searching iterating. + // If callback function `f` returns true, then it continues iterating; or false to stop. IteratorAscFrom(key interface{}, match bool, f func(key, value interface{}) bool) // IteratorDesc iterates the tree readonly in descending order with given callback function `f`. - // If `f` returns true, then it continues iterating; or false to stop. + // + // If callback function `f` returns true, then it continues iterating; or false to stop. IteratorDesc(f func(key, value interface{}) bool) // IteratorDescFrom iterates the tree readonly in descending order with given callback function `f`. - // The parameter `key` specifies the start entry for iterating. The `match` specifies whether - // starting iterating if the `key` is fully matched, or else using index searching iterating. - // If `f` returns true, then it continues iterating; or false to stop. + // + // The parameter `key` specifies the start entry for iterating. + // The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using + // index searching iterating. + // If callback function `f` returns true, then it continues iterating; or false to stop. IteratorDescFrom(key interface{}, match bool, f func(key, value interface{}) bool) } + +// iteratorFromGetIndex returns the index of the key in the keys slice. +// +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, +// or else using index searching iterating. +// If `isIterator` is true, iterator is available; or else not. +func iteratorFromGetIndex(key any, keys []any, match bool) (index int, canIterator bool) { + if match { + for i, k := range keys { + if k == key { + canIterator = true + index = i + } + } + } else { + if i, ok := key.(int); ok { + canIterator = true + index = i + } + } + return +} diff --git a/container/gtree/gtree_avltree.go b/container/gtree/gtree_avltree.go index 49c359369..ac8a51a86 100644 --- a/container/gtree/gtree_avltree.go +++ b/container/gtree/gtree_avltree.go @@ -22,20 +22,21 @@ var _ iTree = (*AVLTree)(nil) type AVLTree struct { mu rwmutex.RWMutex root *AVLTreeNode - comparator func(v1, v2 interface{}) int + comparator func(v1, v2 any) int tree *avltree.Tree } // AVLTreeNode is a single element within the tree. type AVLTreeNode struct { - Key interface{} - Value interface{} + Key any + Value any } // NewAVLTree instantiates an AVL tree with the custom key comparator. +// // The parameter `safe` is used to specify whether using tree in concurrent-safety, // which is false in default. -func NewAVLTree(comparator func(v1, v2 interface{}) int, safe ...bool) *AVLTree { +func NewAVLTree(comparator func(v1, v2 any) int, safe ...bool) *AVLTree { return &AVLTree{ mu: rwmutex.Create(safe...), comparator: comparator, @@ -44,9 +45,9 @@ func NewAVLTree(comparator func(v1, v2 interface{}) int, safe ...bool) *AVLTree } // NewAVLTreeFrom instantiates an AVL tree with the custom key comparator and data map. -// The parameter `safe` is used to specify whether using tree in concurrent-safety, -// which is false in default. -func NewAVLTreeFrom(comparator func(v1, v2 interface{}) int, data map[interface{}]interface{}, safe ...bool) *AVLTree { +// +// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default. +func NewAVLTreeFrom(comparator func(v1, v2 any) int, data map[any]any, safe ...bool) *AVLTree { tree := NewAVLTree(comparator, safe...) for k, v := range data { tree.doSet(k, v) @@ -54,22 +55,22 @@ func NewAVLTreeFrom(comparator func(v1, v2 interface{}) int, data map[interface{ return tree } -// Clone returns a new tree with a copy of current tree. +// Clone clones and returns a new tree from current tree. func (tree *AVLTree) Clone() *AVLTree { newTree := NewAVLTree(tree.comparator, tree.mu.IsSafe()) newTree.Sets(tree.Map()) return newTree } -// Set inserts node into the tree. -func (tree *AVLTree) Set(key interface{}, value interface{}) { +// Set sets key-value pair into the tree. +func (tree *AVLTree) Set(key any, value any) { tree.mu.Lock() defer tree.mu.Unlock() tree.doSet(key, value) } // Sets batch sets key-values to the tree. -func (tree *AVLTree) Sets(data map[interface{}]interface{}) { +func (tree *AVLTree) Sets(data map[any]any) { tree.mu.Lock() defer tree.mu.Unlock() for key, value := range data { @@ -78,8 +79,8 @@ func (tree *AVLTree) Sets(data map[interface{}]interface{}) { } // SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. -func (tree *AVLTree) SetIfNotExist(key interface{}, value interface{}) bool { +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. +func (tree *AVLTree) SetIfNotExist(key any, value any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -90,8 +91,8 @@ func (tree *AVLTree) SetIfNotExist(key interface{}, value interface{}) bool { } // SetIfNotExistFunc sets value with return value of callback function `f`, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. -func (tree *AVLTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. +func (tree *AVLTree) SetIfNotExistFunc(key any, f func() any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -102,11 +103,11 @@ func (tree *AVLTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bo } // SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. // // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that -// it executes function `f` with mutex.Lock of the hash map. -func (tree *AVLTree) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { +// it executes function `f` within mutex lock. +func (tree *AVLTree) SetIfNotExistFuncLock(key any, f func() any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -116,15 +117,18 @@ func (tree *AVLTree) SetIfNotExistFuncLock(key interface{}, f func() interface{} return false } -// Get searches the node in the tree by `key` and returns its value or nil if key is not found in tree. -func (tree *AVLTree) Get(key interface{}) (value interface{}) { +// Get searches the `key` in the tree and returns its associated `value` or nil if key is not found in tree. +// +// Note that, the `nil` value from Get function cannot be used to determine key existence, please use Contains function +// to do so. +func (tree *AVLTree) Get(key any) (value any) { value, _ = tree.Search(key) return } -// GetOrSet returns the value by key, -// or sets value with given `value` if it does not exist and then returns this value. -func (tree *AVLTree) GetOrSet(key interface{}, value interface{}) interface{} { +// GetOrSet returns its `value` of `key`, or sets value with given `value` if it does not exist and then returns +// this value. +func (tree *AVLTree) GetOrSet(key any, value any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -134,10 +138,9 @@ func (tree *AVLTree) GetOrSet(key interface{}, value interface{}) interface{} { } } -// GetOrSetFunc returns the value by key, -// or sets value with returned value of callback function `f` if it does not exist -// and then returns this value. -func (tree *AVLTree) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { +// GetOrSetFunc returns its `value` of `key`, or sets value with returned value of callback function `f` if it does not +// exist and then returns this value. +func (tree *AVLTree) GetOrSetFunc(key any, f func() any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -147,13 +150,11 @@ func (tree *AVLTree) GetOrSetFunc(key interface{}, f func() interface{}) interfa } } -// GetOrSetFuncLock returns the value by key, -// or sets value with returned value of callback function `f` if it does not exist -// and then returns this value. +// GetOrSetFuncLock returns its `value` of `key`, or sets value with returned value of callback function `f` if it does +// not exist and then returns this value. // -// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` -// with mutex.Lock of the hash map. -func (tree *AVLTree) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` within mutex lock. +func (tree *AVLTree) GetOrSetFuncLock(key any, f func() any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -164,32 +165,40 @@ func (tree *AVLTree) GetOrSetFuncLock(key interface{}, f func() interface{}) int } // GetVar returns a gvar.Var with the value by given `key`. -// The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVar(key interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function Get. +func (tree *AVLTree) GetVar(key any) *gvar.Var { return gvar.New(tree.Get(key)) } // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. -// The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSet. +func (tree *AVLTree) GetVarOrSet(key any, value any) *gvar.Var { return gvar.New(tree.GetOrSet(key, value)) } // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. -// The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSetFunc. +func (tree *AVLTree) GetVarOrSetFunc(key any, f func() any) *gvar.Var { return gvar.New(tree.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. -// The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSetFuncLock. +func (tree *AVLTree) GetVarOrSetFuncLock(key any, f func() any) *gvar.Var { return gvar.New(tree.GetOrSetFuncLock(key, f)) } // Search searches the tree with given `key`. // Second return parameter `found` is true if key was found, otherwise false. -func (tree *AVLTree) Search(key interface{}) (value interface{}, found bool) { +func (tree *AVLTree) Search(key any) (value any, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() if node, found := tree.doGet(key); found { @@ -198,8 +207,8 @@ func (tree *AVLTree) Search(key interface{}) (value interface{}, found bool) { return nil, false } -// Contains checks whether `key` exists in the tree. -func (tree *AVLTree) Contains(key interface{}) bool { +// Contains checks and returns whether given `key` exists in the tree. +func (tree *AVLTree) Contains(key any) bool { tree.mu.RLock() defer tree.mu.RUnlock() _, ok := tree.doGet(key) @@ -213,23 +222,23 @@ func (tree *AVLTree) Size() int { return tree.tree.Size() } -// IsEmpty returns true if tree does not contain any nodes. +// IsEmpty returns true if the tree does not contain any nodes. func (tree *AVLTree) IsEmpty() bool { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Size() == 0 } -// Remove removes the node from the tree by key. -// Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *AVLTree) Remove(key interface{}) (value interface{}) { +// Remove removes the node from the tree by `key`, and returns its associated value of `key`. +// The given `key` should adhere to the comparator's type assertion, otherwise method panics. +func (tree *AVLTree) Remove(key any) (value any) { tree.mu.Lock() defer tree.mu.Unlock() return tree.doRemove(key) } -// Removes batch deletes values of the tree by `keys`. -func (tree *AVLTree) Removes(keys []interface{}) { +// Removes batch deletes key-value pairs from the tree by `keys`. +func (tree *AVLTree) Removes(keys []any) { tree.mu.Lock() defer tree.mu.Unlock() for _, key := range keys { @@ -244,22 +253,22 @@ func (tree *AVLTree) Clear() { tree.tree.Clear() } -// Keys returns all keys in asc order. -func (tree *AVLTree) Keys() []interface{} { +// Keys returns all keys from the tree in order by its comparator. +func (tree *AVLTree) Keys() []any { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Keys() } -// Values returns all values in asc order based on the key. -func (tree *AVLTree) Values() []interface{} { +// Values returns all values from the true in order by its comparator based on the key. +func (tree *AVLTree) Values() []any { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Values() } -// Replace the data of the tree with given `data`. -func (tree *AVLTree) Replace(data map[interface{}]interface{}) { +// Replace clears the data of the tree and sets the nodes by given `data`. +func (tree *AVLTree) Replace(data map[any]any) { tree.mu.Lock() defer tree.mu.Unlock() tree.tree.Clear() @@ -273,7 +282,7 @@ func (tree *AVLTree) Print() { fmt.Println(tree.String()) } -// String returns a string representation of container +// String returns a string representation of container. func (tree *AVLTree) String() string { tree.mu.RLock() defer tree.mu.RUnlock() @@ -287,24 +296,20 @@ func (tree *AVLTree) MarshalJSON() (jsonBytes []byte, err error) { return tree.tree.MarshalJSON() } -// Map returns all key-value items as map. -func (tree *AVLTree) Map() map[interface{}]interface{} { - tree.mu.RLock() - defer tree.mu.RUnlock() - m := make(map[interface{}]interface{}, tree.Size()) - tree.IteratorAsc(func(key, value interface{}) bool { +// Map returns all key-value pairs as map. +func (tree *AVLTree) Map() map[any]any { + m := make(map[any]any, tree.Size()) + tree.IteratorAsc(func(key, value any) bool { m[key] = value return true }) return m } -// MapStrAny returns all key-value items as map[string]interface{}. -func (tree *AVLTree) MapStrAny() map[string]interface{} { - tree.mu.RLock() - defer tree.mu.RUnlock() - m := make(map[string]interface{}, tree.Size()) - tree.IteratorAsc(func(key, value interface{}) bool { +// MapStrAny returns all key-value items as map[string]any. +func (tree *AVLTree) MapStrAny() map[string]any { + m := make(map[string]any, tree.Size()) + tree.IteratorAsc(func(key, value any) bool { m[gconv.String(key)] = value return true }) @@ -312,39 +317,48 @@ func (tree *AVLTree) MapStrAny() map[string]interface{} { } // Iterator is alias of IteratorAsc. -func (tree *AVLTree) Iterator(f func(key, value interface{}) bool) { +// +// Also see IteratorAsc. +func (tree *AVLTree) Iterator(f func(key, value any) bool) { tree.IteratorAsc(f) } // IteratorFrom is alias of IteratorAscFrom. -func (tree *AVLTree) IteratorFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// Also see IteratorAscFrom. +func (tree *AVLTree) IteratorFrom(key any, match bool, f func(key, value any) bool) { tree.IteratorAscFrom(key, match, f) } // IteratorAsc iterates the tree readonly in ascending order with given callback function `f`. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *AVLTree) IteratorAsc(f func(key, value interface{}) bool) { +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *AVLTree) IteratorAsc(f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() - it := tree.tree.Iterator() + var ( + ok bool + it = tree.tree.Iterator() + ) for it.Begin(); it.Next(); { index, value := it.Key(), it.Value() - if ok := f(index, value); !ok { + if ok = f(index, value); !ok { break } } } // IteratorAscFrom iterates the tree readonly in ascending order with given callback function `f`. -// The parameter `key` specifies the start entry for iterating. The `match` specifies whether -// starting iterating if the `key` is fully matched, or else using index searching iterating. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *AVLTree) IteratorAscFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// The parameter `key` specifies the start entry for iterating. +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using index +// searching iterating. +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *AVLTree) IteratorAscFrom(key any, match bool, f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() var keys = tree.tree.Keys() - index, isIterator := tree.iteratorFromGetIndex(key, keys, match) - if !isIterator { + index, canIterator := iteratorFromGetIndex(key, keys, match) + if !canIterator { return } for ; index < len(keys); index++ { @@ -353,29 +367,35 @@ func (tree *AVLTree) IteratorAscFrom(key interface{}, match bool, f func(key, va } // IteratorDesc iterates the tree readonly in descending order with given callback function `f`. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *AVLTree) IteratorDesc(f func(key, value interface{}) bool) { +// +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *AVLTree) IteratorDesc(f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() - it := tree.tree.Iterator() + var ( + ok bool + it = tree.tree.Iterator() + ) for it.End(); it.Prev(); { index, value := it.Key(), it.Value() - if ok := f(index, value); !ok { + if ok = f(index, value); !ok { break } } } // IteratorDescFrom iterates the tree readonly in descending order with given callback function `f`. -// The parameter `key` specifies the start entry for iterating. The `match` specifies whether -// starting iterating if the `key` is fully matched, or else using index searching iterating. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *AVLTree) IteratorDescFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// The parameter `key` specifies the start entry for iterating. +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using index +// searching iterating. +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *AVLTree) IteratorDescFrom(key any, match bool, f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() var keys = tree.tree.Keys() - index, isIterator := tree.iteratorFromGetIndex(key, keys, match) - if !isIterator { + index, canIterator := iteratorFromGetIndex(key, keys, match) + if !canIterator { return } for ; index >= 0; index-- { @@ -383,8 +403,7 @@ func (tree *AVLTree) IteratorDescFrom(key interface{}, match bool, f func(key, v } } -// Left returns the minimum element of the AVL tree -// or nil if the tree is empty. +// Left returns the minimum element corresponding to the comparator of the tree or nil if the tree is empty. func (tree *AVLTree) Left() *AVLTreeNode { tree.mu.RLock() defer tree.mu.RUnlock() @@ -398,8 +417,7 @@ func (tree *AVLTree) Left() *AVLTreeNode { } } -// Right returns the maximum element of the AVL tree -// or nil if the tree is empty. +// Right returns the maximum element corresponding to the comparator of the tree or nil if the tree is empty. func (tree *AVLTree) Right() *AVLTreeNode { tree.mu.RLock() defer tree.mu.RUnlock() @@ -413,19 +431,19 @@ func (tree *AVLTree) Right() *AVLTreeNode { } } -// Floor Finds floor node of the input key, return the floor node or nil if no floor node is found. -// Second return parameter is true if floor was found, otherwise false. +// Floor Finds floor node of the input key, returns the floor node or nil if no floor node is found. +// The second returned parameter `found` is true if floor was found, otherwise false. // // Floor node is defined as the largest node that is smaller than or equal to the given node. // A floor node may not be found, either because the tree is empty, or because // all nodes in the tree is larger than the given node. // // Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *AVLTree) Floor(key interface{}) (floor *AVLTreeNode, found bool) { +func (tree *AVLTree) Floor(key any) (floor *AVLTreeNode, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() - node, found := tree.tree.Floor(key) - if !found { + node, ok := tree.tree.Floor(key) + if !ok { return nil, false } return &AVLTreeNode{ @@ -434,19 +452,19 @@ func (tree *AVLTree) Floor(key interface{}) (floor *AVLTreeNode, found bool) { }, true } -// Ceiling finds ceiling node of the input key, return the ceiling node or nil if no ceiling node is found. -// Second return parameter is true if ceiling was found, otherwise false. +// Ceiling finds ceiling node of the input key, returns the ceiling node or nil if no ceiling node is found. +// The second return parameter `found` is true if ceiling was found, otherwise false. // // Ceiling node is defined as the smallest node that is larger than or equal to the given node. // A ceiling node may not be found, either because the tree is empty, or because // all nodes in the tree is smaller than the given node. // // Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *AVLTree) Ceiling(key interface{}) (ceiling *AVLTreeNode, found bool) { +func (tree *AVLTree) Ceiling(key any) (ceiling *AVLTreeNode, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() - node, found := tree.tree.Ceiling(key) - if !found { + node, ok := tree.tree.Ceiling(key) + if !ok { return nil, false } return &AVLTreeNode{ @@ -460,14 +478,14 @@ func (tree *AVLTree) Ceiling(key interface{}) (ceiling *AVLTreeNode, found bool) // or else the comparator would panic. // // If the type of value is different with key, you pass the new `comparator`. -func (tree *AVLTree) Flip(comparator ...func(v1, v2 interface{}) int) { +func (tree *AVLTree) Flip(comparator ...func(v1, v2 any) int) { var t = new(AVLTree) if len(comparator) > 0 { t = NewAVLTree(comparator[0], tree.mu.IsSafe()) } else { t = NewAVLTree(tree.comparator, tree.mu.IsSafe()) } - tree.IteratorAsc(func(key, value interface{}) bool { + tree.IteratorAsc(func(key, value any) bool { t.doSet(value, key) return true }) @@ -475,9 +493,13 @@ func (tree *AVLTree) Flip(comparator ...func(v1, v2 interface{}) int) { tree.Sets(t.Map()) } -// doSet sets key-value pair to the tree. -func (tree *AVLTree) doSet(key, value interface{}) interface{} { - if f, ok := value.(func() interface{}); ok { +// doSet inserts key-value pair node into the tree without lock. +// If `key` already exists, then its value is updated with the new value. +// If `value` is type of , it will be executed and its return value will be set to the map with `key`. +// +// It returns value with given `key`. +func (tree *AVLTree) doSet(key, value any) any { + if f, ok := value.(func() any); ok { value = f() } if value == nil { @@ -487,35 +509,15 @@ func (tree *AVLTree) doSet(key, value interface{}) interface{} { return value } -// doGet retrieves and returns the value of given key from tree. -func (tree *AVLTree) doGet(key interface{}) (value interface{}, found bool) { +// doGet retrieves and returns the value of given key from tree without lock. +func (tree *AVLTree) doGet(key any) (value any, found bool) { return tree.tree.Get(key) } -// doRemove removes key from tree. -func (tree *AVLTree) doRemove(key interface{}) (value interface{}) { +// doRemove removes key from tree and returns its associated value without lock. +// Note that, the given `key` should adhere to the comparator's type assertion, otherwise method panics. +func (tree *AVLTree) doRemove(key any) (value any) { value, _ = tree.tree.Get(key) tree.tree.Remove(key) return } - -// iteratorFromGetIndex returns the index of the key in the keys slice. -// The parameter `match` specifies whether starting iterating if the `key` is fully matched, -// or else using index searching iterating. -// If `isIterator` is true, iterator is available; or else not. -func (tree *AVLTree) iteratorFromGetIndex(key interface{}, keys []interface{}, match bool) (index int, isIterator bool) { - if match { - for i, k := range keys { - if k == key { - isIterator = true - index = i - } - } - } else { - if i, ok := key.(int); ok { - isIterator = true - index = i - } - } - return -} diff --git a/container/gtree/gtree_btree.go b/container/gtree/gtree_btree.go index a7b56c538..59f450533 100644 --- a/container/gtree/gtree_btree.go +++ b/container/gtree/gtree_btree.go @@ -21,22 +21,22 @@ var _ iTree = (*BTree)(nil) // BTree holds elements of the B-tree. type BTree struct { mu rwmutex.RWMutex - comparator func(v1, v2 interface{}) int + comparator func(v1, v2 any) int m int // order (maximum number of children) tree *btree.Tree } // BTreeEntry represents the key-value pair contained within nodes. type BTreeEntry struct { - Key interface{} - Value interface{} + Key any + Value any } // NewBTree instantiates a B-tree with `m` (maximum number of children) and a custom key comparator. // The parameter `safe` is used to specify whether using tree in concurrent-safety, // which is false in default. // Note that the `m` must be greater or equal than 3, or else it panics. -func NewBTree(m int, comparator func(v1, v2 interface{}) int, safe ...bool) *BTree { +func NewBTree(m int, comparator func(v1, v2 any) int, safe ...bool) *BTree { return &BTree{ mu: rwmutex.Create(safe...), m: m, @@ -48,7 +48,7 @@ func NewBTree(m int, comparator func(v1, v2 interface{}) int, safe ...bool) *BTr // NewBTreeFrom instantiates a B-tree with `m` (maximum number of children), a custom key comparator and data map. // The parameter `safe` is used to specify whether using tree in concurrent-safety, // which is false in default. -func NewBTreeFrom(m int, comparator func(v1, v2 interface{}) int, data map[interface{}]interface{}, safe ...bool) *BTree { +func NewBTreeFrom(m int, comparator func(v1, v2 any) int, data map[any]any, safe ...bool) *BTree { tree := NewBTree(m, comparator, safe...) for k, v := range data { tree.doSet(k, v) @@ -56,22 +56,22 @@ func NewBTreeFrom(m int, comparator func(v1, v2 interface{}) int, data map[inter return tree } -// Clone returns a new tree with a copy of current tree. +// Clone clones and returns a new tree from current tree. func (tree *BTree) Clone() *BTree { newTree := NewBTree(tree.m, tree.comparator, tree.mu.IsSafe()) newTree.Sets(tree.Map()) return newTree } -// Set inserts key-value item into the tree. -func (tree *BTree) Set(key interface{}, value interface{}) { +// Set sets key-value pair into the tree. +func (tree *BTree) Set(key any, value any) { tree.mu.Lock() defer tree.mu.Unlock() tree.doSet(key, value) } // Sets batch sets key-values to the tree. -func (tree *BTree) Sets(data map[interface{}]interface{}) { +func (tree *BTree) Sets(data map[any]any) { tree.mu.Lock() defer tree.mu.Unlock() for k, v := range data { @@ -80,8 +80,8 @@ func (tree *BTree) Sets(data map[interface{}]interface{}) { } // SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. -func (tree *BTree) SetIfNotExist(key interface{}, value interface{}) bool { +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. +func (tree *BTree) SetIfNotExist(key any, value any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -92,8 +92,8 @@ func (tree *BTree) SetIfNotExist(key interface{}, value interface{}) bool { } // SetIfNotExistFunc sets value with return value of callback function `f`, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. -func (tree *BTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. +func (tree *BTree) SetIfNotExistFunc(key any, f func() any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -104,11 +104,11 @@ func (tree *BTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bool } // SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. // // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that -// it executes function `f` with mutex.Lock of the hash map. -func (tree *BTree) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { +// it executes function `f` within mutex lock. +func (tree *BTree) SetIfNotExistFuncLock(key any, f func() any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -118,17 +118,20 @@ func (tree *BTree) SetIfNotExistFuncLock(key interface{}, f func() interface{}) return false } -// Get searches the node in the tree by `key` and returns its value or nil if key is not found in tree. -func (tree *BTree) Get(key interface{}) (value interface{}) { +// Get searches the `key` in the tree and returns its associated `value` or nil if key is not found in tree. +// +// Note that, the `nil` value from Get function cannot be used to determine key existence, please use Contains function +// to do so. +func (tree *BTree) Get(key any) (value any) { tree.mu.Lock() defer tree.mu.Unlock() value, _ = tree.doGet(key) return } -// GetOrSet returns the value by key, -// or sets value with given `value` if it does not exist and then returns this value. -func (tree *BTree) GetOrSet(key interface{}, value interface{}) interface{} { +// GetOrSet returns its `value` of `key`, or sets value with given `value` if it does not exist and then returns +// this value. +func (tree *BTree) GetOrSet(key any, value any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -138,10 +141,9 @@ func (tree *BTree) GetOrSet(key interface{}, value interface{}) interface{} { } } -// GetOrSetFunc returns the value by key, -// or sets value with returned value of callback function `f` if it does not exist -// and then returns this value. -func (tree *BTree) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { +// GetOrSetFunc returns its `value` of `key`, or sets value with returned value of callback function `f` if it does not +// exist and then returns this value. +func (tree *BTree) GetOrSetFunc(key any, f func() any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -151,13 +153,11 @@ func (tree *BTree) GetOrSetFunc(key interface{}, f func() interface{}) interface } } -// GetOrSetFuncLock returns the value by key, -// or sets value with returned value of callback function `f` if it does not exist -// and then returns this value. +// GetOrSetFuncLock returns its `value` of `key`, or sets value with returned value of callback function `f` if it does +// not exist and then returns this value. // -// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` -// with mutex.Lock of the hash map. -func (tree *BTree) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` within mutex lock. +func (tree *BTree) GetOrSetFuncLock(key any, f func() any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -168,39 +168,47 @@ func (tree *BTree) GetOrSetFuncLock(key interface{}, f func() interface{}) inter } // GetVar returns a gvar.Var with the value by given `key`. -// The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVar(key interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function Get. +func (tree *BTree) GetVar(key any) *gvar.Var { return gvar.New(tree.Get(key)) } // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. -// The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSet. +func (tree *BTree) GetVarOrSet(key any, value any) *gvar.Var { return gvar.New(tree.GetOrSet(key, value)) } // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. -// The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSetFunc. +func (tree *BTree) GetVarOrSetFunc(key any, f func() any) *gvar.Var { return gvar.New(tree.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. -// The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSetFuncLock. +func (tree *BTree) GetVarOrSetFuncLock(key any, f func() any) *gvar.Var { return gvar.New(tree.GetOrSetFuncLock(key, f)) } // Search searches the tree with given `key`. // Second return parameter `found` is true if key was found, otherwise false. -func (tree *BTree) Search(key interface{}) (value interface{}, found bool) { +func (tree *BTree) Search(key any) (value any, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Get(key) } -// Contains checks whether `key` exists in the tree. -func (tree *BTree) Contains(key interface{}) bool { +// Contains checks and returns whether given `key` exists in the tree. +func (tree *BTree) Contains(key any) bool { tree.mu.RLock() defer tree.mu.RUnlock() _, ok := tree.doGet(key) @@ -221,15 +229,16 @@ func (tree *BTree) IsEmpty() bool { return tree.tree.Size() == 0 } -// Remove removes the node from the tree by `key`. -func (tree *BTree) Remove(key interface{}) (value interface{}) { +// Remove removes the node from the tree by `key`, and returns its associated value of `key`. +// The given `key` should adhere to the comparator's type assertion, otherwise method panics. +func (tree *BTree) Remove(key any) (value any) { tree.mu.Lock() defer tree.mu.Unlock() return tree.doRemove(key) } -// Removes batch deletes values of the tree by `keys`. -func (tree *BTree) Removes(keys []interface{}) { +// Removes batch deletes key-value pairs from the tree by `keys`. +func (tree *BTree) Removes(keys []any) { tree.mu.Lock() defer tree.mu.Unlock() for _, key := range keys { @@ -244,22 +253,22 @@ func (tree *BTree) Clear() { tree.tree.Clear() } -// Keys returns all keys in asc order. -func (tree *BTree) Keys() []interface{} { +// Keys returns all keys from the tree in order by its comparator. +func (tree *BTree) Keys() []any { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Keys() } -// Values returns all values in asc order based on the key. -func (tree *BTree) Values() []interface{} { +// Values returns all values from the true in order by its comparator based on the key. +func (tree *BTree) Values() []any { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Values() } -// Replace the data of the tree with given `data`. -func (tree *BTree) Replace(data map[interface{}]interface{}) { +// Replace clears the data of the tree and sets the nodes by given `data`. +func (tree *BTree) Replace(data map[any]any) { tree.mu.Lock() defer tree.mu.Unlock() tree.tree.Clear() @@ -268,24 +277,20 @@ func (tree *BTree) Replace(data map[interface{}]interface{}) { } } -// Map returns all key-value items as map. -func (tree *BTree) Map() map[interface{}]interface{} { - tree.mu.RLock() - defer tree.mu.RUnlock() - m := make(map[interface{}]interface{}, tree.Size()) - tree.IteratorAsc(func(key, value interface{}) bool { +// Map returns all key-value pairs as map. +func (tree *BTree) Map() map[any]any { + m := make(map[any]any, tree.Size()) + tree.IteratorAsc(func(key, value any) bool { m[key] = value return true }) return m } -// MapStrAny returns all key-value items as map[string]interface{}. -func (tree *BTree) MapStrAny() map[string]interface{} { - tree.mu.RLock() - defer tree.mu.RUnlock() - m := make(map[string]interface{}, tree.Size()) - tree.IteratorAsc(func(key, value interface{}) bool { +// MapStrAny returns all key-value items as map[string]any. +func (tree *BTree) MapStrAny() map[string]any { + m := make(map[string]any, tree.Size()) + tree.IteratorAsc(func(key, value any) bool { m[gconv.String(key)] = value return true }) @@ -312,39 +317,48 @@ func (tree *BTree) MarshalJSON() (jsonBytes []byte, err error) { } // Iterator is alias of IteratorAsc. -func (tree *BTree) Iterator(f func(key, value interface{}) bool) { +// +// Also see IteratorAsc. +func (tree *BTree) Iterator(f func(key, value any) bool) { tree.IteratorAsc(f) } // IteratorFrom is alias of IteratorAscFrom. -func (tree *BTree) IteratorFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// Also see IteratorAscFrom. +func (tree *BTree) IteratorFrom(key any, match bool, f func(key, value any) bool) { tree.IteratorAscFrom(key, match, f) } // IteratorAsc iterates the tree readonly in ascending order with given callback function `f`. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *BTree) IteratorAsc(f func(key, value interface{}) bool) { +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *BTree) IteratorAsc(f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() - it := tree.tree.Iterator() + var ( + ok bool + it = tree.tree.Iterator() + ) for it.Begin(); it.Next(); { index, value := it.Key(), it.Value() - if ok := f(index, value); !ok { + if ok = f(index, value); !ok { break } } } // IteratorAscFrom iterates the tree readonly in ascending order with given callback function `f`. -// The parameter `key` specifies the start entry for iterating. The `match` specifies whether -// starting iterating if the `key` is fully matched, or else using index searching iterating. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *BTree) IteratorAscFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// The parameter `key` specifies the start entry for iterating. +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using index +// searching iterating. +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *BTree) IteratorAscFrom(key any, match bool, f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() var keys = tree.tree.Keys() - index, isIterator := tree.iteratorFromGetIndex(key, keys, match) - if !isIterator { + index, canIterator := iteratorFromGetIndex(key, keys, match) + if !canIterator { return } for ; index < len(keys); index++ { @@ -353,29 +367,35 @@ func (tree *BTree) IteratorAscFrom(key interface{}, match bool, f func(key, valu } // IteratorDesc iterates the tree readonly in descending order with given callback function `f`. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *BTree) IteratorDesc(f func(key, value interface{}) bool) { +// +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *BTree) IteratorDesc(f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() - it := tree.tree.Iterator() + var ( + ok bool + it = tree.tree.Iterator() + ) for it.End(); it.Prev(); { index, value := it.Key(), it.Value() - if ok := f(index, value); !ok { + if ok = f(index, value); !ok { break } } } // IteratorDescFrom iterates the tree readonly in descending order with given callback function `f`. -// The parameter `key` specifies the start entry for iterating. The `match` specifies whether -// starting iterating if the `key` is fully matched, or else using index searching iterating. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *BTree) IteratorDescFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// The parameter `key` specifies the start entry for iterating. +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using index +// searching iterating. +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *BTree) IteratorDescFrom(key any, match bool, f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() var keys = tree.tree.Keys() - index, isIterator := tree.iteratorFromGetIndex(key, keys, match) - if !isIterator { + index, canIterator := iteratorFromGetIndex(key, keys, match) + if !canIterator { return } for ; index >= 0; index-- { @@ -390,7 +410,7 @@ func (tree *BTree) Height() int { return tree.tree.Height() } -// Left returns the left-most (min) entry or nil if tree is empty. +// Left returns the minimum element corresponding to the comparator of the tree or nil if the tree is empty. func (tree *BTree) Left() *BTreeEntry { tree.mu.RLock() defer tree.mu.RUnlock() @@ -404,7 +424,7 @@ func (tree *BTree) Left() *BTreeEntry { } } -// Right returns the right-most (max) entry or nil if tree is empty. +// Right returns the maximum element corresponding to the comparator of the tree or nil if the tree is empty. func (tree *BTree) Right() *BTreeEntry { tree.mu.RLock() defer tree.mu.RUnlock() @@ -418,14 +438,13 @@ func (tree *BTree) Right() *BTreeEntry { } } -// doSet inserts key-value pair node into the tree. -// If key already exists, then its value is updated with the new value. -// If `value` is type of , -// it will be executed and its return value will be set to the map with `key`. +// doSet inserts key-value pair node into the tree without lock. +// If `key` already exists, then its value is updated with the new value. +// If `value` is type of , it will be executed and its return value will be set to the map with `key`. // // It returns value with given `key`. -func (tree *BTree) doSet(key interface{}, value interface{}) interface{} { - if f, ok := value.(func() interface{}); ok { +func (tree *BTree) doSet(key any, value any) any { + if f, ok := value.(func() any); ok { value = f() } if value == nil { @@ -435,36 +454,15 @@ func (tree *BTree) doSet(key interface{}, value interface{}) interface{} { return value } -// doGet get the value from the tree by key. -func (tree *BTree) doGet(key interface{}) (value interface{}, ok bool) { +// doGet get the value from the tree by key without lock. +func (tree *BTree) doGet(key any) (value any, ok bool) { return tree.tree.Get(key) } -// doRemove removes the node from the tree by key. -// Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *BTree) doRemove(key interface{}) (value interface{}) { +// doRemove removes key from tree and returns its associated value without lock. +// Note that, the given `key` should adhere to the comparator's type assertion, otherwise method panics. +func (tree *BTree) doRemove(key any) (value any) { value, _ = tree.tree.Get(key) tree.tree.Remove(key) return } - -// iteratorFromGetIndex returns the index of the key in the keys slice. -// The parameter `match` specifies whether starting iterating if the `key` is fully matched, -// or else using index searching iterating. -// If `isIterator` is true, iterator is available; or else not. -func (tree *BTree) iteratorFromGetIndex(key interface{}, keys []interface{}, match bool) (index int, isIterator bool) { - if match { - for i, k := range keys { - if k == key { - isIterator = true - index = i - } - } - } else { - if i, ok := key.(int); ok { - isIterator = true - index = i - } - } - return -} diff --git a/container/gtree/gtree_redblacktree.go b/container/gtree/gtree_redblacktree.go index 429be2fb6..c5a6bddf8 100644 --- a/container/gtree/gtree_redblacktree.go +++ b/container/gtree/gtree_redblacktree.go @@ -23,20 +23,20 @@ var _ iTree = (*RedBlackTree)(nil) // RedBlackTree holds elements of the red-black tree. type RedBlackTree struct { mu rwmutex.RWMutex - comparator func(v1, v2 interface{}) int + comparator func(v1, v2 any) int tree *redblacktree.Tree } // RedBlackTreeNode is a single element within the tree. type RedBlackTreeNode struct { - Key interface{} - Value interface{} + Key any + Value any } // NewRedBlackTree instantiates a red-black tree with the custom key comparator. // The parameter `safe` is used to specify whether using tree in concurrent-safety, // which is false in default. -func NewRedBlackTree(comparator func(v1, v2 interface{}) int, safe ...bool) *RedBlackTree { +func NewRedBlackTree(comparator func(v1, v2 any) int, safe ...bool) *RedBlackTree { return &RedBlackTree{ mu: rwmutex.Create(safe...), comparator: comparator, @@ -47,7 +47,7 @@ func NewRedBlackTree(comparator func(v1, v2 interface{}) int, safe ...bool) *Red // NewRedBlackTreeFrom instantiates a red-black tree with the custom key comparator and `data` map. // The parameter `safe` is used to specify whether using tree in concurrent-safety, // which is false in default. -func NewRedBlackTreeFrom(comparator func(v1, v2 interface{}) int, data map[interface{}]interface{}, safe ...bool) *RedBlackTree { +func NewRedBlackTreeFrom(comparator func(v1, v2 any) int, data map[any]any, safe ...bool) *RedBlackTree { tree := NewRedBlackTree(comparator, safe...) for k, v := range data { tree.doSet(k, v) @@ -56,7 +56,7 @@ func NewRedBlackTreeFrom(comparator func(v1, v2 interface{}) int, data map[inter } // SetComparator sets/changes the comparator for sorting. -func (tree *RedBlackTree) SetComparator(comparator func(a, b interface{}) int) { +func (tree *RedBlackTree) SetComparator(comparator func(a, b any) int) { tree.comparator = comparator if tree.tree == nil { tree.tree = redblacktree.NewWith(comparator) @@ -68,22 +68,22 @@ func (tree *RedBlackTree) SetComparator(comparator func(a, b interface{}) int) { } } -// Clone returns a new tree with a copy of current tree. +// Clone clones and returns a new tree from current tree. func (tree *RedBlackTree) Clone() *RedBlackTree { newTree := NewRedBlackTree(tree.comparator, tree.mu.IsSafe()) newTree.Sets(tree.Map()) return newTree } -// Set inserts node into the tree. -func (tree *RedBlackTree) Set(key interface{}, value interface{}) { +// Set sets key-value pair into the tree. +func (tree *RedBlackTree) Set(key any, value any) { tree.mu.Lock() defer tree.mu.Unlock() tree.doSet(key, value) } // Sets batch sets key-values to the tree. -func (tree *RedBlackTree) Sets(data map[interface{}]interface{}) { +func (tree *RedBlackTree) Sets(data map[any]any) { tree.mu.Lock() defer tree.mu.Unlock() for key, value := range data { @@ -92,8 +92,8 @@ func (tree *RedBlackTree) Sets(data map[interface{}]interface{}) { } // SetIfNotExist sets `value` to the map if the `key` does not exist, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. -func (tree *RedBlackTree) SetIfNotExist(key interface{}, value interface{}) bool { +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. +func (tree *RedBlackTree) SetIfNotExist(key any, value any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -104,8 +104,8 @@ func (tree *RedBlackTree) SetIfNotExist(key interface{}, value interface{}) bool } // SetIfNotExistFunc sets value with return value of callback function `f`, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. -func (tree *RedBlackTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. +func (tree *RedBlackTree) SetIfNotExistFunc(key any, f func() any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -116,11 +116,11 @@ func (tree *RedBlackTree) SetIfNotExistFunc(key interface{}, f func() interface{ } // SetIfNotExistFuncLock sets value with return value of callback function `f`, and then returns true. -// It returns false if `key` exists, and `value` would be ignored. +// It returns false if `key` exists, and such setting key-value pair operation would be ignored. // // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that -// it executes function `f` with mutex.Lock of the hash map. -func (tree *RedBlackTree) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { +// it executes function `f` within mutex lock. +func (tree *RedBlackTree) SetIfNotExistFuncLock(key any, f func() any) bool { tree.mu.Lock() defer tree.mu.Unlock() if _, ok := tree.doGet(key); !ok { @@ -130,15 +130,18 @@ func (tree *RedBlackTree) SetIfNotExistFuncLock(key interface{}, f func() interf return false } -// Get searches the node in the tree by `key` and returns its value or nil if key is not found in tree. -func (tree *RedBlackTree) Get(key interface{}) (value interface{}) { +// Get searches the `key` in the tree and returns its associated `value` or nil if key is not found in tree. +// +// Note that, the `nil` value from Get function cannot be used to determine key existence, please use Contains function +// to do so. +func (tree *RedBlackTree) Get(key any) (value any) { value, _ = tree.Search(key) return } -// GetOrSet returns the value by key, -// or sets value with given `value` if it does not exist and then returns this value. -func (tree *RedBlackTree) GetOrSet(key interface{}, value interface{}) interface{} { +// GetOrSet returns its `value` of `key`, or sets value with given `value` if it does not exist and then returns +// this value. +func (tree *RedBlackTree) GetOrSet(key any, value any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -148,10 +151,9 @@ func (tree *RedBlackTree) GetOrSet(key interface{}, value interface{}) interface } } -// GetOrSetFunc returns the value by key, -// or sets value with returned value of callback function `f` if it does not exist -// and then returns this value. -func (tree *RedBlackTree) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { +// GetOrSetFunc returns its `value` of `key`, or sets value with returned value of callback function `f` if it does not +// exist and then returns this value. +func (tree *RedBlackTree) GetOrSetFunc(key any, f func() any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -161,13 +163,11 @@ func (tree *RedBlackTree) GetOrSetFunc(key interface{}, f func() interface{}) in } } -// GetOrSetFuncLock returns the value by key, -// or sets value with returned value of callback function `f` if it does not exist -// and then returns this value. +// GetOrSetFuncLock returns its `value` of `key`, or sets value with returned value of callback function `f` if it does +// not exist and then returns this value. // -// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` -// with mutex.Lock of the hash map. -func (tree *RedBlackTree) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f`within mutex lock. +func (tree *RedBlackTree) GetOrSetFuncLock(key any, f func() any) any { tree.mu.Lock() defer tree.mu.Unlock() if v, ok := tree.doGet(key); !ok { @@ -178,32 +178,40 @@ func (tree *RedBlackTree) GetOrSetFuncLock(key interface{}, f func() interface{} } // GetVar returns a gvar.Var with the value by given `key`. -// The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVar(key interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function Get. +func (tree *RedBlackTree) GetVar(key any) *gvar.Var { return gvar.New(tree.Get(key)) } // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. -// The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSet. +func (tree *RedBlackTree) GetVarOrSet(key any, value any) *gvar.Var { return gvar.New(tree.GetOrSet(key, value)) } // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. -// The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSetFunc. +func (tree *RedBlackTree) GetVarOrSetFunc(key any, f func() any) *gvar.Var { return gvar.New(tree.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. -// The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +// Note that, the returned gvar.Var is un-concurrent safe. +// +// Also see function GetOrSetFuncLock. +func (tree *RedBlackTree) GetVarOrSetFuncLock(key any, f func() any) *gvar.Var { return gvar.New(tree.GetOrSetFuncLock(key, f)) } // Search searches the tree with given `key`. // Second return parameter `found` is true if key was found, otherwise false. -func (tree *RedBlackTree) Search(key interface{}) (value interface{}, found bool) { +func (tree *RedBlackTree) Search(key any) (value any, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() if node, found := tree.doGet(key); found { @@ -212,8 +220,8 @@ func (tree *RedBlackTree) Search(key interface{}) (value interface{}, found bool return nil, false } -// Contains checks whether `key` exists in the tree. -func (tree *RedBlackTree) Contains(key interface{}) bool { +// Contains checks and returns whether given `key` exists in the tree. +func (tree *RedBlackTree) Contains(key any) bool { tree.mu.RLock() defer tree.mu.RUnlock() _, ok := tree.doGet(key) @@ -234,16 +242,16 @@ func (tree *RedBlackTree) IsEmpty() bool { return tree.tree.Size() == 0 } -// Remove removes the node from the tree by key. -// Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *RedBlackTree) Remove(key interface{}) (value interface{}) { +// Remove removes the node from the tree by `key`, and returns its associated value of `key`. +// The given `key` should adhere to the comparator's type assertion, otherwise method panics. +func (tree *RedBlackTree) Remove(key any) (value any) { tree.mu.Lock() defer tree.mu.Unlock() return tree.doRemove(key) } -// Removes batch deletes values of the tree by `keys`. -func (tree *RedBlackTree) Removes(keys []interface{}) { +// Removes batch deletes key-value pairs from the tree by `keys`. +func (tree *RedBlackTree) Removes(keys []any) { tree.mu.Lock() defer tree.mu.Unlock() for _, key := range keys { @@ -258,22 +266,22 @@ func (tree *RedBlackTree) Clear() { tree.tree.Clear() } -// Keys returns all keys in asc order. -func (tree *RedBlackTree) Keys() []interface{} { +// Keys returns all keys from the tree in order by its comparator. +func (tree *RedBlackTree) Keys() []any { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Keys() } -// Values returns all values in asc order based on the key. -func (tree *RedBlackTree) Values() []interface{} { +// Values returns all values from the true in order by its comparator based on the key. +func (tree *RedBlackTree) Values() []any { tree.mu.RLock() defer tree.mu.RUnlock() return tree.tree.Values() } -// Replace the data of the tree with given `data`. -func (tree *RedBlackTree) Replace(data map[interface{}]interface{}) { +// Replace clears the data of the tree and sets the nodes by given `data`. +func (tree *RedBlackTree) Replace(data map[any]any) { tree.mu.Lock() defer tree.mu.Unlock() tree.tree.Clear() @@ -301,24 +309,20 @@ func (tree *RedBlackTree) MarshalJSON() (jsonBytes []byte, err error) { return tree.tree.MarshalJSON() } -// Map returns all key-value items as map. -func (tree *RedBlackTree) Map() map[interface{}]interface{} { - tree.mu.RLock() - defer tree.mu.RUnlock() - m := make(map[interface{}]interface{}, tree.Size()) - tree.IteratorAsc(func(key, value interface{}) bool { +// Map returns all key-value pairs as map. +func (tree *RedBlackTree) Map() map[any]any { + m := make(map[any]any, tree.Size()) + tree.IteratorAsc(func(key, value any) bool { m[key] = value return true }) return m } -// MapStrAny returns all key-value items as map[string]interface{}. -func (tree *RedBlackTree) MapStrAny() map[string]interface{} { - tree.mu.RLock() - defer tree.mu.RUnlock() - m := make(map[string]interface{}, tree.Size()) - tree.IteratorAsc(func(key, value interface{}) bool { +// MapStrAny returns all key-value items as map[string]any. +func (tree *RedBlackTree) MapStrAny() map[string]any { + m := make(map[string]any, tree.Size()) + tree.IteratorAsc(func(key, value any) bool { m[gconv.String(key)] = value return true }) @@ -326,39 +330,48 @@ func (tree *RedBlackTree) MapStrAny() map[string]interface{} { } // Iterator is alias of IteratorAsc. -func (tree *RedBlackTree) Iterator(f func(key, value interface{}) bool) { +// +// Also see IteratorAsc. +func (tree *RedBlackTree) Iterator(f func(key, value any) bool) { tree.IteratorAsc(f) } // IteratorFrom is alias of IteratorAscFrom. -func (tree *RedBlackTree) IteratorFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// Also see IteratorAscFrom. +func (tree *RedBlackTree) IteratorFrom(key any, match bool, f func(key, value any) bool) { tree.IteratorAscFrom(key, match, f) } // IteratorAsc iterates the tree readonly in ascending order with given callback function `f`. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *RedBlackTree) IteratorAsc(f func(key, value interface{}) bool) { +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *RedBlackTree) IteratorAsc(f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() - it := tree.tree.Iterator() + var ( + ok bool + it = tree.tree.Iterator() + ) for it.Begin(); it.Next(); { index, value := it.Key(), it.Value() - if ok := f(index, value); !ok { + if ok = f(index, value); !ok { break } } } // IteratorAscFrom iterates the tree readonly in ascending order with given callback function `f`. -// The parameter `key` specifies the start entry for iterating. The `match` specifies whether -// starting iterating if the `key` is fully matched, or else using index searching iterating. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *RedBlackTree) IteratorAscFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// The parameter `key` specifies the start entry for iterating. +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using index +// searching iterating. +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *RedBlackTree) IteratorAscFrom(key any, match bool, f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() var keys = tree.tree.Keys() - index, isIterator := tree.iteratorFromGetIndex(key, keys, match) - if !isIterator { + index, canIterator := iteratorFromGetIndex(key, keys, match) + if !canIterator { return } for ; index < len(keys); index++ { @@ -367,29 +380,35 @@ func (tree *RedBlackTree) IteratorAscFrom(key interface{}, match bool, f func(ke } // IteratorDesc iterates the tree readonly in descending order with given callback function `f`. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *RedBlackTree) IteratorDesc(f func(key, value interface{}) bool) { +// +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *RedBlackTree) IteratorDesc(f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() - it := tree.tree.Iterator() + var ( + ok bool + it = tree.tree.Iterator() + ) for it.End(); it.Prev(); { index, value := it.Key(), it.Value() - if ok := f(index, value); !ok { + if ok = f(index, value); !ok { break } } } // IteratorDescFrom iterates the tree readonly in descending order with given callback function `f`. -// The parameter `key` specifies the start entry for iterating. The `match` specifies whether -// starting iterating if the `key` is fully matched, or else using index searching iterating. -// If `f` returns true, then it continues iterating; or false to stop. -func (tree *RedBlackTree) IteratorDescFrom(key interface{}, match bool, f func(key, value interface{}) bool) { +// +// The parameter `key` specifies the start entry for iterating. +// The parameter `match` specifies whether starting iterating only if the `key` is fully matched, or else using index +// searching iterating. +// If callback function `f` returns true, then it continues iterating; or false to stop. +func (tree *RedBlackTree) IteratorDescFrom(key any, match bool, f func(key, value any) bool) { tree.mu.RLock() defer tree.mu.RUnlock() var keys = tree.tree.Keys() - index, isIterator := tree.iteratorFromGetIndex(key, keys, match) - if !isIterator { + index, canIterator := iteratorFromGetIndex(key, keys, match) + if !canIterator { return } for ; index >= 0; index-- { @@ -397,8 +416,7 @@ func (tree *RedBlackTree) IteratorDescFrom(key interface{}, match bool, f func(k } } -// Left returns the minimum element of the AVL tree -// or nil if the tree is empty. +// Left returns the minimum element corresponding to the comparator of the tree or nil if the tree is empty. func (tree *RedBlackTree) Left() *RedBlackTreeNode { tree.mu.RLock() defer tree.mu.RUnlock() @@ -412,8 +430,7 @@ func (tree *RedBlackTree) Left() *RedBlackTreeNode { } } -// Right returns the maximum element of the AVL tree -// or nil if the tree is empty. +// Right returns the maximum element corresponding to the comparator of the tree or nil if the tree is empty. func (tree *RedBlackTree) Right() *RedBlackTreeNode { tree.mu.RLock() defer tree.mu.RUnlock() @@ -427,15 +444,15 @@ func (tree *RedBlackTree) Right() *RedBlackTreeNode { } } -// Floor Finds floor node of the input key, return the floor node or nil if no floor node is found. -// Second return parameter is true if floor was found, otherwise false. +// Floor Finds floor node of the input key, returns the floor node or nil if no floor node is found. +// The second returned parameter `found` is true if floor was found, otherwise false. // // Floor node is defined as the largest node that is smaller than or equal to the given node. // A floor node may not be found, either because the tree is empty, or because // all nodes in the tree is larger than the given node. // // Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *RedBlackTree) Floor(key interface{}) (floor *RedBlackTreeNode, found bool) { +func (tree *RedBlackTree) Floor(key any) (floor *RedBlackTreeNode, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() node, found := tree.tree.Floor(key) @@ -448,15 +465,15 @@ func (tree *RedBlackTree) Floor(key interface{}) (floor *RedBlackTreeNode, found }, true } -// Ceiling finds ceiling node of the input key, return the ceiling node or nil if no ceiling node is found. -// Second return parameter is true if ceiling was found, otherwise false. +// Ceiling finds ceiling node of the input key, returns the ceiling node or nil if no ceiling node is found. +// The second return parameter `found` is true if ceiling was found, otherwise false. // // Ceiling node is defined as the smallest node that is larger than or equal to the given node. // A ceiling node may not be found, either because the tree is empty, or because // all nodes in the tree is smaller than the given node. // // Key should adhere to the comparator's type assertion, otherwise method panics. -func (tree *RedBlackTree) Ceiling(key interface{}) (ceiling *RedBlackTreeNode, found bool) { +func (tree *RedBlackTree) Ceiling(key any) (ceiling *RedBlackTreeNode, found bool) { tree.mu.RLock() defer tree.mu.RUnlock() node, found := tree.tree.Ceiling(key) @@ -474,14 +491,14 @@ func (tree *RedBlackTree) Ceiling(key interface{}) (ceiling *RedBlackTreeNode, f // or else the comparator would panic. // // If the type of value is different with key, you pass the new `comparator`. -func (tree *RedBlackTree) Flip(comparator ...func(v1, v2 interface{}) int) { +func (tree *RedBlackTree) Flip(comparator ...func(v1, v2 any) int) { var t = new(RedBlackTree) if len(comparator) > 0 { t = NewRedBlackTree(comparator[0], tree.mu.IsSafe()) } else { t = NewRedBlackTree(tree.comparator, tree.mu.IsSafe()) } - tree.IteratorAsc(func(key, value interface{}) bool { + tree.IteratorAsc(func(key, value any) bool { t.doSet(value, key) return true }) @@ -497,7 +514,7 @@ func (tree *RedBlackTree) UnmarshalJSON(b []byte) error { tree.comparator = gutil.ComparatorString tree.tree = redblacktree.NewWith(tree.comparator) } - var data map[string]interface{} + var data map[string]any if err := json.UnmarshalUseNumber(b, &data); err != nil { return err } @@ -508,7 +525,7 @@ func (tree *RedBlackTree) UnmarshalJSON(b []byte) error { } // UnmarshalValue is an interface implement which sets any type of value for map. -func (tree *RedBlackTree) UnmarshalValue(value interface{}) (err error) { +func (tree *RedBlackTree) UnmarshalValue(value any) (err error) { tree.mu.Lock() defer tree.mu.Unlock() if tree.comparator == nil { @@ -521,9 +538,13 @@ func (tree *RedBlackTree) UnmarshalValue(value interface{}) (err error) { return } -// doSet sets key-value pair to the tree. -func (tree *RedBlackTree) doSet(key, value interface{}) interface{} { - if f, ok := value.(func() interface{}); ok { +// doSet inserts key-value pair node into the tree without lock. +// If `key` already exists, then its value is updated with the new value. +// If `value` is type of , it will be executed and its return value will be set to the map with `key`. +// +// It returns value with given `key`. +func (tree *RedBlackTree) doSet(key, value any) any { + if f, ok := value.(func() any); ok { value = f() } if value == nil { @@ -533,35 +554,15 @@ func (tree *RedBlackTree) doSet(key, value interface{}) interface{} { return value } -// doGet retrieves and returns the value of given key from tree. -func (tree *RedBlackTree) doGet(key interface{}) (value interface{}, found bool) { +// doGet retrieves and returns the value of given key from tree without lock. +func (tree *RedBlackTree) doGet(key any) (value any, found bool) { return tree.tree.Get(key) } -// doRemove removes key from tree. -func (tree *RedBlackTree) doRemove(key interface{}) (value interface{}) { +// doRemove removes key from tree and returns its associated value without lock. +// Note that, the given `key` should adhere to the comparator's type assertion, otherwise method panics. +func (tree *RedBlackTree) doRemove(key any) (value any) { value, _ = tree.tree.Get(key) tree.tree.Remove(key) return } - -// iteratorFromGetIndex returns the index of the key in the keys slice. -// The parameter `match` specifies whether starting iterating if the `key` is fully matched, -// or else using index searching iterating. -// If `isIterator` is true, iterator is available; or else not. -func (tree *RedBlackTree) iteratorFromGetIndex(key interface{}, keys []interface{}, match bool) (index int, isIterator bool) { - if match { - for i, k := range keys { - if k == key { - isIterator = true - index = i - } - } - } else { - if i, ok := key.(int); ok { - isIterator = true - index = i - } - } - return -} diff --git a/contrib/config/apollo/apollo.go b/contrib/config/apollo/apollo.go index 21b8cb800..3c967c775 100644 --- a/contrib/config/apollo/apollo.go +++ b/contrib/config/apollo/apollo.go @@ -13,6 +13,7 @@ import ( "github.com/apolloconfig/agollo/v4" apolloConfig "github.com/apolloconfig/agollo/v4/env/config" "github.com/apolloconfig/agollo/v4/storage" + "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" diff --git a/contrib/config/apollo/go.mod b/contrib/config/apollo/go.mod index e99fbdefe..5f46be8af 100644 --- a/contrib/config/apollo/go.mod +++ b/contrib/config/apollo/go.mod @@ -1,21 +1,21 @@ module github.com/gogf/gf/contrib/config/apollo/v2 -go 1.18 +go 1.20 require ( github.com/apolloconfig/agollo/v4 v4.3.1 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -25,19 +25,20 @@ require ( github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.3 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cast v1.3.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.8.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/contrib/config/apollo/go.sum b/contrib/config/apollo/go.sum index fc0b24bd1..8b79d4e4c 100644 --- a/contrib/config/apollo/go.sum +++ b/contrib/config/apollo/go.sum @@ -38,8 +38,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apolloconfig/agollo/v4 v4.3.1 h1:NHjd7KqOPmTvYwJidISc9MPBRO8m9UNrH3tijcEVNAY= @@ -74,8 +74,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -84,8 +84,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -132,7 +132,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -154,8 +154,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -233,8 +233,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -260,7 +260,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0= @@ -280,12 +280,14 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= @@ -367,8 +369,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -435,8 +437,8 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -445,8 +447,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/contrib/config/consul/go.mod b/contrib/config/consul/go.mod index 7a0bfa298..e87661382 100644 --- a/contrib/config/consul/go.mod +++ b/contrib/config/consul/go.mod @@ -1,23 +1,23 @@ module github.com/gogf/gf/contrib/config/consul/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/hashicorp/consul/api v1.24.0 github.com/hashicorp/go-cleanhttp v0.5.2 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -31,14 +31,15 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/config/consul/go.sum b/contrib/config/consul/go.sum index e454b60ac..c3ca809b5 100644 --- a/contrib/config/consul/go.sum +++ b/contrib/config/consul/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -28,8 +28,8 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -37,8 +37,8 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -50,10 +50,10 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= 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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/hashicorp/consul/api v1.24.0 h1:u2XyStA2j0jnCiVUU7Qyrt8idjRn4ORhK6DlvZ3bWhA= @@ -162,8 +162,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -176,14 +176,16 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= @@ -196,8 +198,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -224,15 +226,15 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/contrib/config/kubecm/go.mod b/contrib/config/kubecm/go.mod index ae176aa28..e6874aff1 100644 --- a/contrib/config/kubecm/go.mod +++ b/contrib/config/kubecm/go.mod @@ -1,23 +1,23 @@ module github.com/gogf/gf/contrib/config/kubecm/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 k8s.io/api v0.27.4 k8s.io/apimachinery v0.27.4 k8s.io/client-go v0.27.4 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect @@ -25,10 +25,10 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -42,19 +42,20 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/pflag v1.0.5 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/contrib/config/kubecm/go.sum b/contrib/config/kubecm/go.sum index 29d454b17..ab817bc23 100644 --- a/contrib/config/kubecm/go.sum +++ b/contrib/config/kubecm/go.sum @@ -32,8 +32,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -56,8 +56,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -65,8 +65,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -118,8 +118,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -138,8 +138,8 @@ 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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -190,8 +190,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -206,7 +206,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -216,12 +216,14 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -285,8 +287,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -333,19 +335,19 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -393,7 +395,7 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 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= @@ -476,8 +478,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/config/kubecm/kubecm.go b/contrib/config/kubecm/kubecm.go index a110193cf..2be721d61 100644 --- a/contrib/config/kubecm/kubecm.go +++ b/contrib/config/kubecm/kubecm.go @@ -138,7 +138,7 @@ func (c *Client) doUpdate(ctx context.Context, namespace string) (err error) { ) } var j *gjson.Json - if j, err = gjson.LoadContent(cm.Data[c.config.DataItem]); err != nil { + if j, err = gjson.LoadContent([]byte(cm.Data[c.config.DataItem])); err != nil { return gerror.Wrapf( err, `parse config map item from %s[%s] failed`, c.config.ConfigMap, c.config.DataItem, diff --git a/contrib/config/nacos/go.mod b/contrib/config/nacos/go.mod index 44d66f071..02ab8739d 100644 --- a/contrib/config/nacos/go.mod +++ b/contrib/config/nacos/go.mod @@ -1,14 +1,14 @@ module github.com/gogf/gf/contrib/config/nacos/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/nacos-group/nacos-sdk-go/v2 v2.2.5 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect github.com/alibabacloud-go/tea v1.1.17 // indirect github.com/alibabacloud-go/tea-utils v1.4.4 // indirect @@ -20,13 +20,13 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -44,22 +44,23 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.1.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/contrib/config/nacos/go.sum b/contrib/config/nacos/go.sum index 48205cb2c..ccb081682 100644 --- a/contrib/config/nacos/go.sum +++ b/contrib/config/nacos/go.sum @@ -32,8 +32,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -86,8 +86,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -101,8 +101,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -151,7 +151,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -165,8 +165,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -253,8 +253,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -266,7 +266,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= @@ -280,12 +280,14 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= @@ -303,8 +305,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -370,8 +372,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -388,8 +390,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -430,8 +432,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -439,8 +441,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -577,8 +579,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/config/nacos/nacos.go b/contrib/config/nacos/nacos.go index 0314b3665..5327b9d6e 100644 --- a/contrib/config/nacos/nacos.go +++ b/contrib/config/nacos/nacos.go @@ -114,7 +114,7 @@ func (c *Client) updateLocalValue() (err error) { func (c *Client) doUpdate(content string) (err error) { var j *gjson.Json - if j, err = gjson.LoadContent(content); err != nil { + if j, err = gjson.LoadContent([]byte(content)); err != nil { return gerror.Wrap(err, `parse config map item from nacos failed`) } c.value.Set(j) diff --git a/contrib/config/polaris/go.mod b/contrib/config/polaris/go.mod index 78f92eb39..82d374c0e 100644 --- a/contrib/config/polaris/go.mod +++ b/contrib/config/polaris/go.mod @@ -1,26 +1,26 @@ module github.com/gogf/gf/contrib/config/polaris/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 - github.com/polarismesh/polaris-go v1.5.5 + github.com/gogf/gf/v2 v2.8.1 + github.com/polarismesh/polaris-go v1.5.8 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -39,20 +39,21 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/grpc v1.56.3 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/config/polaris/go.sum b/contrib/config/polaris/go.sum index f520733dd..6a99e16ad 100644 --- a/contrib/config/polaris/go.sum +++ b/contrib/config/polaris/go.sum @@ -168,8 +168,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw= @@ -224,8 +224,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -239,8 +239,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -275,8 +275,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= @@ -301,7 +301,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -339,8 +339,8 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -405,8 +405,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polarismesh/polaris-go v1.5.5 h1:TUxgla21J9Zb3zSynoAA9og0+sYJZ7TpZ2aFwzH7woI= -github.com/polarismesh/polaris-go v1.5.5/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c= +github.com/polarismesh/polaris-go v1.5.8 h1:zBZkZBa4wVxsG5Y/6U4PmY9dY/mddXdfNI65edVu6U8= +github.com/polarismesh/polaris-go v1.5.8/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c= github.com/polarismesh/specification v1.4.1 h1:lTZqeyUhhWuKyr6NDKBwmUrNfcUDvKLxWT/uOq71T5A= github.com/polarismesh/specification v1.4.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -432,8 +432,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -458,8 +458,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -473,12 +473,14 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -580,8 +582,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -692,8 +694,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -707,8 +709,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -960,8 +962,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -978,8 +980,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/config/polaris/polaris.go b/contrib/config/polaris/polaris.go index c14a8ff85..04765d659 100644 --- a/contrib/config/polaris/polaris.go +++ b/contrib/config/polaris/polaris.go @@ -147,7 +147,7 @@ func (c *Client) doUpdate(ctx context.Context) (err error) { return gerror.New("config file is empty") } var j *gjson.Json - if j, err = gjson.LoadContent(c.client.GetContent()); err != nil { + if j, err = gjson.DecodeToJson([]byte(c.client.GetContent())); err != nil { return gerror.Wrap(err, `parse config map item from polaris failed`) } c.value.Set(j) diff --git a/contrib/drivers/clickhouse/clickhouse_z_unit_model_test.go b/contrib/drivers/clickhouse/clickhouse_z_unit_model_test.go index 1d6bbdab4..31600e676 100644 --- a/contrib/drivers/clickhouse/clickhouse_z_unit_model_test.go +++ b/contrib/drivers/clickhouse/clickhouse_z_unit_model_test.go @@ -258,6 +258,19 @@ func Test_Model_Count(t *testing.T) { }) } +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + func Test_Model_Where(t *testing.T) { table := createInitTable() defer dropTable(table) diff --git a/contrib/drivers/clickhouse/go.mod b/contrib/drivers/clickhouse/go.mod index 09d663314..d52ad6820 100644 --- a/contrib/drivers/clickhouse/go.mod +++ b/contrib/drivers/clickhouse/go.mod @@ -1,23 +1,23 @@ module github.com/gogf/gf/contrib/drivers/clickhouse/v2 -go 1.18 +go 1.20 require ( github.com/ClickHouse/clickhouse-go/v2 v2.0.15 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/google/uuid v1.3.0 github.com/shopspring/decimal v1.3.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -26,13 +26,14 @@ require ( github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/paulmach/orb v0.7.1 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/clickhouse/go.sum b/contrib/drivers/clickhouse/go.sum index 1150b98b6..f3ff16e02 100644 --- a/contrib/drivers/clickhouse/go.sum +++ b/contrib/drivers/clickhouse/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4= @@ -10,14 +10,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= @@ -29,13 +29,13 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 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/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= @@ -65,8 +65,8 @@ github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFu 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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= @@ -77,20 +77,22 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -100,8 +102,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -114,12 +116,12 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= diff --git a/contrib/drivers/dm/go.mod b/contrib/drivers/dm/go.mod index d5fbd55ee..93a472dab 100644 --- a/contrib/drivers/dm/go.mod +++ b/contrib/drivers/dm/go.mod @@ -1,36 +1,37 @@ module github.com/gogf/gf/contrib/drivers/dm/v2 -go 1.18 +go 1.20 replace github.com/gogf/gf/v2 => ../../../ require ( gitee.com/chunanyong/dm v1.8.12 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/dm/go.sum b/contrib/drivers/dm/go.sum index ac140f02b..08a0ddf30 100644 --- a/contrib/drivers/dm/go.sum +++ b/contrib/drivers/dm/go.sum @@ -1,26 +1,26 @@ gitee.com/chunanyong/dm v1.8.12 h1:WupbFZL0MRNIIiCPaLDHgFi5jkdkjzjPReuWPaInGwk= gitee.com/chunanyong/dm v1.8.12/go.mod h1:EPRJnuPFgbyOFgJ0TRYCTGzhq+ZT4wdyaj/GW/LLcNg= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -37,24 +37,26 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/drivers/mssql/go.mod b/contrib/drivers/mssql/go.mod index 8b9e89598..604a87105 100644 --- a/contrib/drivers/mssql/go.mod +++ b/contrib/drivers/mssql/go.mod @@ -1,37 +1,38 @@ module github.com/gogf/gf/contrib/drivers/mssql/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/microsoft/go-mssqldb v1.7.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/mssql/go.sum b/contrib/drivers/mssql/go.sum index 09b52c837..b20340e26 100644 --- a/contrib/drivers/mssql/go.sum +++ b/contrib/drivers/mssql/go.sum @@ -4,20 +4,20 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xO github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= @@ -25,10 +25,10 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -49,25 +49,27 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/drivers/mssql/mssql.go b/contrib/drivers/mssql/mssql.go index 470c16126..5be217ce0 100644 --- a/contrib/drivers/mssql/mssql.go +++ b/contrib/drivers/mssql/mssql.go @@ -23,7 +23,8 @@ type Driver struct { } const ( - quoteChar = `"` + rowNumberAliasForSelect = `ROW_NUMBER__` + quoteChar = `"` ) func init() { diff --git a/contrib/drivers/mssql/mssql_do_commit.go b/contrib/drivers/mssql/mssql_do_commit.go new file mode 100644 index 000000000..1dc57c950 --- /dev/null +++ b/contrib/drivers/mssql/mssql_do_commit.go @@ -0,0 +1,29 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mssql + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" +) + +// DoCommit commits current sql and arguments to underlying sql driver. +func (d *Driver) DoCommit(ctx context.Context, in gdb.DoCommitInput) (out gdb.DoCommitOutput, err error) { + out, err = d.Core.DoCommit(ctx, in) + if err != nil { + return + } + if len(out.Records) > 0 { + // remove auto added field. + for i, record := range out.Records { + delete(record, rowNumberAliasForSelect) + out.Records[i] = record + } + } + return +} diff --git a/contrib/drivers/mssql/mssql_do_filter.go b/contrib/drivers/mssql/mssql_do_filter.go index 8cf790e4f..f6e4538bd 100644 --- a/contrib/drivers/mssql/mssql_do_filter.go +++ b/contrib/drivers/mssql/mssql_do_filter.go @@ -18,10 +18,11 @@ import ( ) var ( - selectSqlTmp = `SELECT * FROM (SELECT TOP %d * FROM (SELECT TOP %d %s) as TMP1_ ) as TMP2_ ` + orderBySqlTmp = `SELECT %s %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY` + withoutOrderBySqlTmp = `SELECT %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY` selectWithOrderSqlTmp = ` -SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_ -WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d +SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROW_NUMBER__, %s ) as TMP_ +WHERE TMP_.ROW_NUMBER__ > %d AND TMP_.ROW_NUMBER__ <= %d ` ) @@ -78,89 +79,55 @@ func (d *Driver) parseSql(toBeCommittedSql string) (string, error) { func (d *Driver) handleSelectSqlReplacement(toBeCommittedSql string) (newSql string, err error) { // SELECT * FROM USER WHERE ID=1 LIMIT 1 - match, err := gregex.MatchString(`^SELECT(.+)LIMIT 1$`, toBeCommittedSql) + match, err := gregex.MatchString(`^SELECT(.+?)LIMIT\s+1$`, toBeCommittedSql) if err != nil { return "", err } if len(match) > 1 { - return fmt.Sprintf(`SELECT TOP 1 %s`, match[1]), nil + return fmt.Sprintf(`SELECT TOP 1 %s`, strings.TrimSpace(match[1])), nil } // SELECT * FROM USER WHERE AGE>18 ORDER BY ID DESC LIMIT 100, 200 - patten := `^\s*(?i)(SELECT)|(LIMIT\s*(\d+)\s*,\s*(\d+))` - if gregex.IsMatchString(patten, toBeCommittedSql) == false { - return toBeCommittedSql, nil - } - allMatch, err := gregex.MatchAllString(patten, toBeCommittedSql) - if err != nil { - return "", err - } - var index = 1 - // LIMIT statement checks. - if len(allMatch) < 2 || - (strings.HasPrefix(allMatch[index][0], "LIMIT") == false && - strings.HasPrefix(allMatch[index][0], "limit") == false) { - return toBeCommittedSql, nil - } - if gregex.IsMatchString("((?i)SELECT)(.+)((?i)LIMIT)", toBeCommittedSql) == false { - return toBeCommittedSql, nil - } - // ORDER BY statement checks. - var ( - selectStr = "" - orderStr = "" - haveOrder = gregex.IsMatchString("((?i)SELECT)(.+)((?i)ORDER BY)", toBeCommittedSql) - ) - if haveOrder { - queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)ORDER BY)", toBeCommittedSql) - if len(queryExpr) != 4 || - strings.EqualFold(queryExpr[1], "SELECT") == false || - strings.EqualFold(queryExpr[3], "ORDER BY") == false { - return toBeCommittedSql, nil - } - selectStr = queryExpr[2] - orderExpr, _ := gregex.MatchString("((?i)ORDER BY)(.+)((?i)LIMIT)", toBeCommittedSql) - if len(orderExpr) != 4 || - strings.EqualFold(orderExpr[1], "ORDER BY") == false || - strings.EqualFold(orderExpr[3], "LIMIT") == false { - return toBeCommittedSql, nil - } - orderStr = orderExpr[2] - } else { - queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)LIMIT)", toBeCommittedSql) - if len(queryExpr) != 4 || - strings.EqualFold(queryExpr[1], "SELECT") == false || - strings.EqualFold(queryExpr[3], "LIMIT") == false { - return toBeCommittedSql, nil - } - selectStr = queryExpr[2] - } - first, limit := 0, 0 - for i := 1; i < len(allMatch[index]); i++ { - if len(strings.TrimSpace(allMatch[index][i])) == 0 { - continue - } - if strings.HasPrefix(allMatch[index][i], "LIMIT") || - strings.HasPrefix(allMatch[index][i], "limit") { - first, _ = strconv.Atoi(allMatch[index][i+1]) - limit, _ = strconv.Atoi(allMatch[index][i+2]) - break - } - } - if haveOrder { - toBeCommittedSql = fmt.Sprintf( - selectWithOrderSqlTmp, - orderStr, selectStr, first, first+limit, - ) + pattern := `(?i)SELECT(.+?)(ORDER BY.+?)?\s*LIMIT\s*(\d+)(?:\s*,\s*(\d+))?` + if !gregex.IsMatchString(pattern, toBeCommittedSql) { return toBeCommittedSql, nil } - if first == 0 { - first = limit + allMatch, err := gregex.MatchString(pattern, toBeCommittedSql) + if err != nil { + return "", err } - toBeCommittedSql = fmt.Sprintf( - selectSqlTmp, - limit, first+limit, selectStr, - ) - return toBeCommittedSql, nil + + // SELECT and ORDER BY + selectStr := strings.TrimSpace(allMatch[1]) + orderStr := "" + if len(allMatch[2]) > 0 { + orderStr = strings.TrimSpace(allMatch[2]) + } + + // LIMIT and OFFSET value + first, _ := strconv.Atoi(allMatch[3]) // LIMIT first parameter + limit := 0 + if len(allMatch) > 4 && allMatch[4] != "" { + limit, _ = strconv.Atoi(allMatch[4]) // LIMIT second parameter + } else { + limit = first + first = 0 + } + + if orderStr != "" { + // have ORDER BY clause + newSql = fmt.Sprintf( + orderBySqlTmp, + selectStr, orderStr, first, limit, + ) + } else { + // without ORDER BY clause + newSql = fmt.Sprintf( + withoutOrderBySqlTmp, + selectStr, first, limit, + ) + } + + return newSql, nil } diff --git a/contrib/drivers/mssql/mssql_do_filter_test.go b/contrib/drivers/mssql/mssql_do_filter_test.go new file mode 100644 index 000000000..91ded5723 --- /dev/null +++ b/contrib/drivers/mssql/mssql_do_filter_test.go @@ -0,0 +1,132 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mssql + +import ( + "context" + "reflect" + "testing" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/test/gtest" +) + +func TestDriver_DoFilter(t *testing.T) { + type fields struct { + Core *gdb.Core + } + type args struct { + ctx context.Context + link gdb.Link + sql string + args []interface{} + } + var tests []struct { + name string + fields fields + args args + wantNewSql string + wantNewArgs []interface{} + wantErr bool + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := &Driver{ + Core: tt.fields.Core, + } + gotNewSql, gotNewArgs, err := d.DoFilter(tt.args.ctx, tt.args.link, tt.args.sql, tt.args.args) + if (err != nil) != tt.wantErr { + t.Errorf("DoFilter() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotNewSql != tt.wantNewSql { + t.Errorf("DoFilter() gotNewSql = %v, want %v", gotNewSql, tt.wantNewSql) + } + if !reflect.DeepEqual(gotNewArgs, tt.wantNewArgs) { + t.Errorf("DoFilter() gotNewArgs = %v, want %v", gotNewArgs, tt.wantNewArgs) + } + }) + } +} + +func TestDriver_handleSelectSqlReplacement(t *testing.T) { + + gtest.C(t, func(t *gtest.T) { + d := &Driver{} + + // LIMIT 1 + inputSql := "SELECT * FROM User WHERE ID = 1 LIMIT 1" + expectedSql := "SELECT TOP 1 * FROM User WHERE ID = 1" + resultSql, err := d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // LIMIT query with offset and number of rows + inputSql = "SELECT * FROM User ORDER BY ID DESC LIMIT 100, 200" + expectedSql = "SELECT * FROM User ORDER BY ID DESC OFFSET 100 ROWS FETCH NEXT 200 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // Simple query with no LIMIT + inputSql = "SELECT * FROM User WHERE age > 18" + expectedSql = "SELECT * FROM User WHERE age > 18" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // without LIMIT + inputSql = "SELECT * FROM User ORDER BY ID DESC" + expectedSql = "SELECT * FROM User ORDER BY ID DESC" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // LIMIT query with only rows + inputSql = "SELECT * FROM User LIMIT 50" + expectedSql = "SELECT * FROM User OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // LIMIT query without ORDER BY + inputSql = "SELECT * FROM User LIMIT 30" + expectedSql = "SELECT * FROM User OFFSET 0 ROWS FETCH NEXT 30 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // Complex query with ORDER BY and LIMIT + inputSql = "SELECT name, age FROM User WHERE age > 18 ORDER BY age ASC LIMIT 10, 5" + expectedSql = "SELECT name, age FROM User WHERE age > 18 ORDER BY age ASC OFFSET 10 ROWS FETCH NEXT 5 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // Complex conditional queries have limits + inputSql = "SELECT * FROM User WHERE age > 18 AND status = 'active' LIMIT 100, 50" + expectedSql = "SELECT * FROM User WHERE age > 18 AND status = 'active' OFFSET 100 ROWS FETCH NEXT 50 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // A LIMIT query that contains subquery + inputSql = "SELECT * FROM (SELECT * FROM User WHERE age > 18) AS subquery LIMIT 10" + expectedSql = "SELECT * FROM (SELECT * FROM User WHERE age > 18) AS subquery OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + // Queries with complex ORDER BY and LIMIT + inputSql = "SELECT name, age FROM User WHERE age > 18 ORDER BY age DESC, name ASC LIMIT 20, 10" + expectedSql = "SELECT name, age FROM User WHERE age > 18 ORDER BY age DESC, name ASC OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY" + resultSql, err = d.handleSelectSqlReplacement(inputSql) + t.AssertNil(err) + t.Assert(resultSql, expectedSql) + + }) +} diff --git a/contrib/drivers/mssql/mssql_z_unit_basic_test.go b/contrib/drivers/mssql/mssql_z_unit_basic_test.go index 40d39f988..b283f3047 100644 --- a/contrib/drivers/mssql/mssql_z_unit_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_basic_test.go @@ -794,7 +794,7 @@ func Test_DB_ToJson(t *testing.T) { } // ToJson - resultJson, err := gjson.LoadContent(result.Json()) + resultJson, err := gjson.LoadContent([]byte(result.Json())) if err != nil { gtest.Fatal(err) } diff --git a/contrib/drivers/mssql/mssql_z_unit_model_test.go b/contrib/drivers/mssql/mssql_z_unit_model_test.go index a31ff478d..7435e84cc 100644 --- a/contrib/drivers/mssql/mssql_z_unit_model_test.go +++ b/contrib/drivers/mssql/mssql_z_unit_model_test.go @@ -519,7 +519,19 @@ func Test_Model_Count(t *testing.T) { t.AssertNil(err) t.Assert(count, int64(TableSize)) }) +} +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) } func Test_Model_Select(t *testing.T) { diff --git a/contrib/drivers/mysql/go.mod b/contrib/drivers/mysql/go.mod index 9d92f7393..2b05cf394 100644 --- a/contrib/drivers/mysql/go.mod +++ b/contrib/drivers/mysql/go.mod @@ -1,34 +1,35 @@ module github.com/gogf/gf/contrib/drivers/mysql/v2 -go 1.18 +go 1.20 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/mysql/go.sum b/contrib/drivers/mysql/go.sum index fc917ad11..4e03c25c6 100644 --- a/contrib/drivers/mysql/go.sum +++ b/contrib/drivers/mysql/go.sum @@ -1,24 +1,24 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -35,23 +35,25 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/drivers/mysql/mysql_do_filter.go b/contrib/drivers/mysql/mysql_do_filter.go index 96bc7224c..aff546ab9 100644 --- a/contrib/drivers/mysql/mysql_do_filter.go +++ b/contrib/drivers/mysql/mysql_do_filter.go @@ -13,6 +13,8 @@ import ( ) // DoFilter handles the sql before posts it to database. -func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) { +func (d *Driver) DoFilter( + ctx context.Context, link gdb.Link, sql string, args []interface{}, +) (newSql string, newArgs []interface{}, err error) { return d.Core.DoFilter(ctx, link, sql, args) } diff --git a/contrib/drivers/mysql/mysql_open.go b/contrib/drivers/mysql/mysql_open.go index 4c53fcf39..cd5f74b11 100644 --- a/contrib/drivers/mysql/mysql_open.go +++ b/contrib/drivers/mysql/mysql_open.go @@ -9,7 +9,6 @@ package mysql import ( "database/sql" "fmt" - "net/url" "strings" @@ -23,9 +22,21 @@ import ( // Note that it converts time.Time argument to local timezone in default. func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) { var ( - source string + source = configNodeToSource(config) underlyingDriverName = "mysql" ) + if db, err = sql.Open(underlyingDriverName, source); err != nil { + err = gerror.WrapCodef( + gcode.CodeDbOperationError, err, + `sql.Open failed for driver "%s" by source "%s"`, underlyingDriverName, source, + ) + return nil, err + } + return +} + +func configNodeToSource(config *gdb.ConfigNode) string { + var source string // [username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN] if config.Link != "" { // ============================================================================ @@ -37,10 +48,13 @@ func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) { source, _ = gregex.ReplaceString(`/([\w\.\-]+)+`, "/"+config.Name, source) } } else { - // TODO: Do not set charset when charset is not specified (in v2.5.0) + var portStr string + if config.Port != "" { + portStr = ":" + config.Port + } source = fmt.Sprintf( - "%s:%s@%s(%s:%s)/%s?charset=%s", - config.User, config.Pass, config.Protocol, config.Host, config.Port, config.Name, config.Charset, + "%s:%s@%s(%s%s)/%s?charset=%s", + config.User, config.Pass, config.Protocol, config.Host, portStr, config.Name, config.Charset, ) if config.Timezone != "" { if strings.Contains(config.Timezone, "/") { @@ -52,12 +66,5 @@ func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) { source = fmt.Sprintf("%s&%s", source, config.Extra) } } - if db, err = sql.Open(underlyingDriverName, source); err != nil { - err = gerror.WrapCodef( - gcode.CodeDbOperationError, err, - `sql.Open failed for driver "%s" by source "%s"`, underlyingDriverName, source, - ) - return nil, err - } - return + return source } diff --git a/contrib/drivers/mysql/mysql_z_unit_core_test.go b/contrib/drivers/mysql/mysql_z_unit_core_test.go index 41fcf475c..5dce861e1 100644 --- a/contrib/drivers/mysql/mysql_z_unit_core_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_core_test.go @@ -104,6 +104,7 @@ func Test_DB_Insert(t *testing.T) { "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "T1", "create_time": gtime.Now().String(), + "create_date": gtime.Date(), }) t.AssertNil(err) @@ -114,6 +115,7 @@ func Test_DB_Insert(t *testing.T) { "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "name_2", "create_time": gtime.Now().String(), + "create_date": gtime.Date(), }) t.AssertNil(err) n, _ := result.RowsAffected() @@ -121,19 +123,22 @@ func Test_DB_Insert(t *testing.T) { // struct type User struct { - Id int `gconv:"id"` - Passport string `json:"passport"` - Password string `gconv:"password"` - Nickname string `gconv:"nickname"` - CreateTime string `json:"create_time"` + Id int `gconv:"id"` + Passport string `json:"passport"` + Password string `gconv:"password"` + Nickname string `gconv:"nickname"` + CreateTime string `json:"create_time"` + CreateDate *gtime.Time `json:"create_date"` } - timeStr := gtime.New("2024-10-01 12:01:01").String() + gTime := gtime.New("2024-10-01 12:01:01") + timeStr, dateStr := gTime.String(), "2024-10-01 00:00:00" result, err = db.Insert(ctx, table, User{ Id: 3, Passport: "user_3", Password: "25d55ad283aa400af464c76d713c07ad", Nickname: "name_3", CreateTime: timeStr, + CreateDate: gTime, }) t.AssertNil(err) n, _ = result.RowsAffected() @@ -147,15 +152,18 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["password"].String(), "25d55ad283aa400af464c76d713c07ad") t.Assert(one["nickname"].String(), "name_3") t.Assert(one["create_time"].GTime().String(), timeStr) + t.Assert(one["create_date"].GTime().String(), dateStr) // *struct - timeStr = gtime.New("2024-10-01 12:01:01").String() + gTime = gtime.New("2024-10-01 12:01:01") + timeStr, dateStr = gTime.String(), "2024-10-01 00:00:00" result, err = db.Insert(ctx, table, &User{ Id: 4, Passport: "t4", Password: "25d55ad283aa400af464c76d713c07ad", Nickname: "name_4", CreateTime: timeStr, + CreateDate: gTime, }) t.AssertNil(err) n, _ = result.RowsAffected() @@ -168,9 +176,11 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["password"].String(), "25d55ad283aa400af464c76d713c07ad") t.Assert(one["nickname"].String(), "name_4") t.Assert(one["create_time"].GTime().String(), timeStr) + t.Assert(one["create_date"].GTime().String(), dateStr) // batch with Insert - timeStr = gtime.New("2024-10-01 12:01:01").String() + gTime = gtime.New("2024-10-01 12:01:01") + timeStr, dateStr = gTime.String(), "2024-10-01 00:00:00" r, err := db.Insert(ctx, table, g.Slice{ g.Map{ "id": 200, @@ -178,6 +188,7 @@ func Test_DB_Insert(t *testing.T) { "password": "25d55ad283aa400af464c76d71qw07ad", "nickname": "T200", "create_time": timeStr, + "create_date": gTime, }, g.Map{ "id": 300, @@ -185,6 +196,7 @@ func Test_DB_Insert(t *testing.T) { "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "T300", "create_time": timeStr, + "create_date": gTime, }, }) t.AssertNil(err) @@ -198,6 +210,7 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["password"].String(), "25d55ad283aa400af464c76d71qw07ad") t.Assert(one["nickname"].String(), "T200") t.Assert(one["create_time"].GTime().String(), timeStr) + t.Assert(one["create_date"].GTime().String(), dateStr) }) } @@ -881,7 +894,7 @@ func Test_DB_ToJson(t *testing.T) { } // ToJson - resultJson, err := gjson.LoadContent(result.Json()) + resultJson, err := gjson.LoadContent([]byte(result.Json())) if err != nil { gtest.Fatal(err) } @@ -1644,7 +1657,7 @@ func Test_Core_ClearTableFields(t *testing.T) { gtest.C(t, func(t *gtest.T) { fields, err := db.TableFields(ctx, table) t.AssertNil(err) - t.Assert(len(fields), 5) + t.Assert(len(fields), 6) }) gtest.C(t, func(t *gtest.T) { err := db.GetCore().ClearTableFields(ctx, table) diff --git a/contrib/drivers/mysql/mysql_z_unit_feature_raw_type_test.go b/contrib/drivers/mysql/mysql_z_unit_feature_raw_type_test.go index eb8256785..5bc008e30 100644 --- a/contrib/drivers/mysql/mysql_z_unit_feature_raw_type_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_feature_raw_type_test.go @@ -7,6 +7,7 @@ package mysql_test import ( + "context" "testing" "github.com/gogf/gf/v2/database/gdb" @@ -14,7 +15,7 @@ import ( "github.com/gogf/gf/v2/test/gtest" ) -func Test_Insert_Raw(t *testing.T) { +func Test_Raw_Insert(t *testing.T) { table := createTable() defer dropTable(table) @@ -33,7 +34,7 @@ func Test_Insert_Raw(t *testing.T) { }) } -func Test_BatchInsert_Raw(t *testing.T) { +func Test_Raw_BatchInsert(t *testing.T) { table := createTable() defer dropTable(table) @@ -63,7 +64,7 @@ func Test_BatchInsert_Raw(t *testing.T) { }) } -func Test_Update_Raw(t *testing.T) { +func Test_Raw_Update(t *testing.T) { table := createInitTable() defer dropTable(table) @@ -84,3 +85,45 @@ func Test_Update_Raw(t *testing.T) { t.Assert(n, 1) }) } + +func Test_Raw_Where(t *testing.T) { + table1 := createTable("Test_Raw_Where_Table1") + table2 := createTable("Test_Raw_Where_Table2") + defer dropTable(table1) + defer dropTable(table2) + + // https://github.com/gogf/gf/issues/3922 + gtest.C(t, func(t *gtest.T) { + expectSql := "SELECT * FROM `Test_Raw_Where_Table1` AS A WHERE NOT EXISTS (SELECT B.id FROM `Test_Raw_Where_Table2` AS B WHERE `B`.`id`=A.id) LIMIT 1" + sql, err := gdb.ToSQL(ctx, func(ctx context.Context) error { + s := db.Model(table2).As("B").Ctx(ctx).Fields("B.id").Where("B.id", gdb.Raw("A.id")) + m := db.Model(table1).As("A").Ctx(ctx).Where("NOT EXISTS ?", s).Limit(1) + _, err := m.All() + return err + }) + t.AssertNil(err) + t.Assert(expectSql, sql) + }) + gtest.C(t, func(t *gtest.T) { + expectSql := "SELECT * FROM `Test_Raw_Where_Table1` AS A WHERE NOT EXISTS (SELECT B.id FROM `Test_Raw_Where_Table2` AS B WHERE B.id=A.id) LIMIT 1" + sql, err := gdb.ToSQL(ctx, func(ctx context.Context) error { + s := db.Model(table2).As("B").Ctx(ctx).Fields("B.id").Where(gdb.Raw("B.id=A.id")) + m := db.Model(table1).As("A").Ctx(ctx).Where("NOT EXISTS ?", s).Limit(1) + _, err := m.All() + return err + }) + t.AssertNil(err) + t.Assert(expectSql, sql) + }) + // https://github.com/gogf/gf/issues/3915 + gtest.C(t, func(t *gtest.T) { + expectSql := "SELECT * FROM `Test_Raw_Where_Table1` WHERE `passport` < `nickname`" + sql, err := gdb.ToSQL(ctx, func(ctx context.Context) error { + m := db.Model(table1).Ctx(ctx).WhereLT("passport", gdb.Raw("`nickname`")) + _, err := m.All() + return err + }) + t.AssertNil(err) + t.Assert(expectSql, sql) + }) +} diff --git a/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go b/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go index b32af2fb1..f71a3d378 100644 --- a/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_feature_with_test.go @@ -93,36 +93,17 @@ func Test_Table_Relation_With_Scan(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_score" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -291,36 +272,17 @@ func Test_Table_Relation_With(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -491,36 +453,17 @@ func Test_Table_Relation_WithAll(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -606,36 +549,17 @@ func Test_Table_Relation_WithAll_List(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -747,36 +671,17 @@ func Test_Table_Relation_WithAllCondition_List(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -883,36 +788,17 @@ func Test_Table_Relation_WithAll_Embedded_With_SelfMaintained_Attributes(t *test tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -998,36 +884,17 @@ func Test_Table_Relation_WithAll_Embedded_Without_SelfMaintained_Attributes(t *t tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -1121,36 +988,17 @@ func Test_Table_Relation_WithAll_Embedded_WithoutMeta(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - `, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -1237,36 +1085,17 @@ func Test_Table_Relation_WithAll_AttributeStructAlsoHasWithTag(t *testing.T) { tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -1353,36 +1182,17 @@ func Test_Table_Relation_WithAll_AttributeStructAlsoHasWithTag_MoreDeep(t *testi tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) @@ -1499,36 +1309,17 @@ func Test_Table_Relation_With_AttributeStructAlsoHasWithTag_MoreDeep(t *testing. tableUserDetail = "user_detail" tableUserScores = "user_scores" ) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -name varchar(45) NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUser)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { gtest.Error(err) } defer dropTable(tableUser) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -uid int(10) unsigned NOT NULL AUTO_INCREMENT, -address varchar(45) NOT NULL, -PRIMARY KEY (uid) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserDetail)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { gtest.Error(err) } defer dropTable(tableUserDetail) - if _, err := db.Exec(ctx, fmt.Sprintf(` -CREATE TABLE IF NOT EXISTS %s ( -id int(10) unsigned NOT NULL AUTO_INCREMENT, -uid int(10) unsigned NOT NULL, -score int(10) unsigned NOT NULL, -PRIMARY KEY (id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -`, tableUserScores)); err != nil { + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { gtest.Error(err) } defer dropTable(tableUserScores) diff --git a/contrib/drivers/mysql/mysql_z_unit_init_test.go b/contrib/drivers/mysql/mysql_z_unit_init_test.go index ea4b8694c..1326378c3 100644 --- a/contrib/drivers/mysql/mysql_z_unit_init_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_init_test.go @@ -129,6 +129,7 @@ func createTableWithDb(db gdb.DB, table ...string) (name string) { password char(32) NULL, nickname varchar(45) NULL, create_time timestamp(6) NULL, + create_date date NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, name, diff --git a/contrib/drivers/mysql/mysql_z_unit_internal_test.go b/contrib/drivers/mysql/mysql_z_unit_internal_test.go new file mode 100644 index 000000000..b8868f6ca --- /dev/null +++ b/contrib/drivers/mysql/mysql_z_unit_internal_test.go @@ -0,0 +1,30 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mysql + +import ( + "testing" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/test/gtest" +) + +func Test_configNodeToSource(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + configNode := &gdb.ConfigNode{ + Host: "/tmp/mysql.sock", + Port: "", + User: "username", + Pass: "password", + Name: "dbname", + Type: "mysql", + Protocol: "unix", + } + source := configNodeToSource(configNode) + t.Assert(source, "username:password@unix(/tmp/mysql.sock)/dbname?charset=") + }) +} diff --git a/contrib/drivers/mysql/mysql_z_unit_issue_test.go b/contrib/drivers/mysql/mysql_z_unit_issue_test.go index 072fe1b93..58ceeb0a5 100644 --- a/contrib/drivers/mysql/mysql_z_unit_issue_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_issue_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" @@ -431,6 +432,45 @@ func Test_Issue1733(t *testing.T) { }) } +// https://github.com/gogf/gf/issues/2012 +func Test_Issue2012(t *testing.T) { + table := "time_only_" + guid.S() + if _, err := db.Exec(ctx, fmt.Sprintf(` + CREATE TABLE %s( + id int(8) unsigned zerofill NOT NULL AUTO_INCREMENT, + time_only time, + PRIMARY KEY (id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table, + )); err != nil { + gtest.AssertNil(err) + } + defer dropTable(table) + + type TimeOnly struct { + Id int `json:"id"` + TimeOnly *gtime.Time `json:"timeOnly"` + } + + gtest.C(t, func(t *gtest.T) { + timeOnly := gtime.New("15:04:05") + m := db.Model(table) + + _, err := m.Insert(TimeOnly{ + TimeOnly: gtime.New(timeOnly), + }) + t.AssertNil(err) + + _, err = m.Insert(g.Map{ + "time_only": timeOnly, + }) + t.AssertNil(err) + + _, err = m.Insert("time_only", timeOnly) + t.AssertNil(err) + }) +} + // https://github.com/gogf/gf/issues/2105 func Test_Issue2105(t *testing.T) { table := "issue2105" @@ -1024,7 +1064,7 @@ func Test_Issue2552_ClearTableFieldsAll(t *testing.T) { ctx = context.Background() sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error { one, err := db.Model(table).Ctx(ctx).One() - t.Assert(len(one), 5) + t.Assert(len(one), 6) return err }) t.AssertNil(err) @@ -1039,7 +1079,7 @@ func Test_Issue2552_ClearTableFieldsAll(t *testing.T) { ctx = context.Background() sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error { one, err := db.Model(table).Ctx(ctx).One() - t.Assert(len(one), 4) + t.Assert(len(one), 5) return err }) t.AssertNil(err) @@ -1070,7 +1110,7 @@ func Test_Issue2552_ClearTableFields(t *testing.T) { ctx = context.Background() sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error { one, err := db.Model(table).Ctx(ctx).One() - t.Assert(len(one), 5) + t.Assert(len(one), 6) return err }) t.AssertNil(err) @@ -1085,7 +1125,7 @@ func Test_Issue2552_ClearTableFields(t *testing.T) { ctx = context.Background() sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error { one, err := db.Model(table).Ctx(ctx).One() - t.Assert(len(one), 4) + t.Assert(len(one), 5) return err }) t.AssertNil(err) @@ -1160,3 +1200,212 @@ func Test_Issue3238(t *testing.T) { } }) } + +// https://github.com/gogf/gf/issues/3649 +func Test_Issue3649(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + sql, err := gdb.CatchSQL(context.Background(), func(ctx context.Context) (err error) { + user := db.Model(table).Ctx(ctx) + _, err = user.Where("create_time = ?", gdb.Raw("now()")).WhereLT("create_time", gdb.Raw("now()")).Count() + return + }) + t.AssertNil(err) + sqlStr := fmt.Sprintf("SELECT COUNT(1) FROM `%s` WHERE (create_time = now()) AND (`create_time` < now())", table) + t.Assert(sql[0], sqlStr) + }) +} + +// https://github.com/gogf/gf/issues/3754 +func Test_Issue3754(t *testing.T) { + table := "issue3754" + array := gstr.SplitAndTrim(gtest.DataContent(`issue3754.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + fieldsEx := []string{"delete_at", "create_at", "update_at"} + // Insert. + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).FieldsEx(fieldsEx).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["delete_at"].String(), "") + t.Assert(oneInsert["create_at"].String(), "") + t.Assert(oneInsert["update_at"].String(), "") + + // Update. + dataUpdate := g.Map{ + "name": "name_1000", + } + r, err = db.Model(table).Data(dataUpdate).FieldsEx(fieldsEx).WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["delete_at"].String(), "") + t.Assert(oneUpdate["create_at"].String(), "") + t.Assert(oneUpdate["update_at"].String(), "") + + // FieldsEx does not affect Delete operation. + r, err = db.Model(table).FieldsEx(fieldsEx).WherePri(1).Delete() + n, _ = r.RowsAffected() + t.Assert(n, 1) + oneDeleteUnscoped, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(oneDeleteUnscoped["id"].Int(), 1) + t.Assert(oneDeleteUnscoped["name"].String(), "name_1000") + t.AssertNE(oneDeleteUnscoped["delete_at"].String(), "") + t.Assert(oneDeleteUnscoped["create_at"].String(), "") + t.Assert(oneDeleteUnscoped["update_at"].String(), "") + }) +} + +// https://github.com/gogf/gf/issues/3626 +func Test_Issue3626(t *testing.T) { + table := "issue3626" + array := gstr.SplitAndTrim(gtest.DataContent(`issue3626.sql`), ";") + defer dropTable(table) + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + + // Insert. + gtest.C(t, func(t *gtest.T) { + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + }) + + var ( + cacheKey = guid.S() + cacheFunc = func(duration time.Duration) gdb.HookHandler { + return gdb.HookHandler{ + Select: func(ctx context.Context, in *gdb.HookSelectInput) (result gdb.Result, err error) { + get, err := db.GetCache().Get(ctx, cacheKey) + if err == nil && !get.IsEmpty() { + err = get.Scan(&result) + if err == nil { + return result, nil + } + } + result, err = in.Next(ctx) + if err != nil { + return nil, err + } + if result == nil || result.Len() < 1 { + result = make(gdb.Result, 0) + } + _ = db.GetCache().Set(ctx, cacheKey, result, duration) + return + }, + } + } + ) + gtest.C(t, func(t *gtest.T) { + defer db.GetCache().Clear(ctx) + count, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(count, 1) + count, err = db.Model(table).Hook(cacheFunc(time.Hour)).Count() + t.AssertNil(err) + t.Assert(count, 1) + count, err = db.Model(table).Hook(cacheFunc(time.Hour)).Count() + t.AssertNil(err) + t.Assert(count, 1) + }) +} + +// https://github.com/gogf/gf/issues/3932 +func Test_Issue3932(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Order("id", "desc").One() + t.AssertNil(err) + t.Assert(one["id"], 10) + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Order("id desc").One() + t.AssertNil(err) + t.Assert(one["id"], 10) + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Order("id desc, nickname asc").One() + t.AssertNil(err) + t.Assert(one["id"], 10) + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Order("id desc", "nickname asc").One() + t.AssertNil(err) + t.Assert(one["id"], 10) + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).Order("id desc").Order("nickname asc").One() + t.AssertNil(err) + t.Assert(one["id"], 10) + }) +} + +// https://github.com/gogf/gf/issues/3968 +func Test_Issue3968(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + var hook = gdb.HookHandler{ + Select: func(ctx context.Context, in *gdb.HookSelectInput) (result gdb.Result, err error) { + result, err = in.Next(ctx) + if err != nil { + return nil, err + } + if result != nil { + for i, _ := range result { + result[i]["location"] = gvar.New("ny") + } + } + return + }, + } + var ( + count int + result gdb.Result + ) + err := db.Model(table).Hook(hook).ScanAndCount(&result, &count, false) + t.AssertNil(err) + t.Assert(count, 10) + t.Assert(len(result), 10) + }) +} diff --git a/contrib/drivers/mysql/mysql_z_unit_model_test.go b/contrib/drivers/mysql/mysql_z_unit_model_test.go index e6ef9fc9c..5f3033b36 100644 --- a/contrib/drivers/mysql/mysql_z_unit_model_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_model_test.go @@ -12,6 +12,7 @@ import ( "database/sql" "fmt" "os" + "strings" "testing" "time" @@ -733,6 +734,19 @@ func Test_Model_Count(t *testing.T) { }) } +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + func Test_Model_Value_WithCache(t *testing.T) { table := createTable() defer dropTable(table) @@ -760,7 +774,7 @@ func Test_Model_Value_WithCache(t *testing.T) { value, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{ Duration: time.Second * 10, Force: false, - }).Value() + }).Value("id") t.AssertNil(err) t.Assert(value.Int(), 1) }) @@ -1279,7 +1293,7 @@ func Test_Model_OrderBy(t *testing.T) { }) gtest.C(t, func(t *gtest.T) { - result, err := db.Model(table).Order("NULL").All() + result, err := db.Model(table).Order(gdb.Raw("NULL")).All() t.AssertNil(err) t.Assert(len(result), TableSize) t.Assert(result[0]["nickname"].String(), "name_1") @@ -2335,7 +2349,7 @@ func Test_Model_FieldsEx(t *testing.T) { r, err := db.Model(table).FieldsEx("create_time, id").Where("id in (?)", g.Slice{1, 2}).Order("id asc").All() t.AssertNil(err) t.Assert(len(r), 2) - t.Assert(len(r[0]), 3) + t.Assert(len(r[0]), 4) t.Assert(r[0]["id"], "") t.Assert(r[0]["passport"], "user_1") t.Assert(r[0]["password"], "pass_1") @@ -2964,13 +2978,13 @@ func Test_Model_FieldsEx_AutoMapping(t *testing.T) { // "create_time": gtime.NewFromStr("2018-10-24 10:00:00").String(), gtest.C(t, func(t *gtest.T) { - value, err := db.Model(table).FieldsEx("Passport, Password, NickName, CreateTime").Where("id", 2).Value() + value, err := db.Model(table).FieldsEx("create_date, Passport, Password, NickName, CreateTime").Where("id", 2).Value() t.AssertNil(err) t.Assert(value.Int(), 2) }) gtest.C(t, func(t *gtest.T) { - value, err := db.Model(table).FieldsEx("ID, Passport, Password, CreateTime").Where("id", 2).Value() + value, err := db.Model(table).FieldsEx("create_date, ID, Passport, Password, CreateTime").Where("id", 2).Value() t.AssertNil(err) t.Assert(value.String(), "name_2") }) @@ -2982,7 +2996,7 @@ func Test_Model_FieldsEx_AutoMapping(t *testing.T) { "CreateTime": 1, }).Where("id", 2).One() t.AssertNil(err) - t.Assert(len(one), 2) + t.Assert(len(one), 3) t.Assert(one["id"], 2) t.Assert(one["nickname"], "name_2") }) @@ -2999,7 +3013,7 @@ func Test_Model_FieldsEx_AutoMapping(t *testing.T) { CreateTime: 0, }).Where("id", 2).One() t.AssertNil(err) - t.Assert(len(one), 2) + t.Assert(len(one), 3) t.Assert(one["id"], 2) t.Assert(one["nickname"], "name_2") }) @@ -3157,8 +3171,8 @@ func Test_TimeZoneInsert(t *testing.T) { gtest.AssertNil(err) CreateTime := "2020-11-22 12:23:45" - UpdateTime := "2020-11-22 13:23:45" - DeleteTime := "2020-11-22 14:23:45" + UpdateTime := "2020-11-22 13:23:46" + DeleteTime := "2020-11-22 14:23:47" type User struct { Id int `json:"id"` CreatedAt *gtime.Time `json:"created_at"` @@ -3176,13 +3190,14 @@ func Test_TimeZoneInsert(t *testing.T) { } gtest.C(t, func(t *gtest.T) { - _, _ = db.Model(tableName).Unscoped().Insert(u) + _, err = db.Model(tableName).Unscoped().Insert(u) + t.AssertNil(err) userEntity := &User{} - err := db.Model(tableName).Where("id", 1).Unscoped().Scan(&userEntity) + err = db.Model(tableName).Where("id", 1).Unscoped().Scan(&userEntity) t.AssertNil(err) t.Assert(userEntity.CreatedAt.String(), "2020-11-22 11:23:45") - t.Assert(userEntity.UpdatedAt.String(), "2020-11-22 12:23:45") - t.Assert(gtime.NewFromTime(userEntity.DeletedAt).String(), "2020-11-22 13:23:45") + t.Assert(userEntity.UpdatedAt.String(), "2020-11-22 12:23:46") + t.Assert(gtime.NewFromTime(userEntity.DeletedAt).String(), "2020-11-22 13:23:47") }) } @@ -4785,3 +4800,76 @@ func Test_Model_FixGdbJoin(t *testing.T) { t.Assert(gtest.DataContent(`fix_gdb_join_expect.sql`), sqlSlice[len(sqlSlice)-1]) }) } + +func Test_Model_Year_Date_Time_DateTime_Timestamp(t *testing.T) { + table := "date_time_example" + array := gstr.SplitAndTrim(gtest.DataContent(`date_time_example.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // insert. + var now = gtime.Now() + _, err := db.Model("date_time_example").Insert(g.Map{ + "year": now, + "date": now, + "time": now, + "datetime": now, + "timestamp": now, + }) + t.AssertNil(err) + // select. + one, err := db.Model("date_time_example").One() + t.AssertNil(err) + t.Assert(one["year"].String(), now.Format("Y")) + t.Assert(one["date"].String(), now.Format("Y-m-d")) + t.Assert(one["time"].String(), now.Format("H:i:s")) + t.AssertLT(one["datetime"].GTime().Sub(now).Seconds(), 5) + t.AssertLT(one["timestamp"].GTime().Sub(now).Seconds(), 5) + }) +} + +func Test_OrderBy_Statement_Generated(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := gstr.SplitAndTrim(gtest.DataContent(`fix_gdb_order_by.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable(`employee`) + sqlArray, _ := gdb.CatchSQL(ctx, func(ctx context.Context) error { + g.DB("default").Ctx(ctx).Model("employee").Order("name asc", "age desc").All() + return nil + }) + rawSql := strings.ReplaceAll(sqlArray[len(sqlArray)-1], " ", "") + expectSql := strings.ReplaceAll("SELECT * FROM `employee` ORDER BY `name` asc, `age` desc", " ", "") + t.Assert(rawSql, expectSql) + }) +} + +func Test_Fields_Raw(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + table := createInitTable() + defer dropTable(table) + one, err := db.Model(table).Fields(gdb.Raw("1")).One() + t.AssertNil(err) + t.Assert(one["1"], 1) + + one, err = db.Model(table).Fields(gdb.Raw("2")).One() + t.AssertNil(err) + t.Assert(one["2"], 2) + + one, err = db.Model(table).Fields(gdb.Raw("2")).Where("id", 2).One() + t.AssertNil(err) + t.Assert(one["2"], 2) + + one, err = db.Model(table).Fields(gdb.Raw("2")).Where("id", 10000000000).One() + t.AssertNil(err) + t.Assert(len(one), 0) + }) +} diff --git a/contrib/drivers/mysql/mysql_z_unit_transaction_test.go b/contrib/drivers/mysql/mysql_z_unit_transaction_test.go index f29036092..b0e2a0cc1 100644 --- a/contrib/drivers/mysql/mysql_z_unit_transaction_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_transaction_test.go @@ -20,67 +20,71 @@ import ( ) func Test_TX_Query(t *testing.T) { - tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err = tx.Query("SELECT ?", 1); err != nil { - gtest.Error(err) - } - if _, err = tx.Query("SELECT ?+?", 1, 2); err != nil { - gtest.Error(err) - } - if _, err = tx.Query("SELECT ?+?", g.Slice{1, 2}); err != nil { - gtest.Error(err) - } - if _, err = tx.Query("ERROR"); err == nil { - gtest.Error("FAIL") - } - if err = tx.Commit(); err != nil { - gtest.Error(err) - } + gtest.C(t, func(t *gtest.T) { + tx, err := db.Begin(ctx) + t.AssertNil(err) + + _, err = tx.Query("SELECT ?", 1) + t.AssertNil(err) + + _, err = tx.Query("SELECT ?+?", 1, 2) + t.AssertNil(err) + + _, err = tx.Query("SELECT ?+?", g.Slice{1, 2}) + t.AssertNil(err) + + _, err = tx.Query("ERROR") + t.AssertNE(err, nil) + + err = tx.Commit() + t.AssertNil(err) + + }) } func Test_TX_Exec(t *testing.T) { - tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Exec("SELECT ?", 1); err != nil { - gtest.Error(err) - } - if _, err := tx.Exec("SELECT ?+?", 1, 2); err != nil { - gtest.Error(err) - } - if _, err := tx.Exec("SELECT ?+?", g.Slice{1, 2}); err != nil { - gtest.Error(err) - } - if _, err := tx.Exec("ERROR"); err == nil { - gtest.Error("FAIL") - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + gtest.C(t, func(t *gtest.T) { + tx, err := db.Begin(ctx) + t.AssertNil(err) + + _, err = tx.Exec("SELECT ?", 1) + t.AssertNil(err) + + _, err = tx.Exec("SELECT ?+?", 1, 2) + t.AssertNil(err) + + _, err = tx.Exec("SELECT ?+?", g.Slice{1, 2}) + t.AssertNil(err) + + _, err = tx.Exec("ERROR") + t.AssertNE(err, nil) + + err = tx.Commit() + t.AssertNil(err) + + }) } func Test_TX_Commit(t *testing.T) { - tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + gtest.C(t, func(t *gtest.T) { + tx, err := db.Begin(ctx) + t.AssertNil(err) + + err = tx.Commit() + t.AssertNil(err) + + }) } func Test_TX_Rollback(t *testing.T) { - tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if err := tx.Rollback(); err != nil { - gtest.Error(err) - } + gtest.C(t, func(t *gtest.T) { + tx, err := db.Begin(ctx) + t.AssertNil(err) + + err = tx.Rollback() + t.AssertNil(err) + + }) } func Test_TX_Prepare(t *testing.T) { @@ -96,13 +100,15 @@ func Test_TX_Prepare(t *testing.T) { array, err := rows.Columns() t.AssertNil(err) + t.Assert(array[0], "100") - rows.Close() + err = rows.Close() t.AssertNil(err) - tx.Commit() + err = tx.Commit() t.AssertNil(err) + }) } @@ -112,38 +118,36 @@ func Test_TX_Insert(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + user := tx.Model(table) - if _, err := user.Data(g.Map{ + + _, err = user.Data(g.Map{ "id": 1, "passport": "t1", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "T1", "create_time": gtime.Now().String(), - }).Insert(); err != nil { - gtest.Error(err) - } - if _, err := tx.Insert(table, g.Map{ + }).Insert() + t.AssertNil(err) + + _, err = tx.Insert(table, g.Map{ "id": 2, "passport": "t1", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "T1", "create_time": gtime.Now().String(), - }); err != nil { - gtest.Error(err) - } + }) + t.AssertNil(err) - if n, err := tx.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(2)) - } + n, err := tx.Model(table).Count() + t.AssertNil(err) + + t.Assert(n, int64(2)) + + err = tx.Commit() + t.AssertNil(err) - if err := tx.Commit(); err != nil { - gtest.Error(err) - } }) } @@ -153,10 +157,9 @@ func Test_TX_BatchInsert(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Insert(table, g.List{ + t.AssertNil(err) + + _, err = tx.Insert(table, g.List{ { "id": 2, "passport": "t", @@ -171,17 +174,16 @@ func Test_TX_BatchInsert(t *testing.T) { "nickname": "T3", "create_time": gtime.Now().String(), }, - }, 10); err != nil { - gtest.Error(err) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } - if n, err := db.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(2)) - } + }, 10) + t.AssertNil(err) + + err = tx.Commit() + t.AssertNil(err) + + n, err := db.Model(table).Count() + t.AssertNil(err) + + t.Assert(n, int64(2)) }) } @@ -191,10 +193,9 @@ func Test_TX_BatchReplace(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Replace(table, g.List{ + t.AssertNil(err) + + _, err = tx.Replace(table, g.List{ { "id": 2, "passport": "USER_2", @@ -209,22 +210,21 @@ func Test_TX_BatchReplace(t *testing.T) { "nickname": "NAME_4", "create_time": gtime.Now().String(), }, - }, 10); err != nil { - gtest.Error(err) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } - if n, err := db.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(TableSize)) - } - if value, err := db.Model(table).Fields("password").Where("id", 2).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "PASS_2") - } + }, 10) + t.AssertNil(err) + + err = tx.Commit() + t.AssertNil(err) + + n, err := db.Model(table).Count() + t.AssertNil(err) + + t.Assert(n, int64(TableSize)) + + value, err := db.Model(table).Fields("password").Where("id", 2).Value() + t.AssertNil(err) + + t.Assert(value.String(), "PASS_2") }) } @@ -234,10 +234,9 @@ func Test_TX_BatchSave(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Save(table, g.List{ + t.AssertNil(err) + + _, err = tx.Save(table, g.List{ { "id": 4, "passport": "USER_4", @@ -245,24 +244,21 @@ func Test_TX_BatchSave(t *testing.T) { "nickname": "NAME_4", "create_time": gtime.Now().String(), }, - }, 10); err != nil { - gtest.Error(err) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + }, 10) + t.AssertNil(err) - if n, err := db.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(TableSize)) - } + err = tx.Commit() + t.AssertNil(err) - if value, err := db.Model(table).Fields("password").Where("id", 4).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "PASS_4") - } + n, err := db.Model(table).Count() + t.AssertNil(err) + + t.Assert(n, int64(TableSize)) + + value, err := db.Model(table).Fields("password").Where("id", 4).Value() + t.AssertNil(err) + + t.Assert(value.String(), "PASS_4") }) } @@ -272,26 +268,24 @@ func Test_TX_Replace(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Replace(table, g.Map{ + t.AssertNil(err) + + _, err = tx.Replace(table, g.Map{ "id": 1, "passport": "USER_1", "password": "PASS_1", "nickname": "NAME_1", "create_time": gtime.Now().String(), - }); err != nil { - gtest.Error(err) - } - if err := tx.Rollback(); err != nil { - gtest.Error(err) - } - if value, err := db.Model(table).Fields("nickname").Where("id", 1).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "name_1") - } + }) + t.AssertNil(err) + + err = tx.Rollback() + t.AssertNil(err) + + value, err := db.Model(table).Fields("nickname").Where("id", 1).Value() + t.AssertNil(err) + + t.Assert(value.String(), "name_1") }) } @@ -301,26 +295,24 @@ func Test_TX_Save(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Save(table, g.Map{ + t.AssertNil(err) + + _, err = tx.Save(table, g.Map{ "id": 1, "passport": "USER_1", "password": "PASS_1", "nickname": "NAME_1", "create_time": gtime.Now().String(), - }); err != nil { - gtest.Error(err) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } - if value, err := db.Model(table).Fields("nickname").Where("id", 1).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "NAME_1") - } + }) + t.AssertNil(err) + + err = tx.Commit() + t.AssertNil(err) + + value, err := db.Model(table).Fields("nickname").Where("id", 1).Value() + t.AssertNil(err) + + t.Assert(value.String(), "NAME_1") }) } @@ -330,26 +322,24 @@ func Test_TX_Update(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if result, err := tx.Update(table, "create_time='2019-10-24 10:00:00'", "id=3"); err != nil { - gtest.Error(err) - } else { - n, _ := result.RowsAffected() - t.Assert(n, 1) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + t.AssertNil(err) + + result, err := tx.Update(table, "create_time='2019-10-24 10:00:00'", "id=3") + t.AssertNil(err) + + n, _ := result.RowsAffected() + t.Assert(n, 1) + + err = tx.Commit() + t.AssertNil(err) + _, err = tx.Model(table).Fields("create_time").Where("id", 3).Value() t.AssertNE(err, nil) - if value, err := db.Model(table).Fields("create_time").Where("id", 3).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "2019-10-24 10:00:00") - } + value, err := db.Model(table).Fields("create_time").Where("id", 3).Value() + t.AssertNil(err) + + t.Assert(value.String(), "2019-10-24 10:00:00") }) } @@ -359,17 +349,16 @@ func Test_TX_GetAll(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if result, err := tx.GetAll(fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 1); err != nil { - gtest.Error(err) - } else { - t.Assert(len(result), 1) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + t.AssertNil(err) + + result, err := tx.GetAll(fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 1) + t.AssertNil(err) + + t.Assert(len(result), 1) + + err = tx.Commit() + t.AssertNil(err) + }) } @@ -379,20 +368,17 @@ func Test_TX_GetOne(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if record, err := tx.GetOne(fmt.Sprintf("SELECT * FROM %s WHERE passport=?", table), "user_2"); err != nil { - gtest.Error(err) - } else { - if record == nil { - gtest.Error("FAIL") - } - t.Assert(record["nickname"].String(), "name_2") - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + t.AssertNil(err) + + record, err := tx.GetOne(fmt.Sprintf("SELECT * FROM %s WHERE passport=?", table), "user_2") + t.AssertNil(err) + + t.AssertNE(record, nil) + t.Assert(record["nickname"].String(), "name_2") + + err = tx.Commit() + t.AssertNil(err) + }) } @@ -402,17 +388,16 @@ func Test_TX_GetValue(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if value, err := tx.GetValue(fmt.Sprintf("SELECT id FROM %s WHERE passport=?", table), "user_3"); err != nil { - gtest.Error(err) - } else { - t.Assert(value.Int(), 3) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + t.AssertNil(err) + + value, err := tx.GetValue(fmt.Sprintf("SELECT id FROM %s WHERE passport=?", table), "user_3") + t.AssertNil(err) + + t.Assert(value.Int(), 3) + + err = tx.Commit() + t.AssertNil(err) + }) } @@ -422,17 +407,16 @@ func Test_TX_GetCount(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if count, err := tx.GetCount("SELECT * FROM " + table); err != nil { - gtest.Error(err) - } else { - t.Assert(count, int64(TableSize)) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + t.AssertNil(err) + + count, err := tx.GetCount("SELECT * FROM " + table) + t.AssertNil(err) + + t.Assert(count, int64(TableSize)) + + err = tx.Commit() + t.AssertNil(err) + }) } @@ -442,9 +426,8 @@ func Test_TX_GetStruct(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -453,20 +436,21 @@ func Test_TX_GetStruct(t *testing.T) { CreateTime gtime.Time } user := new(User) - if err := tx.GetStruct(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3); err != nil { - gtest.Error(err) - } + err = tx.GetStruct(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3) + t.AssertNil(err) + t.Assert(user.NickName, "name_3") t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + + err = tx.Commit() + t.AssertNil(err) + }) + gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -475,14 +459,14 @@ func Test_TX_GetStruct(t *testing.T) { CreateTime *gtime.Time } user := new(User) - if err := tx.GetStruct(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3); err != nil { - gtest.Error(err) - } + err = tx.GetStruct(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3) + t.AssertNil(err) + t.Assert(user.NickName, "name_3") t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) } @@ -492,9 +476,8 @@ func Test_TX_GetStructs(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -503,9 +486,9 @@ func Test_TX_GetStructs(t *testing.T) { CreateTime gtime.Time } var users []User - if err := tx.GetStructs(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1); err != nil { - gtest.Error(err) - } + err = tx.GetStructs(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1) + t.AssertNil(err) + t.Assert(len(users), TableSize) t.Assert(users[0].Id, 1) t.Assert(users[1].Id, 2) @@ -514,16 +497,15 @@ func Test_TX_GetStructs(t *testing.T) { t.Assert(users[1].NickName, "name_2") t.Assert(users[2].NickName, "name_3") t.Assert(users[2].CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -532,9 +514,9 @@ func Test_TX_GetStructs(t *testing.T) { CreateTime *gtime.Time } var users []User - if err := tx.GetStructs(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1); err != nil { - gtest.Error(err) - } + err = tx.GetStructs(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1) + t.AssertNil(err) + t.Assert(len(users), TableSize) t.Assert(users[0].Id, 1) t.Assert(users[1].Id, 2) @@ -543,9 +525,9 @@ func Test_TX_GetStructs(t *testing.T) { t.Assert(users[1].NickName, "name_2") t.Assert(users[2].NickName, "name_3") t.Assert(users[2].CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) } @@ -555,9 +537,8 @@ func Test_TX_GetScan(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -566,20 +547,19 @@ func Test_TX_GetScan(t *testing.T) { CreateTime gtime.Time } user := new(User) - if err := tx.GetScan(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3); err != nil { - gtest.Error(err) - } + err = tx.GetScan(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3) + t.AssertNil(err) + t.Assert(user.NickName, "name_3") t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -588,21 +568,20 @@ func Test_TX_GetScan(t *testing.T) { CreateTime *gtime.Time } user := new(User) - if err := tx.GetScan(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3); err != nil { - gtest.Error(err) - } + err = tx.GetScan(user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3) + t.AssertNil(err) + t.Assert(user.NickName, "name_3") t.Assert(user.CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -611,9 +590,9 @@ func Test_TX_GetScan(t *testing.T) { CreateTime gtime.Time } var users []User - if err := tx.GetScan(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1); err != nil { - gtest.Error(err) - } + err = tx.GetScan(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1) + t.AssertNil(err) + t.Assert(len(users), TableSize) t.Assert(users[0].Id, 1) t.Assert(users[1].Id, 2) @@ -622,16 +601,15 @@ func Test_TX_GetScan(t *testing.T) { t.Assert(users[1].NickName, "name_2") t.Assert(users[2].NickName, "name_3") t.Assert(users[2].CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } + t.AssertNil(err) + type User struct { Id int Passport string @@ -640,9 +618,9 @@ func Test_TX_GetScan(t *testing.T) { CreateTime *gtime.Time } var users []User - if err := tx.GetScan(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1); err != nil { - gtest.Error(err) - } + err = tx.GetScan(&users, fmt.Sprintf("SELECT * FROM %s WHERE id>=?", table), 1) + t.AssertNil(err) + t.Assert(len(users), TableSize) t.Assert(users[0].Id, 1) t.Assert(users[1].Id, 2) @@ -651,9 +629,9 @@ func Test_TX_GetScan(t *testing.T) { t.Assert(users[1].NickName, "name_2") t.Assert(users[2].NickName, "name_3") t.Assert(users[2].CreateTime.String(), "2018-10-24 10:00:00") - if err := tx.Commit(); err != nil { - gtest.Error(err) - } + err = tx.Commit() + t.AssertNil(err) + }) } @@ -662,21 +640,18 @@ func Test_TX_Delete(t *testing.T) { table := createInitTable() defer dropTable(table) tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Delete(table, 1); err != nil { - gtest.Error(err) - } - if err := tx.Commit(); err != nil { - gtest.Error(err) - } - if n, err := db.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(0)) - } + t.AssertNil(err) + _, err = tx.Delete(table, 1) + t.AssertNil(err) + + err = tx.Commit() + t.AssertNil(err) + + n, err := db.Model(table).Count() + t.AssertNil(err) + + t.Assert(n, int64(0)) t.Assert(tx.IsClosed(), true) }) @@ -684,27 +659,22 @@ func Test_TX_Delete(t *testing.T) { table := createInitTable() defer dropTable(table) tx, err := db.Begin(ctx) - if err != nil { - gtest.Error(err) - } - if _, err := tx.Delete(table, 1); err != nil { - gtest.Error(err) - } - if n, err := tx.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(0)) - } - if err := tx.Rollback(); err != nil { - gtest.Error(err) - } - if n, err := db.Model(table).Count(); err != nil { - gtest.Error(err) - } else { - t.Assert(n, int64(TableSize)) - t.AssertNE(n, int64(0)) - } + t.AssertNil(err) + _, err = tx.Delete(table, 1) + t.AssertNil(err) + + n, err := tx.Model(table).Count() + t.AssertNil(err) + t.Assert(n, int64(0)) + + err = tx.Rollback() + t.AssertNil(err) + + n, err = db.Model(table).Count() + t.AssertNil(err) + t.Assert(n, int64(TableSize)) + t.AssertNE(n, int64(0)) t.Assert(tx.IsClosed(), true) }) } @@ -716,48 +686,43 @@ func Test_Transaction(t *testing.T) { gtest.C(t, func(t *gtest.T) { ctx := context.TODO() err := db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { - if _, err := tx.Ctx(ctx).Replace(table, g.Map{ + _, err := tx.Ctx(ctx).Replace(table, g.Map{ "id": 1, "passport": "USER_1", "password": "PASS_1", "nickname": "NAME_1", "create_time": gtime.Now().String(), - }); err != nil { - t.Error(err) - } + }) + t.AssertNil(err) + t.Assert(tx.IsClosed(), false) return gerror.New("error") }) t.AssertNE(err, nil) - if value, err := db.Model(table).Ctx(ctx).Fields("nickname").Where("id", 1).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "name_1") - } + value, err := db.Model(table).Ctx(ctx).Fields("nickname").Where("id", 1).Value() + t.AssertNil(err) + t.Assert(value.String(), "name_1") }) gtest.C(t, func(t *gtest.T) { ctx := context.TODO() err := db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { - if _, err := tx.Replace(table, g.Map{ + _, err := tx.Replace(table, g.Map{ "id": 1, "passport": "USER_1", "password": "PASS_1", "nickname": "NAME_1", "create_time": gtime.Now().String(), - }); err != nil { - t.Error(err) - } + }) + t.AssertNil(err) return nil }) t.AssertNil(err) - if value, err := db.Model(table).Fields("nickname").Where("id", 1).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "NAME_1") - } + value, err := db.Model(table).Fields("nickname").Where("id", 1).Value() + t.AssertNil(err) + t.Assert(value.String(), "NAME_1") }) } @@ -768,25 +733,22 @@ func Test_Transaction_Panic(t *testing.T) { gtest.C(t, func(t *gtest.T) { ctx := context.TODO() err := db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { - if _, err := tx.Replace(table, g.Map{ + _, err := tx.Replace(table, g.Map{ "id": 1, "passport": "USER_1", "password": "PASS_1", "nickname": "NAME_1", "create_time": gtime.Now().String(), - }); err != nil { - t.Error(err) - } + }) + t.AssertNil(err) panic("error") return nil }) t.AssertNE(err, nil) - if value, err := db.Model(table).Fields("nickname").Where("id", 1).Value(); err != nil { - gtest.Error(err) - } else { - t.Assert(value.String(), "name_1") - } + value, err := db.Model(table).Fields("nickname").Where("id", 1).Value() + t.AssertNil(err) + t.Assert(value.String(), "name_1") }) } @@ -797,9 +759,11 @@ func Test_Transaction_Nested_Begin_Rollback_Commit(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) t.AssertNil(err) + // tx begin. err = tx.Begin() t.AssertNil(err) + // tx rollback. _, err = tx.Model(table).Data(g.Map{ "id": 1, @@ -809,6 +773,7 @@ func Test_Transaction_Nested_Begin_Rollback_Commit(t *testing.T) { }).Insert() err = tx.Rollback() t.AssertNil(err) + // tx commit. _, err = tx.Model(table).Data(g.Map{ "id": 2, @@ -818,9 +783,11 @@ func Test_Transaction_Nested_Begin_Rollback_Commit(t *testing.T) { }).Insert() err = tx.Commit() t.AssertNil(err) + // check data. all, err := db.Model(table).All() t.AssertNil(err) + t.Assert(len(all), 1) t.Assert(all[0]["id"], 2) }) @@ -853,21 +820,27 @@ func Test_Transaction_Nested_TX_Transaction_UseTX(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + // rollback err = tx.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { _, err = tx.Model(table).Data(g.Map{ @@ -878,6 +851,7 @@ func Test_Transaction_Nested_TX_Transaction_UseTX(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + panic("error") return err }) @@ -888,6 +862,7 @@ func Test_Transaction_Nested_TX_Transaction_UseTX(t *testing.T) { all, err := db.Ctx(ctx).Model(table).All() t.AssertNil(err) + t.Assert(len(all), 1) t.Assert(all[0]["id"], 1) @@ -907,21 +882,27 @@ func Test_Transaction_Nested_TX_Transaction_UseTX(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + // rollback err = tx.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { _, err = tx.Model(table).Data(g.Map{ @@ -932,6 +913,7 @@ func Test_Transaction_Nested_TX_Transaction_UseTX(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + panic("error") return err }) @@ -942,6 +924,7 @@ func Test_Transaction_Nested_TX_Transaction_UseTX(t *testing.T) { all, err = db.Ctx(ctx).Model(table).All() t.AssertNil(err) + t.Assert(len(all), 2) t.Assert(all[0]["id"], 1) t.Assert(all[1]["id"], 3) @@ -975,18 +958,23 @@ func Test_Transaction_Nested_TX_Transaction_UseDB(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) @@ -1001,6 +989,7 @@ func Test_Transaction_Nested_TX_Transaction_UseDB(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + // panic makes this transaction rollback. panic("error") return err @@ -1009,8 +998,10 @@ func Test_Transaction_Nested_TX_Transaction_UseDB(t *testing.T) { return nil }) t.AssertNil(err) + all, err := db.Model(table).All() t.AssertNil(err) + t.Assert(len(all), 1) t.Assert(all[0]["id"], 1) @@ -1029,18 +1020,23 @@ func Test_Transaction_Nested_TX_Transaction_UseDB(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) + return err }) t.AssertNil(err) @@ -1055,6 +1051,7 @@ func Test_Transaction_Nested_TX_Transaction_UseDB(t *testing.T) { "create_time": gtime.Now().String(), }).Insert() t.AssertNil(err) + // panic makes this transaction rollback. panic("error") return err @@ -1066,6 +1063,7 @@ func Test_Transaction_Nested_TX_Transaction_UseDB(t *testing.T) { all, err = db.Model(table).All() t.AssertNil(err) + t.Assert(len(all), 2) t.Assert(all[0]["id"], 1) t.Assert(all[1]["id"], 3) @@ -1079,6 +1077,7 @@ func Test_Transaction_Nested_SavePoint_RollbackTo(t *testing.T) { gtest.C(t, func(t *gtest.T) { tx, err := db.Begin(ctx) t.AssertNil(err) + // tx save point. _, err = tx.Model(table).Data(g.Map{ "id": 1, @@ -1088,6 +1087,7 @@ func Test_Transaction_Nested_SavePoint_RollbackTo(t *testing.T) { }).Insert() err = tx.SavePoint("MyPoint") t.AssertNil(err) + _, err = tx.Model(table).Data(g.Map{ "id": 2, "passport": "user_2", @@ -1097,6 +1097,7 @@ func Test_Transaction_Nested_SavePoint_RollbackTo(t *testing.T) { // tx rollback to. err = tx.RollbackTo("MyPoint") t.AssertNil(err) + // tx commit. err = tx.Commit() t.AssertNil(err) @@ -1104,6 +1105,7 @@ func Test_Transaction_Nested_SavePoint_RollbackTo(t *testing.T) { // check data. all, err := db.Model(table).All() t.AssertNil(err) + t.Assert(len(all), 1) t.Assert(all[0]["id"], 1) }) @@ -1130,12 +1132,14 @@ func Test_Transaction_Method(t *testing.T) { "VALUES('t2','25d55ad283aa400af464c76d713c07ad','T2','2021-08-25 21:53:00',2) ", table)) t.AssertNil(err) + return gerror.New("rollback") }) t.AssertNE(err, nil) count, err := db.Model(table).Count() t.AssertNil(err) + t.Assert(count, int64(0)) }) } diff --git a/contrib/drivers/mysql/testdata/date_time_example.sql b/contrib/drivers/mysql/testdata/date_time_example.sql new file mode 100644 index 000000000..4dc0568a9 --- /dev/null +++ b/contrib/drivers/mysql/testdata/date_time_example.sql @@ -0,0 +1,9 @@ +CREATE TABLE `date_time_example` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `year` year DEFAULT NULL COMMENT 'year', + `date` date DEFAULT NULL COMMENT 'Date', + `time` time DEFAULT NULL COMMENT 'time', + `datetime` datetime DEFAULT NULL COMMENT 'datetime', + `timestamp` timestamp NULL DEFAULT NULL COMMENT 'Timestamp', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/contrib/drivers/mysql/testdata/fix_gdb_order_by.sql b/contrib/drivers/mysql/testdata/fix_gdb_order_by.sql new file mode 100644 index 000000000..2ba712641 --- /dev/null +++ b/contrib/drivers/mysql/testdata/fix_gdb_order_by.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `employee` +( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + age INT NOT NULL +); + +INSERT INTO employee(name, age) VALUES ('John', 30); +INSERT INTO employee(name, age) VALUES ('Mary', 28); \ No newline at end of file diff --git a/contrib/drivers/mysql/testdata/issue3626.sql b/contrib/drivers/mysql/testdata/issue3626.sql new file mode 100644 index 000000000..e4ee53023 --- /dev/null +++ b/contrib/drivers/mysql/testdata/issue3626.sql @@ -0,0 +1,5 @@ +CREATE TABLE `issue3626` ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/mysql/testdata/issue3754.sql b/contrib/drivers/mysql/testdata/issue3754.sql new file mode 100644 index 000000000..e6cdac030 --- /dev/null +++ b/contrib/drivers/mysql/testdata/issue3754.sql @@ -0,0 +1,8 @@ +CREATE TABLE `issue3754` ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(0) DEFAULT NULL, + update_at datetime(0) DEFAULT NULL, + delete_at datetime(0) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/mysql/testdata/with_tpl_user.sql b/contrib/drivers/mysql/testdata/with_tpl_user.sql new file mode 100644 index 000000000..032e9c55d --- /dev/null +++ b/contrib/drivers/mysql/testdata/with_tpl_user.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/mysql/testdata/with_tpl_user_detail.sql b/contrib/drivers/mysql/testdata/with_tpl_user_detail.sql new file mode 100644 index 000000000..54bbccd09 --- /dev/null +++ b/contrib/drivers/mysql/testdata/with_tpl_user_detail.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/mysql/testdata/with_tpl_user_scores.sql b/contrib/drivers/mysql/testdata/with_tpl_user_scores.sql new file mode 100644 index 000000000..d1640ee0a --- /dev/null +++ b/contrib/drivers/mysql/testdata/with_tpl_user_scores.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/oracle/go.mod b/contrib/drivers/oracle/go.mod index 2aa5d7007..2a4e319c1 100644 --- a/contrib/drivers/oracle/go.mod +++ b/contrib/drivers/oracle/go.mod @@ -1,34 +1,35 @@ module github.com/gogf/gf/contrib/drivers/oracle/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/sijms/go-ora/v2 v2.7.10 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/oracle/go.sum b/contrib/drivers/oracle/go.sum index 62895980d..4a2015402 100644 --- a/contrib/drivers/oracle/go.sum +++ b/contrib/drivers/oracle/go.sum @@ -1,22 +1,22 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -33,25 +33,27 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/sijms/go-ora/v2 v2.7.10 h1:GSLdj0PYYgSndhsnm7b6p32OqgnwnUZSkFb3j+htfhI= github.com/sijms/go-ora/v2 v2.7.10/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/drivers/oracle/oracle.go b/contrib/drivers/oracle/oracle.go index ab079e2d8..ae6a1c5dd 100644 --- a/contrib/drivers/oracle/oracle.go +++ b/contrib/drivers/oracle/oracle.go @@ -21,7 +21,8 @@ type Driver struct { } const ( - quoteChar = `"` + rowNumberAliasForSelect = `ROW_NUMBER__` + quoteChar = `"` ) func init() { diff --git a/contrib/drivers/oracle/oracle_do_commit.go b/contrib/drivers/oracle/oracle_do_commit.go new file mode 100644 index 000000000..19fc88f95 --- /dev/null +++ b/contrib/drivers/oracle/oracle_do_commit.go @@ -0,0 +1,29 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package oracle + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" +) + +// DoCommit commits current sql and arguments to underlying sql driver. +func (d *Driver) DoCommit(ctx context.Context, in gdb.DoCommitInput) (out gdb.DoCommitOutput, err error) { + out, err = d.Core.DoCommit(ctx, in) + if err != nil { + return + } + if len(out.Records) > 0 { + // remove auto added field. + for i, record := range out.Records { + delete(record, rowNumberAliasForSelect) + out.Records[i] = record + } + } + return +} diff --git a/contrib/drivers/oracle/oracle_do_filter.go b/contrib/drivers/oracle/oracle_do_filter.go index 0d9f8ed49..0f952857c 100644 --- a/contrib/drivers/oracle/oracle_do_filter.go +++ b/contrib/drivers/oracle/oracle_do_filter.go @@ -20,9 +20,8 @@ import ( var ( newSqlReplacementTmp = ` SELECT * FROM ( - SELECT GFORM.*, ROWNUM ROWNUM_ FROM (%s %s) GFORM WHERE ROWNUM <= %d -) - WHERE ROWNUM_ > %d + SELECT GFORM.*, ROWNUM ROW_NUMBER__ FROM (%s %s) GFORM WHERE ROWNUM <= %d +) WHERE ROW_NUMBER__ > %d ` ) diff --git a/contrib/drivers/oracle/oracle_order.go b/contrib/drivers/oracle/oracle_order.go new file mode 100644 index 000000000..60d7157c4 --- /dev/null +++ b/contrib/drivers/oracle/oracle_order.go @@ -0,0 +1,12 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package oracle + +// OrderRandomFunction returns the SQL function for random ordering. +func (d *Driver) OrderRandomFunction() string { + return "DBMS_RANDOM.VALUE()" +} diff --git a/contrib/drivers/oracle/oracle_z_unit_model_test.go b/contrib/drivers/oracle/oracle_z_unit_model_test.go index 3763564c8..b9ecb5b4c 100644 --- a/contrib/drivers/oracle/oracle_z_unit_model_test.go +++ b/contrib/drivers/oracle/oracle_z_unit_model_test.go @@ -460,6 +460,19 @@ func Test_Model_Count(t *testing.T) { } +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + func Test_Model_Select(t *testing.T) { table := createInitTable() defer dropTable(table) @@ -1177,6 +1190,17 @@ func Test_Model_Replace(t *testing.T) { }) } +func Test_OrderRandom(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).OrderRandom().All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + }) +} + /* not support the "AS" func Test_Model_Raw(t *testing.T) { table := createInitTable() diff --git a/contrib/drivers/pgsql/go.mod b/contrib/drivers/pgsql/go.mod index 96315fa14..74d72cb9b 100644 --- a/contrib/drivers/pgsql/go.mod +++ b/contrib/drivers/pgsql/go.mod @@ -1,34 +1,35 @@ module github.com/gogf/gf/contrib/drivers/pgsql/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/lib/pq v1.10.9 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/pgsql/go.sum b/contrib/drivers/pgsql/go.sum index a4e6f627d..577f08841 100644 --- a/contrib/drivers/pgsql/go.sum +++ b/contrib/drivers/pgsql/go.sum @@ -1,22 +1,22 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -35,23 +35,25 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/drivers/pgsql/pgsql_convert.go b/contrib/drivers/pgsql/pgsql_convert.go index dc71a8cc4..71657669b 100644 --- a/contrib/drivers/pgsql/pgsql_convert.go +++ b/contrib/drivers/pgsql/pgsql_convert.go @@ -12,6 +12,7 @@ import ( "strings" "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/gogf/gf/v2/util/gconv" @@ -19,17 +20,22 @@ import ( // ConvertValueForField converts value to database acceptable value. func (d *Driver) ConvertValueForField(ctx context.Context, fieldType string, fieldValue interface{}) (interface{}, error) { - var ( - fieldValueKind = reflect.TypeOf(fieldValue).Kind() - ) + if g.IsNil(fieldValue) { + return d.Core.ConvertValueForField(ctx, fieldType, fieldValue) + } + + var fieldValueKind = reflect.TypeOf(fieldValue).Kind() if fieldValueKind == reflect.Slice { - fieldValue = gstr.ReplaceByMap(gconv.String(fieldValue), - map[string]string{ - "[": "{", - "]": "}", - }, - ) + // For pgsql, json or jsonb require '[]' + if !gstr.Contains(fieldType, "json") { + fieldValue = gstr.ReplaceByMap(gconv.String(fieldValue), + map[string]string{ + "[": "{", + "]": "}", + }, + ) + } } return d.Core.ConvertValueForField(ctx, fieldType, fieldValue) } diff --git a/contrib/drivers/pgsql/pgsql_do_filter.go b/contrib/drivers/pgsql/pgsql_do_filter.go index fa0b1c4a5..a595d908a 100644 --- a/contrib/drivers/pgsql/pgsql_do_filter.go +++ b/contrib/drivers/pgsql/pgsql_do_filter.go @@ -9,9 +9,9 @@ package pgsql import ( "context" "fmt" - "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/text/gregex" + "github.com/gogf/gf/v2/text/gstr" ) // DoFilter deals with the sql string before commits it to underlying sql driver. @@ -31,9 +31,13 @@ func (d *Driver) DoFilter( // Refer: // https://github.com/gogf/gf/issues/1537 // https://www.postgresql.org/docs/12/functions-json.html - newSql, err = gregex.ReplaceStringFuncMatch(`(::jsonb([^\w\d]*)\$\d)`, newSql, func(match []string) string { - return fmt.Sprintf(`::jsonb%s?`, match[2]) - }) + newSql, err = gregex.ReplaceStringFuncMatch( + `(::jsonb([^\w\d]*)\$\d)`, + newSql, + func(match []string) string { + return fmt.Sprintf(`::jsonb%s?`, match[2]) + }, + ) if err != nil { return "", nil, err } @@ -41,6 +45,13 @@ func (d *Driver) DoFilter( if err != nil { return "", nil, err } + + // Add support for pgsql INSERT OR IGNORE. + if gstr.HasPrefix(newSql, gdb.InsertOperationIgnore) { + newSql = "INSERT" + newSql[len(gdb.InsertOperationIgnore):] + " ON CONFLICT DO NOTHING" + } + newArgs = args + return d.Core.DoFilter(ctx, link, newSql, newArgs) } diff --git a/contrib/drivers/pgsql/pgsql_do_insert.go b/contrib/drivers/pgsql/pgsql_do_insert.go index 0e0ac31de..15a102cdc 100644 --- a/contrib/drivers/pgsql/pgsql_do_insert.go +++ b/contrib/drivers/pgsql/pgsql_do_insert.go @@ -9,7 +9,6 @@ package pgsql import ( "context" "database/sql" - "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" @@ -24,12 +23,6 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list `Replace operation is not supported by pgsql driver`, ) - case gdb.InsertOptionIgnore: - return nil, gerror.NewCode( - gcode.CodeNotSupported, - `Insert ignore operation is not supported by pgsql driver`, - ) - case gdb.InsertOptionDefault: tableFields, err := d.GetCore().GetDB().TableFields(ctx, table) if err == nil { diff --git a/contrib/drivers/pgsql/pgsql_open.go b/contrib/drivers/pgsql/pgsql_open.go index 7bbd98462..21d3dce13 100644 --- a/contrib/drivers/pgsql/pgsql_open.go +++ b/contrib/drivers/pgsql/pgsql_open.go @@ -34,16 +34,12 @@ func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) { source, _ = gregex.ReplaceString(`dbname=([\w\.\-]+)+`, "dbname="+config.Name, source) } } else { + source = fmt.Sprintf( + "user=%s password='%s' host=%s port=%s sslmode=disable", + config.User, config.Pass, config.Host, config.Port) + if config.Name != "" { - source = fmt.Sprintf( - "user=%s password=%s host=%s port=%s dbname=%s sslmode=disable", - config.User, config.Pass, config.Host, config.Port, config.Name, - ) - } else { - source = fmt.Sprintf( - "user=%s password=%s host=%s port=%s sslmode=disable", - config.User, config.Pass, config.Host, config.Port, - ) + source = fmt.Sprintf("%s dbname=%s", source, config.Name) } if config.Namespace != "" { diff --git a/contrib/drivers/pgsql/pgsql_order.go b/contrib/drivers/pgsql/pgsql_order.go new file mode 100644 index 000000000..6fedce1eb --- /dev/null +++ b/contrib/drivers/pgsql/pgsql_order.go @@ -0,0 +1,12 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package pgsql + +// OrderRandomFunction returns the SQL function for random ordering. +func (d *Driver) OrderRandomFunction() string { + return "RANDOM()" +} diff --git a/contrib/drivers/pgsql/pgsql_z_unit_db_test.go b/contrib/drivers/pgsql/pgsql_z_unit_db_test.go index 9cadd86d1..fabccc45f 100644 --- a/contrib/drivers/pgsql/pgsql_z_unit_db_test.go +++ b/contrib/drivers/pgsql/pgsql_z_unit_db_test.go @@ -383,3 +383,115 @@ int_col INT);` }) } + +func Test_DB_InsertIgnore(t *testing.T) { + table := createTable() + defer dropTable(table) + + // Insert test record + gtest.C(t, func(t *gtest.T) { + _, err := db.Insert(ctx, table, g.Map{ + "id": 1, + "passport": "t1", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "T1", + "create_time": gtime.Now().String(), + }) + t.AssertNil(err) + + answer, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 1) + t.AssertNil(err) + t.Assert(len(answer), 1) + t.Assert(answer[0]["passport"], "t1") + t.Assert(answer[0]["password"], "25d55ad283aa400af464c76d713c07ad") + t.Assert(answer[0]["nickname"], "T1") + + // Ignore Duplicate record + result, err := db.InsertIgnore(ctx, table, g.Map{ + "id": 1, + "passport": "t1_duplicate", + "password": "duplicate_password", + "nickname": "Duplicate", + "create_time": gtime.Now().String(), + }) + t.AssertNil(err) + + n, _ := result.RowsAffected() + t.Assert(n, 0) + + answer, err = db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 1) + t.AssertNil(err) + t.Assert(len(answer), 1) + t.Assert(answer[0]["passport"], "t1") + t.Assert(answer[0]["password"], "25d55ad283aa400af464c76d713c07ad") + t.Assert(answer[0]["nickname"], "T1") + + // Insert Correct Record + result, err = db.Insert(ctx, table, g.Map{ + "id": 2, + "passport": "t2", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_2", + "create_time": gtime.Now().String(), + }) + t.AssertNil(err) + n, _ = result.RowsAffected() + t.Assert(n, 1) + + answer, err = db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 2) + t.AssertNil(err) + t.Assert(len(answer), 1) + t.Assert(answer[0]["passport"], "t2") + t.Assert(answer[0]["password"], "25d55ad283aa400af464c76d713c07ad") + t.Assert(answer[0]["nickname"], "name_2") + + // Insert Multiple Records Using g.Map Array + data := g.List{ + { + "id": 3, + "passport": "t3", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_3", + "create_time": gtime.Now().String(), + }, + { + "id": 4, + "passport": "t4", + "password": "25d55ad283aa400af464c76d713c07ad", + "nickname": "name_4", + "create_time": gtime.Now().String(), + }, + { + "id": 1, + "passport": "t1_conflict", + "password": "conflict_password", + "nickname": "conflict_name", + "create_time": gtime.Now().String(), + }, + { + "id": 2, + "passport": "t2_conflict", + "password": "conflict_password", + "nickname": "conflict_name", + "create_time": gtime.Now().String(), + }, + } + + // Insert Multiple Records with Ignore + result, err = db.InsertIgnore(ctx, table, data) + t.AssertNil(err) + + n, _ = result.RowsAffected() + t.Assert(n, 2) + + answer, err = db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s", table)) + t.AssertNil(err) + t.Assert(len(answer), 4) + // Should have four records in total (ID 1, 2, 3, 4) + + t.Assert(answer[0]["passport"], "t1") + t.Assert(answer[1]["passport"], "t2") + t.Assert(answer[2]["passport"], "t3") + t.Assert(answer[3]["passport"], "t4") + }) +} diff --git a/contrib/drivers/pgsql/pgsql_z_unit_issue_test.go b/contrib/drivers/pgsql/pgsql_z_unit_issue_test.go index 492826c21..b329cdfdf 100644 --- a/contrib/drivers/pgsql/pgsql_z_unit_issue_test.go +++ b/contrib/drivers/pgsql/pgsql_z_unit_issue_test.go @@ -103,3 +103,72 @@ func Test_Issue3632(t *testing.T) { t.AssertNil(err) }) } + +// https://github.com/gogf/gf/issues/3671 +func Test_Issue3671(t *testing.T) { + type SubMember struct { + Seven string + Eight int64 + } + type Member struct { + One []int64 `json:"one" orm:"one"` + Two [][]string `json:"two" orm:"two"` + Three []string `json:"three" orm:"three"` + Four []int64 `json:"four" orm:"four"` + Five []SubMember `json:"five" orm:"five"` + } + var ( + sqlText = gtest.DataContent("issues", "issue3671.sql") + table = fmt.Sprintf(`%s_%d`, TablePrefix+"issue3632", gtime.TimestampNano()) + ) + if _, err := db.Exec(ctx, fmt.Sprintf(sqlText, table)); err != nil { + gtest.Fatal(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + var ( + dao = db.Model(table) + member = Member{ + One: []int64{1, 2, 3}, + Two: [][]string{{"a", "b"}, {"c", "d"}}, + Three: []string{"x", "y", "z"}, + Four: []int64{1, 2, 3}, + Five: []SubMember{{Seven: "1", Eight: 2}, {Seven: "3", Eight: 4}}, + } + ) + + _, err := dao.Ctx(ctx).Data(&member).Insert() + t.AssertNil(err) + }) +} + +// https://github.com/gogf/gf/issues/3668 +func Test_Issue3668(t *testing.T) { + type Issue3668 struct { + Text interface{} + Number interface{} + } + var ( + sqlText = gtest.DataContent("issues", "issue3668.sql") + table = fmt.Sprintf(`%s_%d`, TablePrefix+"issue3668", gtime.TimestampNano()) + ) + if _, err := db.Exec(ctx, fmt.Sprintf(sqlText, table)); err != nil { + gtest.Fatal(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + var ( + dao = db.Model(table) + data = Issue3668{ + Text: "我们都是自然的婴儿,卧在宇宙的摇篮里", + Number: nil, + } + ) + _, err := dao.Ctx(ctx). + Data(data). + Insert() + t.AssertNil(err) + }) +} diff --git a/contrib/drivers/pgsql/pgsql_z_unit_model_test.go b/contrib/drivers/pgsql/pgsql_z_unit_model_test.go index 781438b76..634de6dc8 100644 --- a/contrib/drivers/pgsql/pgsql_z_unit_model_test.go +++ b/contrib/drivers/pgsql/pgsql_z_unit_model_test.go @@ -226,6 +226,19 @@ func Test_Model_Count(t *testing.T) { }) } +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + func Test_Model_Where(t *testing.T) { table := createInitTable() defer dropTable(table) @@ -587,3 +600,14 @@ func Test_Model_OnDuplicateEx(t *testing.T) { t.Assert(one["nickname"], "name_1") }) } + +func Test_OrderRandom(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).OrderRandom().All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + }) +} diff --git a/contrib/drivers/pgsql/testdata/issues/issue3668.sql b/contrib/drivers/pgsql/testdata/issues/issue3668.sql new file mode 100644 index 000000000..968231ab6 --- /dev/null +++ b/contrib/drivers/pgsql/testdata/issues/issue3668.sql @@ -0,0 +1,4 @@ +CREATE TABLE "public"."%s" ( + "text" varchar(255) COLLATE "pg_catalog"."default", + "number" int4 +); diff --git a/contrib/drivers/pgsql/testdata/issues/issue3671.sql b/contrib/drivers/pgsql/testdata/issues/issue3671.sql new file mode 100644 index 000000000..57d78d70c --- /dev/null +++ b/contrib/drivers/pgsql/testdata/issues/issue3671.sql @@ -0,0 +1,8 @@ +CREATE TABLE "public"."%s" +( + "one" int8[] NOT NULL, + "two" text[][] NOT NULL, + "three" jsonb, + "four" json, + "five" jsonb +); diff --git a/contrib/drivers/sqlite/go.mod b/contrib/drivers/sqlite/go.mod index 45ec898ac..48b040e0f 100644 --- a/contrib/drivers/sqlite/go.mod +++ b/contrib/drivers/sqlite/go.mod @@ -1,23 +1,23 @@ module github.com/gogf/gf/contrib/drivers/sqlite/v2 -go 1.18 +go 1.20 require ( github.com/glebarez/go-sqlite v1.21.2 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -25,13 +25,14 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect modernc.org/mathutil v1.5.0 // indirect diff --git a/contrib/drivers/sqlite/go.sum b/contrib/drivers/sqlite/go.sum index 33d70c163..8707f88d5 100644 --- a/contrib/drivers/sqlite/go.sum +++ b/contrib/drivers/sqlite/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -7,23 +7,23 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= 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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -43,23 +43,25 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/drivers/sqlite/sqlite_do_filter.go b/contrib/drivers/sqlite/sqlite_do_filter.go index fa6057674..3547b800e 100644 --- a/contrib/drivers/sqlite/sqlite_do_filter.go +++ b/contrib/drivers/sqlite/sqlite_do_filter.go @@ -14,7 +14,9 @@ import ( ) // DoFilter deals with the sql string before commits it to underlying sql driver. -func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) { +func (d *Driver) DoFilter( + ctx context.Context, link gdb.Link, sql string, args []interface{}, +) (newSql string, newArgs []interface{}, err error) { // Special insert/ignore operation for sqlite. switch { case gstr.HasPrefix(sql, gdb.InsertOperationIgnore): diff --git a/contrib/drivers/sqlite/sqlite_order.go b/contrib/drivers/sqlite/sqlite_order.go new file mode 100644 index 000000000..075e67ef9 --- /dev/null +++ b/contrib/drivers/sqlite/sqlite_order.go @@ -0,0 +1,12 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package sqlite + +// OrderRandomFunction returns the SQL function for random ordering. +func (d *Driver) OrderRandomFunction() string { + return "RANDOM()" +} diff --git a/contrib/drivers/sqlite/sqlite_z_unit_core_test.go b/contrib/drivers/sqlite/sqlite_z_unit_core_test.go index 95c5cd68d..1c151472f 100644 --- a/contrib/drivers/sqlite/sqlite_z_unit_core_test.go +++ b/contrib/drivers/sqlite/sqlite_z_unit_core_test.go @@ -831,7 +831,7 @@ func Test_DB_ToJson(t *testing.T) { } // ToJson - resultJson, err := gjson.LoadContent(result.Json()) + resultJson, err := gjson.LoadContent([]byte(result.Json())) if err != nil { gtest.Fatal(err) } diff --git a/contrib/drivers/sqlite/sqlite_z_unit_init_test.go b/contrib/drivers/sqlite/sqlite_z_unit_init_test.go index 6d82d9412..5a9aa66ed 100644 --- a/contrib/drivers/sqlite/sqlite_z_unit_init_test.go +++ b/contrib/drivers/sqlite/sqlite_z_unit_init_test.go @@ -111,13 +111,9 @@ func createTableWithDb(db gdb.DB, table ...string) (name string) { if _, err := db.Exec(ctx, fmt.Sprintf(` CREATE TABLE %s ( - id INTEGER PRIMARY KEY AUTOINCREMENT - UNIQUE - NOT NULL, - passport VARCHAR(45) NOT NULL - DEFAULT passport, - password VARCHAR(128) NOT NULL - DEFAULT password, + id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, + passport VARCHAR(45) NOT NULL DEFAULT passport, + password VARCHAR(128) NOT NULL DEFAULT password, nickname VARCHAR(45), create_time DATETIME ); @@ -125,7 +121,6 @@ func createTableWithDb(db gdb.DB, table ...string) (name string) { )); err != nil { gtest.Fatal(err) } - return } diff --git a/contrib/drivers/sqlite/sqlite_z_unit_model_test.go b/contrib/drivers/sqlite/sqlite_z_unit_model_test.go index 7734bb5b7..19e97bfa5 100644 --- a/contrib/drivers/sqlite/sqlite_z_unit_model_test.go +++ b/contrib/drivers/sqlite/sqlite_z_unit_model_test.go @@ -650,6 +650,7 @@ func Test_Model_AllAndCount(t *testing.T) { t.Assert(len(result), TableSize) t.Assert(count, TableSize) }) + // AllAndCount with no data gtest.C(t, func(t *gtest.T) { result, count, err := db.Model(table).Where("id<0").AllAndCount(false) @@ -864,6 +865,19 @@ func Test_Model_Count(t *testing.T) { }) } +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + func Test_Model_Select(t *testing.T) { table := createInitTable() defer dropTable(table) @@ -1417,7 +1431,7 @@ func Test_Model_OrderBy(t *testing.T) { }) gtest.C(t, func(t *gtest.T) { - result, err := db.Model(table).Order("NULL").All() + result, err := db.Model(table).Order(gdb.Raw("NULL")).All() t.AssertNil(err) t.Assert(len(result), TableSize) t.Assert(result[0]["nickname"].String(), "name_1") @@ -4299,3 +4313,14 @@ func TestResult_Structs1(t *testing.T) { t.Assert(array[1].Name, "smith") }) } + +func Test_OrderRandom(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + result, err := db.Model(table).OrderRandom().All() + t.AssertNil(err) + t.Assert(len(result), TableSize) + }) +} diff --git a/contrib/drivers/sqlitecgo/go.mod b/contrib/drivers/sqlitecgo/go.mod index ad3de69f5..1435ed4ff 100644 --- a/contrib/drivers/sqlitecgo/go.mod +++ b/contrib/drivers/sqlitecgo/go.mod @@ -1,34 +1,35 @@ module github.com/gogf/gf/contrib/drivers/sqlitecgo/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/mattn/go-sqlite3 v1.14.17 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/drivers/sqlitecgo/go.sum b/contrib/drivers/sqlitecgo/go.sum index b786b4bbd..8217c5949 100644 --- a/contrib/drivers/sqlitecgo/go.sum +++ b/contrib/drivers/sqlitecgo/go.sum @@ -1,22 +1,22 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -35,23 +35,25 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go b/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go index f53e4eadf..6c578225e 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go @@ -16,7 +16,9 @@ import ( ) // DoFilter deals with the sql string before commits it to underlying sql driver. -func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) { +func (d *Driver) DoFilter( + ctx context.Context, link gdb.Link, sql string, args []interface{}, +) (newSql string, newArgs []interface{}, err error) { // Special insert/ignore operation for sqlite. switch { case gstr.HasPrefix(sql, gdb.InsertOperationIgnore): diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_core_test.go b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_core_test.go index fee914add..fa2fe2c71 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_core_test.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_core_test.go @@ -831,7 +831,7 @@ func Test_DB_ToJson(t *testing.T) { } // ToJson - resultJson, err := gjson.LoadContent(result.Json()) + resultJson, err := gjson.LoadContent([]byte(result.Json())) if err != nil { gtest.Fatal(err) } diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go index 05e146d76..613ef9c64 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go @@ -824,6 +824,19 @@ func Test_Model_Count(t *testing.T) { }) } +func Test_Model_Exist(t *testing.T) { + table := createInitTable() + defer dropTable(table) + gtest.C(t, func(t *gtest.T) { + exist, err := db.Model(table).Exist() + t.AssertNil(err) + t.Assert(exist, TableSize > 0) + exist, err = db.Model(table).Where("id", -1).Exist() + t.AssertNil(err) + t.Assert(exist, false) + }) +} + func Test_Model_Select(t *testing.T) { table := createInitTable() defer dropTable(table) @@ -1377,7 +1390,7 @@ func Test_Model_OrderBy(t *testing.T) { }) gtest.C(t, func(t *gtest.T) { - result, err := db.Model(table).Order("NULL").All() + result, err := db.Model(table).Order(gdb.Raw("NULL")).All() t.AssertNil(err) t.Assert(len(result), TableSize) t.Assert(result[0]["nickname"].String(), "name_1") diff --git a/contrib/metric/otelmetric/go.mod b/contrib/metric/otelmetric/go.mod index 48036c369..f12c66382 100644 --- a/contrib/metric/otelmetric/go.mod +++ b/contrib/metric/otelmetric/go.mod @@ -1,15 +1,15 @@ module github.com/gogf/gf/contrib/metric/otelmetric/v2 -go 1.21 +go 1.22 require ( github.com/gogf/gf/v2 v2.7.2 github.com/prometheus/client_golang v1.19.1 go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 - go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel v1.32.0 go.opentelemetry.io/otel/exporters/prometheus v0.50.0 - go.opentelemetry.io/otel/metric v1.28.0 - go.opentelemetry.io/otel/sdk v1.28.0 + go.opentelemetry.io/otel/metric v1.32.0 + go.opentelemetry.io/otel/sdk v1.32.0 go.opentelemetry.io/otel/sdk/metric v1.28.0 ) @@ -19,7 +19,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.17.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -29,7 +29,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -37,10 +37,10 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/metric/otelmetric/go.sum b/contrib/metric/otelmetric/go.sum index 14d7934e4..08814e6ab 100644 --- a/contrib/metric/otelmetric/go.sum +++ b/contrib/metric/otelmetric/go.sum @@ -10,8 +10,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -39,8 +39,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -64,26 +64,26 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 h1:nOlJEAJyrcy8hexK65M+dsCHIx7CVVbybcFDNkcTcAc= go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0/go.mod h1:u79lGGIlkg3Ryw425RbMjEkGYNxSnXRyR286O840+u4= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/exporters/prometheus v0.50.0 h1:2Ewsda6hejmbhGFyUvWZjUThC98Cf8Zy6g0zkIimOng= go.opentelemetry.io/otel/exporters/prometheus v0.50.0/go.mod h1:pMm5PkUo5YwbLiuEf7t2xg4wbP0/eSJrMxIMxKosynY= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/nosql/redis/go.mod b/contrib/nosql/redis/go.mod index e25d98cd7..23f738421 100644 --- a/contrib/nosql/redis/go.mod +++ b/contrib/nosql/redis/go.mod @@ -1,35 +1,37 @@ module github.com/gogf/gf/contrib/nosql/redis/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 github.com/redis/go-redis/v9 v9.2.1 - go.opentelemetry.io/otel v1.14.0 - go.opentelemetry.io/otel/trace v1.14.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/nosql/redis/go.sum b/contrib/nosql/redis/go.sum index c33db4f5c..e954f1914 100644 --- a/contrib/nosql/redis/go.sum +++ b/contrib/nosql/redis/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -11,18 +11,18 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 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/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -32,28 +32,34 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -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-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/nosql/redis/redis_group_script.go b/contrib/nosql/redis/redis_group_script.go index a074748df..3f1a6ef77 100644 --- a/contrib/nosql/redis/redis_group_script.go +++ b/contrib/nosql/redis/redis_group_script.go @@ -76,6 +76,9 @@ func (r GroupScript) ScriptExists(ctx context.Context, sha1 string, sha1s ...str s = append(s, "Exists") s = append(s, sha1Array...) result, err := r.Operation.Do(ctx, "Script", s...) + if err != nil { + return nil, err + } var ( m = make(map[string]bool) resultArray = result.Vars() diff --git a/contrib/registry/etcd/etcd.go b/contrib/registry/etcd/etcd.go index 503478d12..fac43a9e4 100644 --- a/contrib/registry/etcd/etcd.go +++ b/contrib/registry/etcd/etcd.go @@ -12,6 +12,7 @@ import ( "time" etcd3 "go.etcd.io/etcd/client/v3" + "google.golang.org/grpc" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" @@ -38,11 +39,26 @@ type Registry struct { type Option struct { Logger glog.ILogger KeepaliveTTL time.Duration + + // DialTimeout is the timeout for failing to establish a connection. + DialTimeout time.Duration + + // AutoSyncInterval is the interval to update endpoints with its latest members. + AutoSyncInterval time.Duration + + DialOptions []grpc.DialOption } const ( // DefaultKeepAliveTTL is the default keepalive TTL. DefaultKeepAliveTTL = 10 * time.Second + + // DefaultDialTimeout is the timeout for failing to establish a connection. + DefaultDialTimeout = time.Second * 5 + + // DefaultAutoSyncInterval is the interval to update endpoints with its latest members. + // 0 disables auto-sync. By default auto-sync is disabled. + DefaultAutoSyncInterval = time.Second ) // New creates and returns a new etcd registry. @@ -80,6 +96,21 @@ func New(address string, option ...Option) gsvc.Registry { if password != "" { cfg.Password = password } + + cfg.DialTimeout = DefaultDialTimeout + cfg.AutoSyncInterval = DefaultAutoSyncInterval + + var usedOption Option + if len(option) > 0 { + usedOption = option[0] + } + if usedOption.DialTimeout > 0 { + cfg.DialTimeout = usedOption.DialTimeout + } + if usedOption.AutoSyncInterval > 0 { + cfg.AutoSyncInterval = usedOption.AutoSyncInterval + } + client, err := etcd3.New(cfg) if err != nil { panic(gerror.Wrap(err, `create etcd client failed`)) diff --git a/contrib/registry/etcd/go.mod b/contrib/registry/etcd/go.mod index 40701da71..487f54564 100644 --- a/contrib/registry/etcd/go.mod +++ b/contrib/registry/etcd/go.mod @@ -1,48 +1,49 @@ module github.com/gogf/gf/contrib/registry/etcd/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/v2 v2.8.1 go.etcd.io/etcd/client/v3 v3.5.7 + google.golang.org/grpc v1.59.0 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect go.etcd.io/etcd/api/v3 v3.5.7 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/registry/etcd/go.sum b/contrib/registry/etcd/go.sum index 84da7e36b..379f4f2b5 100644 --- a/contrib/registry/etcd/go.sum +++ b/contrib/registry/etcd/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= @@ -11,13 +11,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -27,9 +27,9 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -51,12 +51,12 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE 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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= @@ -65,12 +65,14 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mE go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= @@ -86,8 +88,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -96,12 +98,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -120,8 +122,8 @@ google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/contrib/registry/file/file_discovery.go b/contrib/registry/file/file_discovery.go index 36065cc11..b5c03d977 100644 --- a/contrib/registry/file/file_discovery.go +++ b/contrib/registry/file/file_discovery.go @@ -10,6 +10,7 @@ import ( "context" "github.com/gogf/gf/v2/container/gmap" + "github.com/gogf/gf/v2/container/gtype" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/os/gfile" @@ -55,8 +56,12 @@ func (r *Registry) Watch(ctx context.Context, key string) (watcher gsvc.Watcher, prefix: key, discovery: r, ch: make(chan gsvc.Service, 100), + closed: gtype.NewBool(false), } _, err = gfsnotify.Add(r.path, func(event *gfsnotify.Event) { + if fileWatcher.closed.Val() { + return + } if event.IsChmod() { return } @@ -94,7 +99,7 @@ func (r *Registry) getServices(ctx context.Context) (services []gsvc.Service, er `service "%s" is expired, update at: %s, current: %s, sub duration: %s`, s.GetKey(), updateAt.String(), nowTime.String(), subDuration.String(), ) - _ = gfile.Remove(filePath) + _ = gfile.RemoveFile(filePath) continue } services = append(services, s) diff --git a/contrib/registry/file/file_registrar.go b/contrib/registry/file/file_registrar.go index d98098779..d7bdfb8ee 100644 --- a/contrib/registry/file/file_registrar.go +++ b/contrib/registry/file/file_registrar.go @@ -44,7 +44,7 @@ func (r *Registry) Register(ctx context.Context, service gsvc.Service) (register // Deregister off-lines and removes `service` from the Registry. func (r *Registry) Deregister(ctx context.Context, service gsvc.Service) error { - return gfile.Remove(r.getServiceFilePath(service)) + return gfile.RemoveFile(r.getServiceFilePath(service)) } func (r *Registry) getServiceFilePath(service gsvc.Service) string { diff --git a/contrib/registry/file/file_watcher.go b/contrib/registry/file/file_watcher.go index fa060ef0a..b10e74304 100644 --- a/contrib/registry/file/file_watcher.go +++ b/contrib/registry/file/file_watcher.go @@ -9,6 +9,8 @@ package file import ( "context" + "github.com/gogf/gf/v2/container/gtype" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/net/gsvc" ) @@ -17,11 +19,15 @@ type Watcher struct { prefix string // Watched prefix key, not file name prefix. discovery gsvc.Discovery // Service discovery. ch chan gsvc.Service // Changes that caused by inotify. + closed *gtype.Bool // Whether the channel has been closed } // Proceed proceeds watch in blocking way. // It returns all complete services that watched by `key` if any change. func (w *Watcher) Proceed() (services []gsvc.Service, err error) { + if w.closed.Val() { + return nil, gerror.New("discovery service was closed") + } <-w.ch return w.discovery.Search(context.Background(), gsvc.SearchInput{ Prefix: w.prefix, @@ -30,6 +36,8 @@ func (w *Watcher) Proceed() (services []gsvc.Service, err error) { // Close closes the watcher. func (w *Watcher) Close() error { - close(w.ch) + if w.closed.Cas(false, true) { + close(w.ch) + } return nil } diff --git a/contrib/registry/file/go.mod b/contrib/registry/file/go.mod index 37178c10c..8e1bb98d4 100644 --- a/contrib/registry/file/go.mod +++ b/contrib/registry/file/go.mod @@ -1,31 +1,32 @@ module github.com/gogf/gf/contrib/registry/file/v2 -go 1.18 +go 1.20 -require github.com/gogf/gf/v2 v2.7.2 +require github.com/gogf/gf/v2 v2.8.1 require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/registry/file/go.sum b/contrib/registry/file/go.sum index 726644ce5..ae66c9eaa 100644 --- a/contrib/registry/file/go.sum +++ b/contrib/registry/file/go.sum @@ -1,22 +1,22 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -33,23 +33,25 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/registry/nacos/go.mod b/contrib/registry/nacos/go.mod index aac9b7e19..f243e5954 100644 --- a/contrib/registry/nacos/go.mod +++ b/contrib/registry/nacos/go.mod @@ -1,14 +1,14 @@ module github.com/gogf/gf/contrib/registry/nacos/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 - github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288 + github.com/gogf/gf/v2 v2.8.1 + github.com/nacos-group/nacos-sdk-go/v2 v2.2.7 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect github.com/alibabacloud-go/tea v1.1.17 // indirect github.com/alibabacloud-go/tea-utils v1.4.4 // indirect @@ -20,13 +20,13 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -43,22 +43,23 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.1.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect - google.golang.org/grpc v1.57.2 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.56.3 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/contrib/registry/nacos/go.sum b/contrib/registry/nacos/go.sum index bd7ff2c08..43d0d9771 100644 --- a/contrib/registry/nacos/go.sum +++ b/contrib/registry/nacos/go.sum @@ -32,8 +32,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -82,8 +82,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -96,8 +96,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -145,7 +145,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -159,8 +159,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -168,8 +168,6 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288 h1:GuL6co0J2oMb2Rd/hbxZfJz1QlZr+DpIsz3Wcvok65o= -github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288/go.mod h1:xF3RcNkFUEIik3RCihkvgORtZXZXlp+OeGK0aUALVYU= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -211,6 +209,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nacos-group/nacos-sdk-go/v2 v2.2.7 h1:wCC1f3/VzIR1WD30YKeJGZAOchYCK/35mLC8qWt6Q6o= +github.com/nacos-group/nacos-sdk-go/v2 v2.2.7/go.mod h1:VYlyDPlQchPC31PmfBustu81vsOkdpCuO5k0dRdQcFc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -242,8 +242,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -255,7 +255,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -265,12 +265,14 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= @@ -286,8 +288,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -349,8 +351,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -367,8 +369,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -409,8 +411,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -418,8 +420,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -522,8 +524,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -536,8 +538,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.57.2 h1:uw37EN34aMFFXB2QPW7Tq6tdTbind1GpRxw5aOX3a5k= -google.golang.org/grpc v1.57.2/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -550,8 +552,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/registry/nacos/nacos.go b/contrib/registry/nacos/nacos.go index 78024b216..600ebe635 100644 --- a/contrib/registry/nacos/nacos.go +++ b/contrib/registry/nacos/nacos.go @@ -17,10 +17,10 @@ import ( "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" - "github.com/joy999/nacos-sdk-go/clients" - "github.com/joy999/nacos-sdk-go/clients/naming_client" - "github.com/joy999/nacos-sdk-go/common/constant" - "github.com/joy999/nacos-sdk-go/vo" + "github.com/nacos-group/nacos-sdk-go/v2/clients" + "github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client" + "github.com/nacos-group/nacos-sdk-go/v2/common/constant" + "github.com/nacos-group/nacos-sdk-go/v2/vo" ) const ( diff --git a/contrib/registry/nacos/nacos_discovery.go b/contrib/registry/nacos/nacos_discovery.go index b67973c0c..6e38585db 100644 --- a/contrib/registry/nacos/nacos_discovery.go +++ b/contrib/registry/nacos/nacos_discovery.go @@ -13,8 +13,8 @@ import ( "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/text/gstr" - "github.com/joy999/nacos-sdk-go/model" - "github.com/joy999/nacos-sdk-go/vo" + "github.com/nacos-group/nacos-sdk-go/v2/model" + "github.com/nacos-group/nacos-sdk-go/v2/vo" ) // Search searches and returns services with specified condition. diff --git a/contrib/registry/nacos/nacos_register.go b/contrib/registry/nacos/nacos_register.go index 70dff428a..afc950c60 100644 --- a/contrib/registry/nacos/nacos_register.go +++ b/contrib/registry/nacos/nacos_register.go @@ -11,7 +11,7 @@ import ( "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/util/gconv" - "github.com/joy999/nacos-sdk-go/vo" + "github.com/nacos-group/nacos-sdk-go/v2/vo" ) // Register registers `service` to Registry. diff --git a/contrib/registry/nacos/nacos_service.go b/contrib/registry/nacos/nacos_service.go index 1bd7733d3..8ac5f5ce1 100644 --- a/contrib/registry/nacos/nacos_service.go +++ b/contrib/registry/nacos/nacos_service.go @@ -12,7 +12,7 @@ import ( "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/text/gstr" - "github.com/joy999/nacos-sdk-go/model" + "github.com/nacos-group/nacos-sdk-go/v2/model" ) // NewServiceFromInstance new one service from instance diff --git a/contrib/registry/nacos/nacos_watcher.go b/contrib/registry/nacos/nacos_watcher.go index fe9fc85b3..c9454d164 100644 --- a/contrib/registry/nacos/nacos_watcher.go +++ b/contrib/registry/nacos/nacos_watcher.go @@ -12,7 +12,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/net/gsvc" - "github.com/joy999/nacos-sdk-go/model" + "github.com/nacos-group/nacos-sdk-go/v2/model" ) // Watcher used to mange service event such as update. diff --git a/contrib/registry/nacos/nacos_z_test.go b/contrib/registry/nacos/nacos_z_test.go index 959078c32..0470c4abb 100644 --- a/contrib/registry/nacos/nacos_z_test.go +++ b/contrib/registry/nacos/nacos_z_test.go @@ -18,7 +18,7 @@ import ( "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/guid" - "github.com/joy999/nacos-sdk-go/common/constant" + "github.com/nacos-group/nacos-sdk-go/v2/common/constant" ) const ( diff --git a/contrib/registry/polaris/README_ZH.MD b/contrib/registry/polaris/README_ZH.MD index 0006cfb31..e47248b0c 100644 --- a/contrib/registry/polaris/README_ZH.MD +++ b/contrib/registry/polaris/README_ZH.MD @@ -19,7 +19,7 @@ require github.com/gogf/gf/contrib/registry/polaris/v2 latest ## Golang版本限制 ``` -golang version >= 1.15 +golang version >= 1.20 ``` ## 示例 diff --git a/contrib/registry/polaris/go.mod b/contrib/registry/polaris/go.mod index 91a79c044..b941c4387 100644 --- a/contrib/registry/polaris/go.mod +++ b/contrib/registry/polaris/go.mod @@ -1,58 +1,59 @@ module github.com/gogf/gf/contrib/registry/polaris/v2 -go 1.18 +go 1.21 require ( - github.com/gogf/gf/v2 v2.7.2 - github.com/polarismesh/polaris-go v1.5.5 + github.com/gogf/gf/v2 v2.8.1 + github.com/polarismesh/polaris-go v1.5.8 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dlclark/regexp2 v1.11.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/polarismesh/specification v1.4.1 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/polarismesh/specification v1.5.1 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.56.3 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/registry/polaris/go.sum b/contrib/registry/polaris/go.sum index f520733dd..26b7619c8 100644 --- a/contrib/registry/polaris/go.sum +++ b/contrib/registry/polaris/go.sum @@ -168,8 +168,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw= @@ -190,8 +190,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/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= @@ -210,8 +210,9 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.2 h1:/u628IuisSTwri5/UKloiIsH8+qF2Pu7xEQX+yIKg68= +github.com/dlclark/regexp2 v1.11.2/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -224,8 +225,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -239,8 +240,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -275,8 +276,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= @@ -301,7 +302,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -324,8 +326,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -339,13 +341,14 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -368,8 +371,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -383,7 +387,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -393,6 +396,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= @@ -405,37 +410,44 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polarismesh/polaris-go v1.5.5 h1:TUxgla21J9Zb3zSynoAA9og0+sYJZ7TpZ2aFwzH7woI= -github.com/polarismesh/polaris-go v1.5.5/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c= -github.com/polarismesh/specification v1.4.1 h1:lTZqeyUhhWuKyr6NDKBwmUrNfcUDvKLxWT/uOq71T5A= +github.com/polarismesh/polaris-go v1.5.8 h1:zBZkZBa4wVxsG5Y/6U4PmY9dY/mddXdfNI65edVu6U8= +github.com/polarismesh/polaris-go v1.5.8/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c= github.com/polarismesh/specification v1.4.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU= +github.com/polarismesh/specification v1.5.1 h1:cJ2m0RBepdopGo/e3UpKdsab3NpDZnw5IsVTB1sFc5I= +github.com/polarismesh/specification v1.5.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -458,8 +470,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -473,12 +486,14 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -580,8 +595,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -692,8 +707,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -707,8 +722,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -923,8 +938,8 @@ google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -960,8 +975,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -978,8 +993,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/contrib/registry/zookeeper/go.mod b/contrib/registry/zookeeper/go.mod index 68050d25d..3afa94bb4 100644 --- a/contrib/registry/zookeeper/go.mod +++ b/contrib/registry/zookeeper/go.mod @@ -1,35 +1,36 @@ module github.com/gogf/gf/contrib/registry/zookeeper/v2 -go 1.18 +go 1.20 require ( github.com/go-zookeeper/zk v1.0.3 - github.com/gogf/gf/v2 v2.7.2 - golang.org/x/sync v0.4.0 + github.com/gogf/gf/v2 v2.8.1 + golang.org/x/sync v0.7.0 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/registry/zookeeper/go.sum b/contrib/registry/zookeeper/go.sum index ca644cedb..4768eeba0 100644 --- a/contrib/registry/zookeeper/go.sum +++ b/contrib/registry/zookeeper/go.sum @@ -1,24 +1,24 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -35,25 +35,27 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/registry/zookeeper/zookeeper_registrar.go b/contrib/registry/zookeeper/zookeeper_registrar.go index 5b8a01817..26273a5b2 100644 --- a/contrib/registry/zookeeper/zookeeper_registrar.go +++ b/contrib/registry/zookeeper/zookeeper_registrar.go @@ -65,7 +65,7 @@ func (r *Registry) Register(_ context.Context, service gsvc.Service) (gsvc.Servi // Deregister off-lines and removes `service` from the Registry. func (r *Registry) Deregister(ctx context.Context, service gsvc.Service) error { ch := make(chan error, 1) - prefix := strings.TrimPrefix(strings.ReplaceAll(service.GetPrefix(), "/", "-"), "-") + prefix := strings.Trim(strings.ReplaceAll(service.GetPrefix(), "/", "-"), "-") servicePath := path.Join(r.opts.namespace, prefix, service.GetName()) go func() { err := r.conn.Delete(servicePath, -1) diff --git a/contrib/registry/zookeeper/zookeeper_watcher.go b/contrib/registry/zookeeper/zookeeper_watcher.go index def4fa818..1ee710a17 100644 --- a/contrib/registry/zookeeper/zookeeper_watcher.go +++ b/contrib/registry/zookeeper/zookeeper_watcher.go @@ -66,7 +66,7 @@ func (w *watcher) Proceed() ([]gsvc.Service, error) { } func (w *watcher) getServicesByPrefix() ([]gsvc.Service, error) { - prefix := strings.TrimPrefix(strings.ReplaceAll(w.prefix, "/", "-"), "-") + prefix := strings.Trim(strings.ReplaceAll(w.prefix, "/", "-"), "-") serviceNamePath := path.Join(w.nameSpace, prefix) instances, err, _ := w.group.Do(serviceNamePath, func() (interface{}, error) { servicesID, _, err := w.conn.Children(serviceNamePath) @@ -122,7 +122,7 @@ func (w *watcher) Close() error { } func (w *watcher) watch(ctx context.Context) { - prefix := strings.TrimPrefix(strings.ReplaceAll(w.prefix, "/", "-"), "-") + prefix := strings.Trim(strings.ReplaceAll(w.prefix, "/", "-"), "-") serviceNamePath := path.Join(w.nameSpace, prefix) for { diff --git a/contrib/rpc/grpcx/go.mod b/contrib/rpc/grpcx/go.mod index 5f7ddcbae..7040f915e 100644 --- a/contrib/rpc/grpcx/go.mod +++ b/contrib/rpc/grpcx/go.mod @@ -1,38 +1,38 @@ module github.com/gogf/gf/contrib/rpc/grpcx/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/contrib/registry/file/v2 v2.7.2 - github.com/gogf/gf/v2 v2.7.2 - go.opentelemetry.io/otel v1.14.0 - go.opentelemetry.io/otel/trace v1.14.0 - google.golang.org/grpc v1.57.2 - google.golang.org/protobuf v1.31.0 + github.com/gogf/gf/contrib/registry/file/v2 v2.8.1 + github.com/gogf/gf/v2 v2.8.1 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 + google.golang.org/grpc v1.64.1 + google.golang.org/protobuf v1.34.2 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/rpc/grpcx/go.sum b/contrib/rpc/grpcx/go.sum index 91076b49f..7afa6ebd7 100644 --- a/contrib/rpc/grpcx/go.sum +++ b/contrib/rpc/grpcx/go.sum @@ -1,26 +1,22 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -37,32 +33,31 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.57.2 h1:uw37EN34aMFFXB2QPW7Tq6tdTbind1GpRxw5aOX3a5k= -google.golang.org/grpc v1.57.2/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/rpc/grpcx/grpcx_grpc_client.go b/contrib/rpc/grpcx/grpcx_grpc_client.go index 51b77ffc8..47aa27c7b 100644 --- a/contrib/rpc/grpcx/grpcx_grpc_client.go +++ b/contrib/rpc/grpcx/grpcx_grpc_client.go @@ -8,6 +8,7 @@ package grpcx import ( "fmt" + "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -31,11 +32,11 @@ func (c modClient) NewGrpcClientConn(serviceNameOrAddress string, opts ...grpc.D autoLoadAndRegisterFileRegistry() var ( - dialAddress = serviceNameOrAddress + target = serviceNameOrAddress grpcClientOptions = make([]grpc.DialOption, 0) ) if isServiceName(serviceNameOrAddress) { - dialAddress = fmt.Sprintf( + target = fmt.Sprintf( `%s://%s`, gsvc.Schema, gsvc.NewServiceWithName(serviceNameOrAddress).GetKey(), ) @@ -69,7 +70,7 @@ func (c modClient) NewGrpcClientConn(serviceNameOrAddress string, opts ...grpc.D grpcClientOptions = append(grpcClientOptions, c.ChainStream( c.StreamTracing, )) - conn, err := grpc.Dial(dialAddress, grpcClientOptions...) + conn, err := grpc.NewClient(target, grpcClientOptions...) if err != nil { return nil, err } diff --git a/contrib/rpc/grpcx/grpcx_grpc_server.go b/contrib/rpc/grpcx/grpcx_grpc_server.go index 7d14d30d9..c022e6ea9 100644 --- a/contrib/rpc/grpcx/grpcx_grpc_server.go +++ b/contrib/rpc/grpcx/grpcx_grpc_server.go @@ -285,23 +285,23 @@ func (s *GrpcServer) calculateListenedEndpoints(ctx context.Context) gsvc.Endpoi s.Logger().Errorf(ctx, `error retrieving intranet ip: %+v`, err) return nil } - // If no intranet ips found, it uses all ips that can be retrieved, - // it may include internet ip. - if len(intranetIps) == 0 { - allIps, err := gipv4.GetIpArray() - if err != nil { - s.Logger().Errorf(ctx, `error retrieving ip from current node: %+v`, err) - return nil - } - s.Logger().Noticef( - ctx, - `no intranet ip found, using internet ip to register service: %v`, - allIps, - ) - listenedIps = allIps + if len(intranetIps) != 0 { + listenedIps = intranetIps break } - listenedIps = intranetIps + // If no intranet ips found, it uses all ips that can be retrieved, + // it may include internet ip. + allIps, err := gipv4.GetIpArray() + if err != nil { + s.Logger().Errorf(ctx, `error retrieving ip from current node: %+v`, err) + return nil + } + s.Logger().Noticef( + ctx, + `no intranet ip found, using internet ip to register service: %v`, + allIps, + ) + listenedIps = allIps default: listenedIps = []string{addrArray[0]} } diff --git a/contrib/rpc/grpcx/internal/tracing/tracing.go b/contrib/rpc/grpcx/internal/tracing/tracing.go index d8e22ea65..6b21f4c93 100644 --- a/contrib/rpc/grpcx/internal/tracing/tracing.go +++ b/contrib/rpc/grpcx/internal/tracing/tracing.go @@ -29,12 +29,10 @@ const ( tracingInstrumentGrpcClient = "github.com/gogf/gf/contrib/rpc/grpcx/v2/krpc.GrpcClient" tracingInstrumentGrpcServer = "github.com/gogf/gf/contrib/rpc/grpcx/v2/krpc.GrpcServer" tracingEventGrpcRequest = "grpc.request" - tracingEventGrpcRequestMessage = "grpc.request.message" tracingEventGrpcRequestBaggage = "grpc.request.baggage" tracingEventGrpcMetadataOutgoing = "grpc.metadata.outgoing" tracingEventGrpcMetadataIncoming = "grpc.metadata.incoming" tracingEventGrpcResponse = "grpc.response" - tracingEventGrpcResponseMessage = "grpc.response.message" ) type metadataSupplier struct { diff --git a/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_client.go b/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_client.go index 2ccf475d8..a244eeb0d 100644 --- a/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_client.go +++ b/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_client.go @@ -19,7 +19,6 @@ import ( "google.golang.org/grpc/status" "github.com/gogf/gf/contrib/rpc/grpcx/v2/internal/grpcctx" - "github.com/gogf/gf/contrib/rpc/grpcx/v2/internal/utils" "github.com/gogf/gf/v2" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/util/gconv" @@ -59,25 +58,10 @@ func UnaryClientInterceptor(ctx context.Context, method string, req, reply inter span.AddEvent(tracingEventGrpcRequest, trace.WithAttributes( attribute.String(tracingEventGrpcRequestBaggage, gconv.String(gtrace.GetBaggageMap(ctx))), attribute.String(tracingEventGrpcMetadataOutgoing, gconv.String(grpcctx.Ctx{}.OutgoingMap(ctx))), - attribute.String( - tracingEventGrpcRequestMessage, - utils.MarshalMessageToJsonStringForTracing( - req, "Request", tracingMaxContentLogSize, - ), - ), )) err := invoker(ctx, method, req, reply, cc, callOpts...) - span.AddEvent(tracingEventGrpcResponse, trace.WithAttributes( - attribute.String( - tracingEventGrpcResponseMessage, - utils.MarshalMessageToJsonStringForTracing( - reply, "Response", tracingMaxContentLogSize, - ), - ), - )) - if err != nil { s, _ := status.FromError(err) span.SetStatus(codes.Error, s.Message()) diff --git a/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_server.go b/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_server.go index b94d4563e..fe77c6020 100644 --- a/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_server.go +++ b/contrib/rpc/grpcx/internal/tracing/tracing_interceptor_server.go @@ -20,7 +20,6 @@ import ( "google.golang.org/grpc/status" "github.com/gogf/gf/contrib/rpc/grpcx/v2/internal/grpcctx" - "github.com/gogf/gf/contrib/rpc/grpcx/v2/internal/utils" "github.com/gogf/gf/v2" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/util/gconv" @@ -58,25 +57,10 @@ func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.Una span.AddEvent(tracingEventGrpcRequest, trace.WithAttributes( attribute.String(tracingEventGrpcRequestBaggage, gconv.String(gtrace.GetBaggageMap(ctx))), attribute.String(tracingEventGrpcMetadataIncoming, gconv.String(grpcctx.Ctx{}.IncomingMap(ctx))), - attribute.String( - tracingEventGrpcRequestMessage, - utils.MarshalMessageToJsonStringForTracing( - req, "Request", tracingMaxContentLogSize, - ), - ), )) res, err := handler(ctx, req) - span.AddEvent(tracingEventGrpcResponse, trace.WithAttributes( - attribute.String( - tracingEventGrpcResponseMessage, - utils.MarshalMessageToJsonStringForTracing( - res, "Response", tracingMaxContentLogSize, - ), - ), - )) - if err != nil { s, _ := status.FromError(err) span.SetStatus(codes.Error, s.Message()) diff --git a/contrib/sdk/httpclient/go.mod b/contrib/sdk/httpclient/go.mod index f10bbb8ca..ed6e4fa3b 100644 --- a/contrib/sdk/httpclient/go.mod +++ b/contrib/sdk/httpclient/go.mod @@ -1,31 +1,32 @@ module github.com/gogf/gf/contrib/sdk/httpclient/v2 -go 1.18 +go 1.20 -require github.com/gogf/gf/v2 v2.7.2 +require github.com/gogf/gf/v2 v2.8.1 require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/sdk/httpclient/go.sum b/contrib/sdk/httpclient/go.sum index 726644ce5..ae66c9eaa 100644 --- a/contrib/sdk/httpclient/go.sum +++ b/contrib/sdk/httpclient/go.sum @@ -1,22 +1,22 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -33,23 +33,25 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/trace/jaeger/go.mod b/contrib/trace/jaeger/go.mod deleted file mode 100644 index 22c2e6f4b..000000000 --- a/contrib/trace/jaeger/go.mod +++ /dev/null @@ -1,19 +0,0 @@ -module github.com/gogf/gf/contrib/trace/jaeger/v2 - -go 1.18 - -require ( - github.com/gogf/gf/v2 v2.7.2 - go.opentelemetry.io/otel v1.14.0 - go.opentelemetry.io/otel/exporters/jaeger v1.14.0 - go.opentelemetry.io/otel/sdk v1.14.0 -) - -require ( - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/sys v0.19.0 // indirect -) - -replace github.com/gogf/gf/v2 => ../../../ diff --git a/contrib/trace/jaeger/go.sum b/contrib/trace/jaeger/go.sum deleted file mode 100644 index 6c3f9eb80..000000000 --- a/contrib/trace/jaeger/go.sum +++ /dev/null @@ -1,35 +0,0 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel/exporters/jaeger v1.14.0 h1:CjbUNd4iN2hHmWekmOqZ+zSCU+dzZppG8XsV+A3oc8Q= -go.opentelemetry.io/otel/exporters/jaeger v1.14.0/go.mod h1:4Ay9kk5vELRrbg5z4cpP9EtmQRFap2Wb0woPG4lujZA= -go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/trace/jaeger/jaeger.go b/contrib/trace/jaeger/jaeger.go deleted file mode 100644 index 3ddb82833..000000000 --- a/contrib/trace/jaeger/jaeger.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -// Package jaeger provides OpenTelemetry provider using jaeger. -// -// Deprecated: -// Please use `github.com/gogf/gf/contrib/trace/otlphttp/v2` instead. -// As dependent package `go.opentelemetry.io/otel/exporters/jaeger` is deprecated in otel, -// this package will be never be maintained from goframe v2.6.0. -package jaeger - -import ( - "strings" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/jaeger" - "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" - - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/net/gipv4" - "github.com/gogf/gf/v2/text/gregex" -) - -const ( - tracerHostnameTagKey = "hostname" -) - -// Init initializes and registers jaeger to global TracerProvider. -// -// The output parameter `flush` is used for waiting exported trace spans to be uploaded, -// which is useful if your program is ending, and you do not want to lose recent spans. -func Init(serviceName, endpoint string) (*trace.TracerProvider, error) { - // Create the Jaeger exporter - var endpointOption jaeger.EndpointOption - if strings.HasPrefix(endpoint, "http") { - // HTTP. - endpointOption = jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(endpoint)) - } else { - // UDP. - match, err := gregex.MatchString(`(.+):(\d+)`, endpoint) - if err != nil { - return nil, err - } - if len(match) < 3 { - return nil, gerror.NewCodef( - gcode.CodeInvalidParameter, `invalid endpoint "%s"`, endpoint, - ) - } - var ( - host = match[1] - port = match[2] - ) - endpointOption = jaeger.WithAgentEndpoint( - jaeger.WithAgentHost(host), jaeger.WithAgentPort(port), - ) - } - // Try retrieving host ip for tracing info. - var ( - hostIp = "NoHostIpFound" - intranetIPArray, err = gipv4.GetIntranetIpArray() - ) - if err != nil { - return nil, err - } - if len(intranetIPArray) == 0 { - if intranetIPArray, err = gipv4.GetIpArray(); err != nil { - return nil, err - } - } - if len(intranetIPArray) > 0 { - hostIp = intranetIPArray[0] - } - - exp, err := jaeger.New(endpointOption) - if err != nil { - return nil, err - } - tp := trace.NewTracerProvider( - // Always be sure to batch in production. - trace.WithBatcher(exp), - // Record information about this application in a Resource. - trace.WithResource(resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceNameKey.String(serviceName), - semconv.HostNameKey.String(hostIp), - attribute.String(tracerHostnameTagKey, hostIp), - )), - ) - // Register our TracerProvider as the global, so any imported - // instrumentation in the future will default to using it. - otel.SetTracerProvider(tp) - return tp, nil -} diff --git a/contrib/trace/otlpgrpc/go.mod b/contrib/trace/otlpgrpc/go.mod index 549cad184..565db9acd 100644 --- a/contrib/trace/otlpgrpc/go.mod +++ b/contrib/trace/otlpgrpc/go.mod @@ -1,27 +1,26 @@ module github.com/gogf/gf/contrib/trace/otlpgrpc/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 - google.golang.org/grpc v1.60.1 + github.com/gogf/gf/v2 v2.8.1 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + google.golang.org/grpc v1.64.1 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -29,16 +28,16 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/protobuf v1.32.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/trace/otlpgrpc/go.sum b/contrib/trace/otlpgrpc/go.sum index a3c7ee86b..a8b1a5e15 100644 --- a/contrib/trace/otlpgrpc/go.sum +++ b/contrib/trace/otlpgrpc/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= @@ -7,22 +7,18 @@ github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= @@ -43,45 +39,41 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/trace/otlpgrpc/otlpgrpc.go b/contrib/trace/otlpgrpc/otlpgrpc.go index 872d156a6..79de7012a 100644 --- a/contrib/trace/otlpgrpc/otlpgrpc.go +++ b/contrib/trace/otlpgrpc/otlpgrpc.go @@ -17,9 +17,9 @@ import ( "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" - "google.golang.org/grpc" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + "google.golang.org/grpc/encoding/gzip" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gipv4" @@ -33,7 +33,7 @@ const ( // // The output parameter `Shutdown` is used for waiting exported trace spans to be uploaded, // which is useful if your program is ending, and you do not want to lose recent spans. -func Init(serviceName, endpoint, traceToken string) (func(), error) { +func Init(serviceName, endpoint, traceToken string) (func(ctx context.Context), error) { // Try retrieving host ip for tracing info. var ( intranetIPArray, err = gipv4.GetIntranetIpArray() @@ -53,13 +53,12 @@ func Init(serviceName, endpoint, traceToken string) (func(), error) { hostIP = intranetIPArray[0] } - traceClient := otlptracegrpc.NewClient( + ctx := context.Background() + traceExp, err := otlptrace.New(ctx, otlptracegrpc.NewClient( otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint(endpoint), // Replace the otel Agent Addr with the access point obtained in the prerequisite。 otlptracegrpc.WithHeaders(map[string]string{"Authentication": traceToken}), - otlptracegrpc.WithDialOption(grpc.WithBlock())) - ctx := context.Background() - traceExp, err := otlptrace.New(ctx, traceClient) + otlptracegrpc.WithCompressor(gzip.Name))) if err != nil { return nil, err } @@ -79,18 +78,26 @@ func Init(serviceName, endpoint, traceToken string) (func(), error) { return nil, err } - bsp := sdktrace.NewBatchSpanProcessor(traceExp) - tracerProvider := sdktrace.NewTracerProvider( - sdktrace.WithSampler(sdktrace.AlwaysSample()), - sdktrace.WithResource(res), - sdktrace.WithSpanProcessor(bsp), + tracerProvider := trace.NewTracerProvider( + // AlwaysSample is a sampler that samples every trace. + // see: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/trace#AlwaysSample + // example see: [example/trace/provider/grpc/main.go](../../../../../example/trace/provider/grpc/main.go#L87) + trace.WithSampler(trace.AlwaysSample()), + // WithResource returns a trace option that sets the resource to be associated with spans. + // see: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/trace#WithResource + // example see: [example/trace/provider/grpc/main.go](../../../../../example/trace/provider/grpc/main.go#L36) + trace.WithResource(res), + // WithSpanProcessor returns a trace option that sets the span processor to be used by the trace provider. + // see: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/trace#WithSpanProcessor + // example see: [example/trace/provider/grpc/main.go](../../../../../example/trace/provider/grpc/main.go#L99) + trace.WithSpanProcessor(trace.NewBatchSpanProcessor(traceExp)), ) // Set the global propagator to traceContext (not set by default). - otel.SetTextMapPropagator(propagation.TraceContext{}) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) otel.SetTracerProvider(tracerProvider) - return func() { + return func(ctx context.Context) { ctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() if err = tracerProvider.Shutdown(ctx); err != nil { diff --git a/contrib/trace/otlphttp/go.mod b/contrib/trace/otlphttp/go.mod index 794f02092..6b817b4b6 100644 --- a/contrib/trace/otlphttp/go.mod +++ b/contrib/trace/otlphttp/go.mod @@ -1,26 +1,26 @@ module github.com/gogf/gf/contrib/trace/otlphttp/v2 -go 1.18 +go 1.20 require ( - github.com/gogf/gf/v2 v2.7.2 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 + github.com/gogf/gf/v2 v2.8.1 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -28,17 +28,17 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/grpc v1.60.1 // indirect - google.golang.org/protobuf v1.32.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contrib/trace/otlphttp/go.sum b/contrib/trace/otlphttp/go.sum index 2161434e5..a70b53bcf 100644 --- a/contrib/trace/otlphttp/go.sum +++ b/contrib/trace/otlphttp/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= @@ -7,13 +7,13 @@ github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -21,8 +21,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= @@ -43,44 +43,44 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/contrib/trace/otlphttp/otlphttp.go b/contrib/trace/otlphttp/otlphttp.go index 91ac74fd3..2a09b664d 100644 --- a/contrib/trace/otlphttp/otlphttp.go +++ b/contrib/trace/otlphttp/otlphttp.go @@ -17,8 +17,8 @@ import ( "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gipv4" @@ -32,7 +32,7 @@ const ( // // The output parameter `Shutdown` is used for waiting exported trace spans to be uploaded, // which is useful if your program is ending, and you do not want to lose recent spans. -func Init(serviceName, endpoint, path string) (func(), error) { +func Init(serviceName, endpoint, path string) (func(ctx context.Context), error) { // Try retrieving host ip for tracing info. var ( intranetIPArray, err = gipv4.GetIntranetIpArray() @@ -52,15 +52,13 @@ func Init(serviceName, endpoint, path string) (func(), error) { hostIP = intranetIPArray[0] } - traceClientHTTP := otlptracehttp.NewClient( + ctx := context.Background() + traceExp, err := otlptrace.New(ctx, otlptracehttp.NewClient( otlptracehttp.WithEndpoint(endpoint), otlptracehttp.WithURLPath(path), otlptracehttp.WithInsecure(), otlptracehttp.WithCompression(1), - ) - - ctx := context.Background() - traceExp, err := otlptrace.New(ctx, traceClientHTTP) + )) if err != nil { return nil, err } @@ -77,18 +75,26 @@ func Init(serviceName, endpoint, path string) (func(), error) { ), ) - bsp := sdktrace.NewBatchSpanProcessor(traceExp) - tracerProvider := sdktrace.NewTracerProvider( - sdktrace.WithSampler(sdktrace.AlwaysSample()), - sdktrace.WithResource(res), - sdktrace.WithSpanProcessor(bsp), + tracerProvider := trace.NewTracerProvider( + // AlwaysSample is a sampler that samples every trace. + // see: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/trace#AlwaysSample + // example see: [example/trace/provider/http/main.go](../../../../../example/trace/provider/http/main.go#L84) + trace.WithSampler(trace.AlwaysSample()), + // WithResource returns a trace option that sets the resource to be associated with spans. + // see: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/trace#WithResource + // example see: [example/trace/provider/http/main.go](../../../../../example/trace/provider/http/main.go#L33) + trace.WithResource(res), + // WithSpanProcessor returns a trace option that sets the span processor to be used by the trace provider. + // see: https://pkg.go.dev/go.opentelemetry.io/otel/sdk/trace#WithSpanProcessor + // example see: [example/trace/provider/http/main.go](../../../../../example/trace/provider/http/main.go#L96) + trace.WithSpanProcessor(trace.NewBatchSpanProcessor(traceExp)), ) // Set the global propagator to traceContext (not set by default). - otel.SetTextMapPropagator(propagation.TraceContext{}) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) otel.SetTracerProvider(tracerProvider) - return func() { + return func(ctx context.Context) { ctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() if err = tracerProvider.Shutdown(ctx); err != nil { diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index 8bffa2636..74d76e5c8 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -178,6 +178,7 @@ type DB interface { ConvertValueForLocal(ctx context.Context, fieldType string, fieldValue interface{}) (interface{}, error) // See Core.ConvertValueForLocal CheckLocalTypeForField(ctx context.Context, fieldType string, fieldValue interface{}) (LocalType, error) // See Core.CheckLocalTypeForField FormatUpsert(columns []string, list List, option DoInsertOption) (string, error) // See Core.DoFormatUpsert + OrderRandomFunction() string // See Core.OrderRandomFunction } // TX defines the interfaces for ORM transaction operations. @@ -395,12 +396,13 @@ const ( linkPattern = `(\w+):([\w\-\$]*):(.*?)@(\w+?)\((.+?)\)/{0,1}([^\?]*)\?{0,1}(.*)` ) -type queryType int +type SelectType int const ( - queryTypeNormal queryType = iota - queryTypeCount - queryTypeValue + SelectTypeDefault SelectType = iota + SelectTypeCount + SelectTypeValue + SelectTypeArray ) type joinOperator string @@ -446,6 +448,7 @@ type LocalType string const ( LocalTypeUndefined LocalType = "" LocalTypeString LocalType = "string" + LocalTypeTime LocalType = "time" LocalTypeDate LocalType = "date" LocalTypeDatetime LocalType = "datetime" LocalTypeInt LocalType = "int" @@ -491,9 +494,11 @@ const ( fieldTypeSmallmoney = "smallmoney" fieldTypeBool = "bool" fieldTypeBit = "bit" - fieldTypeDate = "date" - fieldTypeDatetime = "datetime" - fieldTypeTimestamp = "timestamp" + fieldTypeYear = "year" // YYYY + fieldTypeDate = "date" // YYYY-MM-DD + fieldTypeTime = "time" // HH:MM:SS + fieldTypeDatetime = "datetime" // YYYY-MM-DD HH:MM:SS + fieldTypeTimestamp = "timestamp" // YYYYMMDD HHMMSS fieldTypeTimestampz = "timestamptz" fieldTypeJson = "json" fieldTypeJsonb = "jsonb" @@ -631,6 +636,8 @@ func Instance(name ...string) (db DB, err error) { // getConfigNodeByGroup calculates and returns a configuration node of given group. It // calculates the value internally using weight algorithm for load balance. // +// The returned node is a clone of configuration node, which is safe for later modification. +// // The parameter `master` specifies whether retrieving a master node, or else a slave node // if master-slave configured. func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) { @@ -670,6 +677,7 @@ func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) { } // getConfigNodeByWeight calculates the configuration weights and randomly returns a node. +// The returned node is a clone of configuration node, which is safe for later modification. // // Calculation algorithm brief: // 1. If we have 2 nodes, and their weights are both 1, then the weight range is [0, 199]; @@ -693,13 +701,13 @@ func getConfigNodeByWeight(cg ConfigGroup) *ConfigNode { } // Exclude the right border value. var ( - min = 0 - max = 0 - random = grand.N(0, total-1) + minWeight = 0 + maxWeight = 0 + random = grand.N(0, total-1) ) for i := 0; i < len(cg); i++ { - max = min + cg[i].Weight*100 - if random >= min && random < max { + maxWeight = minWeight + cg[i].Weight*100 + if random >= minWeight && random < maxWeight { // ==================================================== // Return a COPY of the ConfigNode. // ==================================================== @@ -707,7 +715,7 @@ func getConfigNodeByWeight(cg ConfigGroup) *ConfigNode { node = cg[i] return &node } - min = max + minWeight = maxWeight } return nil } @@ -725,6 +733,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error configs.RLock() defer configs.RUnlock() // Value COPY for node. + // The returned node is a clone of configuration node, which is safe for later modification. node, err = getConfigNodeByGroup(c.group, master) if err != nil { return nil, err @@ -773,7 +782,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error } return sqlDb } - // it here uses node value not pointer as the cache key, in case of oracle ORA-12516 error. + // it here uses NODE VALUE not pointer as the cache key, in case of oracle ORA-12516 error. instanceValue = c.links.GetOrSetFuncLock(*node, instanceCacheFunc) ) if instanceValue != nil && sqlDb == nil { diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index a3896c30b..ec14ffd1b 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -278,7 +278,7 @@ func (c *Core) doUnion(ctx context.Context, unionType int, unions ...*Model) *Mo unionTypeStr = "UNION" } for _, v := range unions { - sqlWithHolder, holderArgs := v.getFormattedSqlAndArgs(ctx, queryTypeNormal, false) + sqlWithHolder, holderArgs := v.getFormattedSqlAndArgs(ctx, SelectTypeDefault, false) if composedSqlStr == "" { composedSqlStr += fmt.Sprintf(`(%s)`, sqlWithHolder) } else { @@ -697,7 +697,7 @@ func (c *Core) FilteredLink() string { // // Note that this interface implements mainly for workaround for a json infinite loop bug // of Golang version < v1.14. -func (c Core) MarshalJSON() ([]byte, error) { +func (c *Core) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf(`%+v`, c)), nil } diff --git a/database/gdb/gdb_core_config.go b/database/gdb/gdb_core_config.go index d649f8998..fdec90f2e 100644 --- a/database/gdb/gdb_core_config.go +++ b/database/gdb/gdb_core_config.go @@ -276,12 +276,18 @@ func parseConfigNodeLink(node *ConfigNode) *ConfigNode { node.Pass = match[3] node.Protocol = match[4] array := gstr.Split(match[5], ":") - if len(array) == 2 && node.Protocol != "file" { - node.Host = array[0] - node.Port = array[1] - node.Name = match[6] - } else { + if node.Protocol == "file" { node.Name = match[5] + } else { + if len(array) == 2 { + // link with port. + node.Host = array[0] + node.Port = array[1] + } else { + // link without port. + node.Host = array[0] + } + node.Name = match[6] } if len(match) > 6 && match[7] != "" { node.Extra = match[7] diff --git a/database/gdb/gdb_core_structure.go b/database/gdb/gdb_core_structure.go index 852c7aa58..bbb9df757 100644 --- a/database/gdb/gdb_core_structure.go +++ b/database/gdb/gdb_core_structure.go @@ -28,7 +28,19 @@ import ( func (c *Core) GetFieldTypeStr(ctx context.Context, fieldName, table, schema string) string { field := c.GetFieldType(ctx, fieldName, table, schema) if field != nil { - return field.Type + // Kinds of data type examples: + // year(4) + // datetime + // varchar(64) + // bigint(20) + // int(10) unsigned + typeName := gstr.StrTillEx(field.Type, "(") // int(10) unsigned -> int + if typeName != "" { + typeName = gstr.Trim(typeName) + } else { + typeName = field.Type + } + return typeName } return "" } @@ -63,9 +75,10 @@ func (c *Core) ConvertDataForRecord(ctx context.Context, value interface{}, tabl data = MapOrStructToMapDeep(value, true) ) for fieldName, fieldValue := range data { + var fieldType = c.GetFieldTypeStr(ctx, fieldName, table, c.GetSchema()) data[fieldName], err = c.db.ConvertValueForField( ctx, - c.GetFieldTypeStr(ctx, fieldName, table, c.GetSchema()), + fieldType, fieldValue, ) if err != nil { @@ -83,6 +96,10 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field err error convertedValue = fieldValue ) + switch fieldValue.(type) { + case time.Time, *time.Time, gtime.Time, *gtime.Time: + goto Default + } // If `value` implements interface `driver.Valuer`, it then uses the interface for value converting. if valuer, ok := fieldValue.(driver.Valuer); ok { if convertedValue, err = valuer.Value(); err != nil { @@ -90,6 +107,7 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field } return convertedValue, nil } +Default: // Default value converting. var ( rvValue = reflect.ValueOf(fieldValue) @@ -100,6 +118,9 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field rvKind = rvValue.Kind() } switch rvKind { + case reflect.Invalid: + convertedValue = nil + case reflect.Slice, reflect.Array, reflect.Map: // It should ignore the bytes type. if _, ok := fieldValue.([]byte); !ok { @@ -109,7 +130,6 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field return nil, err } } - case reflect.Struct: switch r := fieldValue.(type) { // If the time is zero, it then updates it to nil, @@ -117,25 +137,65 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field case time.Time: if r.IsZero() { convertedValue = nil + } else { + switch fieldType { + case fieldTypeYear: + convertedValue = r.Format("2006") + case fieldTypeDate: + convertedValue = r.Format("2006-01-02") + case fieldTypeTime: + convertedValue = r.Format("15:04:05") + default: + } + } + + case *time.Time: + if r == nil { + // Nothing to do. + } else { + switch fieldType { + case fieldTypeYear: + convertedValue = r.Format("2006") + case fieldTypeDate: + convertedValue = r.Format("2006-01-02") + case fieldTypeTime: + convertedValue = r.Format("15:04:05") + default: + } } case gtime.Time: if r.IsZero() { convertedValue = nil } else { - convertedValue = r.Time + switch fieldType { + case fieldTypeYear: + convertedValue = r.Layout("2006") + case fieldTypeDate: + convertedValue = r.Layout("2006-01-02") + case fieldTypeTime: + convertedValue = r.Layout("15:04:05") + default: + convertedValue = r.Time + } } case *gtime.Time: if r.IsZero() { convertedValue = nil } else { - convertedValue = r.Time + switch fieldType { + case fieldTypeYear: + convertedValue = r.Layout("2006") + case fieldTypeDate: + convertedValue = r.Layout("2006-01-02") + case fieldTypeTime: + convertedValue = r.Layout("15:04:05") + default: + convertedValue = r.Time + } } - case *time.Time: - // Nothing to do. - case Counter, *Counter: // Nothing to do. @@ -156,7 +216,9 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field } } } + default: } + return convertedValue, nil } @@ -247,6 +309,10 @@ func (c *Core) CheckLocalTypeForField(ctx context.Context, fieldType string, fie fieldTypeDate: return LocalTypeDate, nil + case + fieldTypeTime: + return LocalTypeTime, nil + case fieldTypeDatetime, fieldTypeTimestamp, @@ -353,13 +419,19 @@ func (c *Core) ConvertValueForLocal( return gconv.Bool(fieldValue), nil case LocalTypeDate: - // Date without time. if t, ok := fieldValue.(time.Time); ok { return gtime.NewFromTime(t).Format("Y-m-d"), nil } t, _ := gtime.StrToTime(gconv.String(fieldValue)) return t.Format("Y-m-d"), nil + case LocalTypeTime: + if t, ok := fieldValue.(time.Time); ok { + return gtime.NewFromTime(t).Format("H:i:s"), nil + } + t, _ := gtime.StrToTime(gconv.String(fieldValue)) + return t.Format("H:i:s"), nil + case LocalTypeDatetime: if t, ok := fieldValue.(time.Time); ok { return gtime.NewFromTime(t), nil diff --git a/database/gdb/gdb_core_underlying.go b/database/gdb/gdb_core_underlying.go index dec32513a..dbdc59eb3 100644 --- a/database/gdb/gdb_core_underlying.go +++ b/database/gdb/gdb_core_underlying.go @@ -53,7 +53,9 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter } if c.db.GetConfig().QueryTimeout > 0 { - ctx, _ = context.WithTimeout(ctx, c.db.GetConfig().QueryTimeout) + var cancelFunc context.CancelFunc + ctx, cancelFunc = context.WithTimeout(ctx, c.db.GetConfig().QueryTimeout) + defer cancelFunc() } // Sql filtering. @@ -83,6 +85,9 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter Type: SqlTypeQueryContext, IsTransaction: link.IsTransaction(), }) + if err != nil { + return nil, err + } return out.Records, err } @@ -144,13 +149,18 @@ func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interf Type: SqlTypeExecContext, IsTransaction: link.IsTransaction(), }) + if err != nil { + return nil, err + } return out.Result, err } // DoFilter is a hook function, which filters the sql and its arguments before it's committed to underlying driver. // The parameter `link` specifies the current database connection operation object. You can modify the sql // string `sql` and its arguments `args` as you wish before they're committed to driver. -func (c *Core) DoFilter(ctx context.Context, link Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) { +func (c *Core) DoFilter( + ctx context.Context, link Link, sql string, args []interface{}, +) (newSql string, newArgs []interface{}, err error) { return sql, args, nil } @@ -322,7 +332,6 @@ func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (stmt *Stmt link = &txLink{tx.GetSqlTX()} } else { // Or else it creates one from master node. - var err error if link, err = c.MasterLink(); err != nil { return nil, err } @@ -336,7 +345,9 @@ func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (stmt *Stmt if c.db.GetConfig().PrepareTimeout > 0 { // DO NOT USE cancel function in prepare statement. - ctx, _ = context.WithTimeout(ctx, c.db.GetConfig().PrepareTimeout) + var cancelFunc context.CancelFunc + ctx, cancelFunc = context.WithTimeout(ctx, c.db.GetConfig().PrepareTimeout) + defer cancelFunc() } // Link execution. @@ -347,6 +358,9 @@ func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (stmt *Stmt Type: SqlTypePrepareContext, IsTransaction: link.IsTransaction(), }) + if err != nil { + return nil, err + } return out.Stmt, err } @@ -379,7 +393,7 @@ func (c *Core) FormatUpsert(columns []string, list List, option DoInsertOption) } } else { for _, column := range columns { - // If it's SAVE operation, do not automatically update the creating time. + // If it's `SAVE` operation, do not automatically update the creating time. if c.IsSoftCreatedFieldName(column) { continue } @@ -455,6 +469,11 @@ func (c *Core) RowsToResult(ctx context.Context, rows *sql.Rows) (Result, error) return result, nil } +// OrderRandomFunction returns the SQL function for random ordering. +func (c *Core) OrderRandomFunction() string { + return "RAND()" +} + func (c *Core) columnValueToLocalValue(ctx context.Context, value interface{}, columnType *sql.ColumnType) (interface{}, error) { var scanType = columnType.ScanType() if scanType != nil { @@ -469,6 +488,7 @@ func (c *Core) columnValueToLocalValue(ctx context.Context, value interface{}, c gconv.String(value), columnType.ScanType().String(), ), nil + default: } } // Other complex types, especially custom types. diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index 38e0d5b4c..752710d1c 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -344,8 +344,8 @@ func doQuoteString(s, charLeft, charRight string) string { return gstr.Join(array1, ",") } -func getFieldsFromStructOrMap(structOrMap interface{}) (fields []string) { - fields = []string{} +func getFieldsFromStructOrMap(structOrMap any) (fields []any) { + fields = []any{} if utils.IsStruct(structOrMap) { structFields, _ := gstructs.Fields(gstructs.FieldsInput{ Pointer: structOrMap, @@ -362,7 +362,7 @@ func getFieldsFromStructOrMap(structOrMap interface{}) (fields []string) { } } } else { - fields = gutil.Keys(structOrMap) + fields = gconv.Interfaces(gutil.Keys(structOrMap)) } return } @@ -777,11 +777,7 @@ func formatWhereKeyValue(in formatWhereKeyValueInput) (newArgs []interface{}) { } else { in.Buffer.WriteString(quotedKey) } - if s, ok := in.Value.(Raw); ok { - in.Buffer.WriteString(gconv.String(s)) - } else { - in.Args = append(in.Args, in.Value) - } + in.Args = append(in.Args, in.Value) } } return in.Args diff --git a/database/gdb/gdb_model.go b/database/gdb/gdb_model.go index ab9cf4317..beaa51500 100644 --- a/database/gdb/gdb_model.go +++ b/database/gdb/gdb_model.go @@ -24,8 +24,8 @@ type Model struct { linkType int // Mark for operation on master or slave. tablesInit string // Table names when model initialization. tables string // Operation table names, which can be more than one table names and aliases, like: "user", "user u", "user u, user_detail ud". - fields string // Operation fields, multiple fields joined using char ','. - fieldsEx string // Excluded operation fields, multiple fields joined using char ','. + fields []any // Operation fields, multiple fields joined using char ','. + fieldsEx []any // Excluded operation fields, it here uses slice instead of string type for quick filtering. withArray []interface{} // Arguments for With feature. withAll bool // Enable model association operations on all objects that have "with" tag in the struct. extraArgs []interface{} // Extra custom arguments for sql, which are prepended to the arguments before sql committed to underlying driver. @@ -65,7 +65,7 @@ type ChunkHandler func(result Result, err error) bool const ( linkTypeMaster = 1 linkTypeSlave = 2 - defaultFields = "*" + defaultField = "*" whereHolderOperatorWhere = 1 whereHolderOperatorAnd = 2 whereHolderOperatorOr = 3 @@ -132,7 +132,6 @@ func (c *Core) Model(tableNameQueryOrStruct ...interface{}) *Model { schema: c.schema, tablesInit: tableStr, tables: tableStr, - fields: defaultFields, start: -1, offset: -1, filter: true, @@ -281,6 +280,14 @@ func (m *Model) Clone() *Model { newModel.whereBuilder = m.whereBuilder.Clone() newModel.whereBuilder.model = newModel // Shallow copy slice attributes. + if n := len(m.fields); n > 0 { + newModel.fields = make([]any, n) + copy(newModel.fields, m.fields) + } + if n := len(m.fieldsEx); n > 0 { + newModel.fieldsEx = make([]any, n) + copy(newModel.fieldsEx, m.fieldsEx) + } if n := len(m.extraArgs); n > 0 { newModel.extraArgs = make([]interface{}, n) copy(newModel.extraArgs, m.extraArgs) @@ -289,6 +296,10 @@ func (m *Model) Clone() *Model { newModel.withArray = make([]interface{}, n) copy(newModel.withArray, m.withArray) } + if n := len(m.having); n > 0 { + newModel.having = make([]interface{}, n) + copy(newModel.having, m.having) + } return newModel } diff --git a/database/gdb/gdb_model_cache.go b/database/gdb/gdb_model_cache.go index c1b6ca820..76592cdec 100644 --- a/database/gdb/gdb_model_cache.go +++ b/database/gdb/gdb_model_cache.go @@ -90,7 +90,7 @@ func (m *Model) getSelectResultFromCache(ctx context.Context, sql string, args . } func (m *Model) saveSelectResultToCache( - ctx context.Context, queryType queryType, result Result, sql string, args ...interface{}, + ctx context.Context, selectType SelectType, result Result, sql string, args ...interface{}, ) (err error) { if !m.cacheEnabled || m.tx != nil { return @@ -108,18 +108,19 @@ func (m *Model) saveSelectResultToCache( // Special handler for Value/Count operations result. if len(result) > 0 { var core = m.db.GetCore() - switch queryType { - case queryTypeValue, queryTypeCount: + switch selectType { + case SelectTypeValue, SelectTypeArray, SelectTypeCount: if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil { if result[0][internalData.FirstResultColumn].IsEmpty() { result = nil } } + default: } } // In case of Cache Penetration. - if result.IsEmpty() { + if result != nil && result.IsEmpty() { if m.cacheOption.Force { result = Result{} } else { diff --git a/database/gdb/gdb_model_fields.go b/database/gdb/gdb_model_fields.go index c9e29a3f8..9f7e2cc7c 100644 --- a/database/gdb/gdb_model_fields.go +++ b/database/gdb/gdb_model_fields.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/gogf/gf/v2/container/gset" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) @@ -17,31 +18,38 @@ import ( // Fields appends `fieldNamesOrMapStruct` to the operation fields of the model, multiple fields joined using char ','. // The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct. // -// Eg: +// Example: // Fields("id", "name", "age") // Fields([]string{"id", "name", "age"}) // Fields(map[string]interface{}{"id":1, "name":"john", "age":18}) -// Fields(User{ Id: 1, Name: "john", Age: 18}). +// Fields(User{Id: 1, Name: "john", Age: 18}). func (m *Model) Fields(fieldNamesOrMapStruct ...interface{}) *Model { length := len(fieldNamesOrMapStruct) if length == 0 { return m } - fields := m.getFieldsFrom(m.tablesInit, fieldNamesOrMapStruct...) + fields := m.filterFieldsFrom(m.tablesInit, fieldNamesOrMapStruct...) if len(fields) == 0 { return m } - return m.appendFieldsByStr(gstr.Join(fields, ",")) + model := m.getModel() + return model.appendToFields(fields...) } // FieldsPrefix performs as function Fields but add extra prefix for each field. func (m *Model) FieldsPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...interface{}) *Model { - fields := m.getFieldsFrom(m.getTableNameByPrefixOrAlias(prefixOrAlias), fieldNamesOrMapStruct...) + fields := m.filterFieldsFrom( + m.getTableNameByPrefixOrAlias(prefixOrAlias), + fieldNamesOrMapStruct..., + ) if len(fields) == 0 { return m } - gstr.PrefixArray(fields, prefixOrAlias+".") - return m.appendFieldsByStr(gstr.Join(fields, ",")) + for i, field := range fields { + fields[i] = prefixOrAlias + "." + gconv.String(field) + } + model := m.getModel() + return model.appendToFields(fields...) } // FieldsEx appends `fieldNamesOrMapStruct` to the excluded operation fields of the model, @@ -49,28 +57,38 @@ func (m *Model) FieldsPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...inte // Note that this function supports only single table operations. // The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct. // -// Also see Fields. +// Example: +// FieldsEx("id", "name", "age") +// FieldsEx([]string{"id", "name", "age"}) +// FieldsEx(map[string]interface{}{"id":1, "name":"john", "age":18}) +// FieldsEx(User{Id: 1, Name: "john", Age: 18}). func (m *Model) FieldsEx(fieldNamesOrMapStruct ...interface{}) *Model { return m.doFieldsEx(m.tablesInit, fieldNamesOrMapStruct...) } + func (m *Model) doFieldsEx(table string, fieldNamesOrMapStruct ...interface{}) *Model { length := len(fieldNamesOrMapStruct) if length == 0 { return m } - fields := m.getFieldsFrom(table, fieldNamesOrMapStruct...) + fields := m.filterFieldsFrom(table, fieldNamesOrMapStruct...) if len(fields) == 0 { return m } - return m.appendFieldsExByStr(gstr.Join(fields, ",")) + model := m.getModel() + model.fieldsEx = append(model.fieldsEx, fields...) + return model } // FieldsExPrefix performs as function FieldsEx but add extra prefix for each field. func (m *Model) FieldsExPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...interface{}) *Model { - model := m.doFieldsEx(m.getTableNameByPrefixOrAlias(prefixOrAlias), fieldNamesOrMapStruct...) - array := gstr.SplitAndTrim(model.fieldsEx, ",") - gstr.PrefixArray(array, prefixOrAlias+".") - model.fieldsEx = gstr.Join(array, ",") + model := m.doFieldsEx( + m.getTableNameByPrefixOrAlias(prefixOrAlias), + fieldNamesOrMapStruct..., + ) + for i, field := range model.fieldsEx { + model.fieldsEx[i] = prefixOrAlias + "." + gconv.String(field) + } return model } @@ -80,7 +98,10 @@ func (m *Model) FieldCount(column string, as ...string) *Model { if len(as) > 0 && as[0] != "" { asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0])) } - return m.appendFieldsByStr(fmt.Sprintf(`COUNT(%s)%s`, m.QuoteWord(column), asStr)) + model := m.getModel() + return model.appendToFields( + fmt.Sprintf(`COUNT(%s)%s`, m.QuoteWord(column), asStr), + ) } // FieldSum formats and appends commonly used field `SUM(column)` to the select fields of model. @@ -89,7 +110,10 @@ func (m *Model) FieldSum(column string, as ...string) *Model { if len(as) > 0 && as[0] != "" { asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0])) } - return m.appendFieldsByStr(fmt.Sprintf(`SUM(%s)%s`, m.QuoteWord(column), asStr)) + model := m.getModel() + return model.appendToFields( + fmt.Sprintf(`SUM(%s)%s`, m.QuoteWord(column), asStr), + ) } // FieldMin formats and appends commonly used field `MIN(column)` to the select fields of model. @@ -98,7 +122,10 @@ func (m *Model) FieldMin(column string, as ...string) *Model { if len(as) > 0 && as[0] != "" { asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0])) } - return m.appendFieldsByStr(fmt.Sprintf(`MIN(%s)%s`, m.QuoteWord(column), asStr)) + model := m.getModel() + return model.appendToFields( + fmt.Sprintf(`MIN(%s)%s`, m.QuoteWord(column), asStr), + ) } // FieldMax formats and appends commonly used field `MAX(column)` to the select fields of model. @@ -107,7 +134,10 @@ func (m *Model) FieldMax(column string, as ...string) *Model { if len(as) > 0 && as[0] != "" { asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0])) } - return m.appendFieldsByStr(fmt.Sprintf(`MAX(%s)%s`, m.QuoteWord(column), asStr)) + model := m.getModel() + return model.appendToFields( + fmt.Sprintf(`MAX(%s)%s`, m.QuoteWord(column), asStr), + ) } // FieldAvg formats and appends commonly used field `AVG(column)` to the select fields of model. @@ -116,7 +146,10 @@ func (m *Model) FieldAvg(column string, as ...string) *Model { if len(as) > 0 && as[0] != "" { asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0])) } - return m.appendFieldsByStr(fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr)) + model := m.getModel() + return model.appendToFields( + fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr), + ) } // GetFieldsStr retrieves and returns all fields from the table, joined with char ','. @@ -152,17 +185,17 @@ func (m *Model) GetFieldsStr(prefix ...string) string { // joined with char ','. // The parameter `fields` specifies the fields that are excluded. // The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u."). -func (m *Model) GetFieldsExStr(fields string, prefix ...string) string { +func (m *Model) GetFieldsExStr(fields string, prefix ...string) (string, error) { prefixStr := "" if len(prefix) > 0 { prefixStr = prefix[0] } tableFields, err := m.TableFields(m.tablesInit) if err != nil { - panic(err) + return "", err } if len(tableFields) == 0 { - panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables)) + return "", gerror.Newf(`empty table fields for table "%s"`, m.tables) } fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ",")) fieldsArray := make([]string, len(tableFields)) @@ -180,7 +213,7 @@ func (m *Model) GetFieldsExStr(fields string, prefix ...string) string { newFields += prefixStr + k } newFields = m.db.GetCore().QuoteString(newFields) - return newFields + return newFields, nil } // HasField determine whether the field exists in the table. @@ -189,7 +222,7 @@ func (m *Model) HasField(field string) (bool, error) { } // getFieldsFrom retrieves, filters and returns fields name from table `table`. -func (m *Model) getFieldsFrom(table string, fieldNamesOrMapStruct ...interface{}) []string { +func (m *Model) filterFieldsFrom(table string, fieldNamesOrMapStruct ...any) []any { length := len(fieldNamesOrMapStruct) if length == 0 { return nil @@ -198,7 +231,7 @@ func (m *Model) getFieldsFrom(table string, fieldNamesOrMapStruct ...interface{} // String slice. case length >= 2: return m.mappingAndFilterToTableFields( - table, gconv.Strings(fieldNamesOrMapStruct), true, + table, fieldNamesOrMapStruct, true, ) // It needs type asserting. @@ -206,13 +239,13 @@ func (m *Model) getFieldsFrom(table string, fieldNamesOrMapStruct ...interface{} structOrMap := fieldNamesOrMapStruct[0] switch r := structOrMap.(type) { case string: - return m.mappingAndFilterToTableFields(table, []string{r}, false) + return m.mappingAndFilterToTableFields(table, []any{r}, false) case []string: - return m.mappingAndFilterToTableFields(table, r, true) + return m.mappingAndFilterToTableFields(table, gconv.Interfaces(r), true) case Raw, *Raw: - return []string{gconv.String(structOrMap)} + return []any{structOrMap} default: return m.mappingAndFilterToTableFields(table, getFieldsFromStructOrMap(structOrMap), true) @@ -223,29 +256,20 @@ func (m *Model) getFieldsFrom(table string, fieldNamesOrMapStruct ...interface{} } } -func (m *Model) appendFieldsByStr(fields string) *Model { - if fields != "" { - model := m.getModel() - if model.fields == defaultFields { - model.fields = "" - } - if model.fields != "" { - model.fields += "," - } - model.fields += fields - return model +func (m *Model) appendToFields(fields ...any) *Model { + if len(fields) == 0 { + return m } - return m + model := m.getModel() + model.fields = append(model.fields, fields...) + return model } -func (m *Model) appendFieldsExByStr(fieldsEx string) *Model { - if fieldsEx != "" { - model := m.getModel() - if model.fieldsEx != "" { - model.fieldsEx += "," +func (m *Model) isFieldInFieldsEx(field string) bool { + for _, v := range m.fieldsEx { + if v == field { + return true } - model.fieldsEx += fieldsEx - return model } - return m + return false } diff --git a/database/gdb/gdb_model_hook.go b/database/gdb/gdb_model_hook.go index 7dd007405..3428990a7 100644 --- a/database/gdb/gdb_model_hook.go +++ b/database/gdb/gdb_model_hook.go @@ -66,11 +66,12 @@ type internalParamHookDelete struct { // which is usually not be interesting for upper business hook handler. type HookSelectInput struct { internalParamHookSelect - Model *Model // Current operation Model. - Table string // The table name that to be used. Update this attribute to change target table name. - Schema string // The schema name that to be used. Update this attribute to change target schema name. - Sql string // The sql string that to be committed. - Args []interface{} // The arguments of sql. + Model *Model // Current operation Model. + Table string // The table name that to be used. Update this attribute to change target table name. + Schema string // The schema name that to be used. Update this attribute to change target schema name. + Sql string // The sql string that to be committed. + Args []interface{} // The arguments of sql. + SelectType SelectType // The type of this SELECT operation. } // HookInsertInput holds the parameters for insert hook operation. diff --git a/database/gdb/gdb_model_insert.go b/database/gdb/gdb_model_insert.go index 798b355ae..fad1728ac 100644 --- a/database/gdb/gdb_model_insert.go +++ b/database/gdb/gdb_model_insert.go @@ -45,11 +45,11 @@ func (m *Model) Data(data ...interface{}) *Model { model.data = s model.extraArgs = data[1:] } else { - m := make(map[string]interface{}) + newData := make(map[string]interface{}) for i := 0; i < len(data); i += 2 { - m[gconv.String(data[i])] = data[i+1] + newData[gconv.String(data[i])] = data[i+1] } - model.data = m + model.data = newData } } else if len(data) == 1 { switch value := data[0].(type) { @@ -285,7 +285,14 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption InsertOptio } // Automatic handling for creating/updating time. - if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") { + if fieldNameCreate != "" && m.isFieldInFieldsEx(fieldNameCreate) { + fieldNameCreate = "" + } + if fieldNameUpdate != "" && m.isFieldInFieldsEx(fieldNameUpdate) { + fieldNameUpdate = "" + } + var isSoftTimeFeatureEnabled = fieldNameCreate != "" || fieldNameUpdate != "" + if !m.unscoped && isSoftTimeFeatureEnabled { for k, v := range list { if fieldNameCreate != "" && empty.IsNil(v[fieldNameCreate]) { fieldCreateValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeCreate, false) @@ -299,6 +306,7 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption InsertOptio v[fieldNameUpdate] = fieldUpdateValue } } + // for timestamp field that should initialize the delete_at field with value, for example 0. if fieldNameDelete != "" && empty.IsNil(v[fieldNameDelete]) { fieldDeleteValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeDelete, true) if fieldDeleteValue != nil { diff --git a/database/gdb/gdb_model_order_group.go b/database/gdb/gdb_model_order_group.go index 8e25c14da..664dcf540 100644 --- a/database/gdb/gdb_model_order_group.go +++ b/database/gdb/gdb_model_order_group.go @@ -15,28 +15,42 @@ import ( // Order sets the "ORDER BY" statement for the model. // -// Eg: +// Example: // Order("id desc") -// Order("id", "desc"). +// Order("id", "desc") // Order("id desc,name asc") +// Order("id desc", "name asc") // Order("id desc").Order("name asc") // Order(gdb.Raw("field(id, 3,1,2)")). func (m *Model) Order(orderBy ...interface{}) *Model { if len(orderBy) == 0 { return m } - model := m.getModel() - if model.orderBy != "" { - model.orderBy += "," - } + var ( + core = m.db.GetCore() + model = m.getModel() + ) for _, v := range orderBy { + if model.orderBy != "" { + model.orderBy += "," + } switch v.(type) { case Raw, *Raw: model.orderBy += gconv.String(v) - return model + default: + orderByStr := gconv.String(v) + if gstr.Contains(orderByStr, " ") { + model.orderBy += core.QuoteString(orderByStr) + } else { + if gstr.Equal(orderByStr, "ASC") || gstr.Equal(orderByStr, "DESC") { + model.orderBy = gstr.TrimRight(model.orderBy, ",") + model.orderBy += " " + orderByStr + } else { + model.orderBy += core.QuoteWord(orderByStr) + } + } } } - model.orderBy += model.db.GetCore().QuoteString(gstr.JoinAny(orderBy, " ")) return model } @@ -59,7 +73,7 @@ func (m *Model) OrderDesc(column string) *Model { // OrderRandom sets the "ORDER BY RANDOM()" statement for the model. func (m *Model) OrderRandom() *Model { model := m.getModel() - model.orderBy = "RAND()" + model.orderBy = m.db.OrderRandomFunction() return model } @@ -68,10 +82,14 @@ func (m *Model) Group(groupBy ...string) *Model { if len(groupBy) == 0 { return m } - model := m.getModel() + var ( + core = m.db.GetCore() + model = m.getModel() + ) + if model.groupBy != "" { model.groupBy += "," } - model.groupBy += model.db.GetCore().QuoteString(strings.Join(groupBy, ",")) + model.groupBy += core.QuoteString(strings.Join(groupBy, ",")) return model } diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 975ca6dc4..8c6433abf 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -12,6 +12,7 @@ import ( "reflect" "github.com/gogf/gf/v2/container/gset" + "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/reflection" @@ -27,7 +28,7 @@ import ( // see Model.Where. func (m *Model) All(where ...interface{}) (Result, error) { var ctx = m.GetCtx() - return m.doGetAll(ctx, false, where...) + return m.doGetAll(ctx, SelectTypeDefault, false, where...) } // AllAndCount retrieves all records and the total count of records from the model. @@ -53,7 +54,7 @@ func (m *Model) AllAndCount(useFieldForCount bool) (result Result, totalCount in // If useFieldForCount is false, set the fields to a constant value of 1 for counting if !useFieldForCount { - countModel.fields = "1" + countModel.fields = []any{Raw("1")} } // Get the total count of records @@ -68,7 +69,7 @@ func (m *Model) AllAndCount(useFieldForCount bool) (result Result, totalCount in } // Retrieve all records - result, err = m.doGetAll(m.GetCtx(), false) + result, err = m.doGetAll(m.GetCtx(), SelectTypeDefault, false) return } @@ -109,7 +110,7 @@ func (m *Model) One(where ...interface{}) (Record, error) { if len(where) > 0 { return m.Where(where[0], where[1:]...).One() } - all, err := m.doGetAll(ctx, true) + all, err := m.doGetAll(ctx, SelectTypeDefault, true) if err != nil { return nil, err } @@ -135,24 +136,42 @@ func (m *Model) Array(fieldsAndWhere ...interface{}) ([]Value, error) { return m.Fields(gconv.String(fieldsAndWhere[0])).Array() } } - all, err := m.All() - if err != nil { - return nil, err - } + var ( field string core = m.db.GetCore() ctx = core.injectInternalColumn(m.GetCtx()) ) + all, err := m.doGetAll(ctx, SelectTypeArray, false) + if err != nil { + return nil, err + } if len(all) > 0 { - if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil { - field = internalData.FirstResultColumn - } else { + internalData := core.getInternalColumnFromCtx(ctx) + if internalData == nil { return nil, gerror.NewCode( gcode.CodeInternalError, - `query array error: the internal context data is missing. there's internal issue should be fixed`, + `query count error: the internal context data is missing. there's internal issue should be fixed`, ) } + // If FirstResultColumn present, it returns the value of the first record of the first field. + // It means it use no cache mechanism, while cache mechanism makes `internalData` missing. + field = internalData.FirstResultColumn + if field == "" { + // Fields number check. + var recordFields = m.getRecordFields(all[0]) + if len(recordFields) == 1 { + field = recordFields[0] + } else { + // it returns error if there are multiple fields in the result record. + return nil, gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid fields for "Array" operation, result fields number "%d"%s, but expect one`, + len(recordFields), + gjson.MustEncodeString(recordFields), + ) + } + } } return all.Array(field), nil } @@ -176,7 +195,7 @@ func (m *Model) Array(fieldsAndWhere ...interface{}) ([]Value, error) { func (m *Model) doStruct(pointer interface{}, where ...interface{}) error { model := m // Auto selecting fields by struct attributes. - if model.fieldsEx == "" && (model.fields == "" || model.fields == "*") { + if len(model.fieldsEx) == 0 && len(model.fields) == 0 { if v, ok := pointer.(reflect.Value); ok { model = m.Fields(v.Interface()) } else { @@ -212,7 +231,7 @@ func (m *Model) doStruct(pointer interface{}, where ...interface{}) error { func (m *Model) doStructs(pointer interface{}, where ...interface{}) error { model := m // Auto selecting fields by struct attributes. - if model.fieldsEx == "" && (model.fields == "" || model.fields == "*") { + if len(model.fieldsEx) == 0 && len(model.fields) == 0 { if v, ok := pointer.(reflect.Value); ok { model = m.Fields( reflect.New( @@ -281,10 +300,12 @@ func (m *Model) Scan(pointer interface{}, where ...interface{}) error { } } -// ScanAndCount scans a single record or record array that matches the given conditions and counts the total number of records that match those conditions. -// If useFieldForCount is true, it will use the fields specified in the model for counting; -// The pointer parameter is a pointer to a struct that the scanned data will be stored in. -// The pointerCount parameter is a pointer to an integer that will be set to the total number of records that match the given conditions. +// ScanAndCount scans a single record or record array that matches the given conditions and counts the total number +// of records that match those conditions. +// +// If `useFieldForCount` is true, it will use the fields specified in the model for counting; +// The `pointer` parameter is a pointer to a struct that the scanned data will be stored in. +// The `totalCount` parameter is a pointer to an integer that will be set to the total number of records that match the given conditions. // The where parameter is an optional list of conditions to use when retrieving records. // // Example: @@ -314,7 +335,7 @@ func (m *Model) ScanAndCount(pointer interface{}, totalCount *int, useFieldForCo countModel := m.Clone() // If useFieldForCount is false, set the fields to a constant value of 1 for counting if !useFieldForCount { - countModel.fields = "1" + countModel.fields = []any{Raw("1")} } // Get the total count of records @@ -341,7 +362,7 @@ func (m *Model) ScanList(structSlicePointer interface{}, bindToAttrName string, if err != nil { return err } - if m.fields != defaultFields || m.fieldsEx != "" { + if len(m.fields) > 0 || len(m.fieldsEx) != 0 { // There are custom fields. result, err = m.All() } else { @@ -394,27 +415,54 @@ func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) { } } var ( - sqlWithHolder, holderArgs = m.getFormattedSqlAndArgs(ctx, queryTypeValue, true) - all, err = m.doGetAllBySql(ctx, queryTypeValue, sqlWithHolder, holderArgs...) + sqlWithHolder, holderArgs = m.getFormattedSqlAndArgs(ctx, SelectTypeValue, true) + all, err = m.doGetAllBySql(ctx, SelectTypeValue, sqlWithHolder, holderArgs...) ) if err != nil { return nil, err } if len(all) > 0 { - if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil { - if v, ok := all[0][internalData.FirstResultColumn]; ok { - return v, nil - } - } else { + internalData := core.getInternalColumnFromCtx(ctx) + if internalData == nil { return nil, gerror.NewCode( gcode.CodeInternalError, - `query value error: the internal context data is missing. there's internal issue should be fixed`, + `query count error: the internal context data is missing. there's internal issue should be fixed`, ) } + // If FirstResultColumn present, it returns the value of the first record of the first field. + // It means it use no cache mechanism, while cache mechanism makes `internalData` missing. + if v, ok := all[0][internalData.FirstResultColumn]; ok { + return v, nil + } + // Fields number check. + var recordFields = m.getRecordFields(all[0]) + if len(recordFields) == 1 { + for _, v := range all[0] { + return v, nil + } + } + // it returns error if there are multiple fields in the result record. + return nil, gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid fields for "Value" operation, result fields number "%d"%s, but expect one`, + len(recordFields), + gjson.MustEncodeString(recordFields), + ) } return nil, nil } +func (m *Model) getRecordFields(record Record) []string { + if len(record) == 0 { + return nil + } + var fields = make([]string, 0) + for k := range record { + fields = append(fields, k) + } + return fields +} + // Count does "SELECT COUNT(x) FROM ..." statement for the model. // The optional parameter `where` is the same as the parameter of Model.Where function, // see Model.Where. @@ -427,27 +475,62 @@ func (m *Model) Count(where ...interface{}) (int, error) { return m.Where(where[0], where[1:]...).Count() } var ( - sqlWithHolder, holderArgs = m.getFormattedSqlAndArgs(ctx, queryTypeCount, false) - all, err = m.doGetAllBySql(ctx, queryTypeCount, sqlWithHolder, holderArgs...) + sqlWithHolder, holderArgs = m.getFormattedSqlAndArgs(ctx, SelectTypeCount, false) + all, err = m.doGetAllBySql(ctx, SelectTypeCount, sqlWithHolder, holderArgs...) ) if err != nil { return 0, err } if len(all) > 0 { - if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil { - if v, ok := all[0][internalData.FirstResultColumn]; ok { - return v.Int(), nil - } - } else { + internalData := core.getInternalColumnFromCtx(ctx) + if internalData == nil { return 0, gerror.NewCode( gcode.CodeInternalError, `query count error: the internal context data is missing. there's internal issue should be fixed`, ) } + // If FirstResultColumn present, it returns the value of the first record of the first field. + // It means it use no cache mechanism, while cache mechanism makes `internalData` missing. + if v, ok := all[0][internalData.FirstResultColumn]; ok { + return v.Int(), nil + } + // Fields number check. + var recordFields = m.getRecordFields(all[0]) + if len(recordFields) == 1 { + for _, v := range all[0] { + return v.Int(), nil + } + } + // it returns error if there are multiple fields in the result record. + return 0, gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid fields for "Count" operation, result fields number "%d"%s, but expect one`, + len(recordFields), + gjson.MustEncodeString(recordFields), + ) } return 0, nil } +// Exist does "SELECT 1 FROM ... LIMIT 1" statement for the model. +// The optional parameter `where` is the same as the parameter of Model.Where function, +// see Model.Where. +func (m *Model) Exist(where ...interface{}) (bool, error) { + if len(where) > 0 { + return m.Where(where[0], where[1:]...).Exist() + } + one, err := m.Fields(Raw("1")).One() + if err != nil { + return false, err + } + for _, val := range one { + if val.Bool() { + return true, nil + } + } + return false, nil +} + // CountColumn does "SELECT COUNT(x) FROM ..." statement for the model. func (m *Model) CountColumn(column string) (int, error) { if len(column) == 0 { @@ -576,16 +659,18 @@ func (m *Model) Having(having interface{}, args ...interface{}) *Model { // The parameter `limit1` specifies whether limits querying only one record if m.limit is not set. // The optional parameter `where` is the same as the parameter of Model.Where function, // see Model.Where. -func (m *Model) doGetAll(ctx context.Context, limit1 bool, where ...interface{}) (Result, error) { +func (m *Model) doGetAll(ctx context.Context, selectType SelectType, limit1 bool, where ...interface{}) (Result, error) { if len(where) > 0 { return m.Where(where[0], where[1:]...).All() } - sqlWithHolder, holderArgs := m.getFormattedSqlAndArgs(ctx, queryTypeNormal, limit1) - return m.doGetAllBySql(ctx, queryTypeNormal, sqlWithHolder, holderArgs...) + sqlWithHolder, holderArgs := m.getFormattedSqlAndArgs(ctx, selectType, limit1) + return m.doGetAllBySql(ctx, selectType, sqlWithHolder, holderArgs...) } // doGetAllBySql does the select statement on the database. -func (m *Model) doGetAllBySql(ctx context.Context, queryType queryType, sql string, args ...interface{}) (result Result, err error) { +func (m *Model) doGetAllBySql( + ctx context.Context, selectType SelectType, sql string, args ...interface{}, +) (result Result, err error) { if result, err = m.getSelectResultFromCache(ctx, sql, args...); err != nil || result != nil { return } @@ -597,29 +682,30 @@ func (m *Model) doGetAllBySql(ctx context.Context, queryType queryType, sql stri }, handler: m.hookHandler.Select, }, - Model: m, - Table: m.tables, - Sql: sql, - Args: m.mergeArguments(args), + Model: m, + Table: m.tables, + Sql: sql, + Args: m.mergeArguments(args), + SelectType: selectType, } if result, err = in.Next(ctx); err != nil { return } - err = m.saveSelectResultToCache(ctx, queryType, result, sql, args...) + err = m.saveSelectResultToCache(ctx, selectType, result, sql, args...) return } func (m *Model) getFormattedSqlAndArgs( - ctx context.Context, queryType queryType, limit1 bool, + ctx context.Context, selectType SelectType, limit1 bool, ) (sqlWithHolder string, holderArgs []interface{}) { - switch queryType { - case queryTypeCount: + switch selectType { + case SelectTypeCount: queryFields := "COUNT(1)" - if m.fields != "" && m.fields != "*" { + if len(m.fields) > 0 { // DO NOT quote the m.fields here, in case of fields like: // DISTINCT t.user_id uid - queryFields = fmt.Sprintf(`COUNT(%s%s)`, m.distinct, m.fields) + queryFields = fmt.Sprintf(`COUNT(%s%s)`, m.distinct, m.getFieldsAsStr()) } // Raw SQL Model. if m.rawSql != "" { @@ -656,7 +742,7 @@ func (m *Model) getFormattedSqlAndArgs( func (m *Model) getHolderAndArgsAsSubModel(ctx context.Context) (holder string, args []interface{}) { holder, args = m.getFormattedSqlAndArgs( - ctx, queryTypeNormal, false, + ctx, SelectTypeDefault, false, ) args = m.mergeArguments(args) return @@ -672,29 +758,50 @@ func (m *Model) getAutoPrefix() string { return autoPrefix } +func (m *Model) getFieldsAsStr() string { + var ( + fieldsStr string + core = m.db.GetCore() + ) + for _, v := range m.fields { + field := gconv.String(v) + switch { + case gstr.ContainsAny(field, "()"): + case gstr.ContainsAny(field, ". "): + default: + switch v.(type) { + case Raw, *Raw: + default: + field = core.QuoteString(field) + } + } + if fieldsStr != "" { + fieldsStr += "," + } + fieldsStr += field + } + return fieldsStr +} + // getFieldsFiltered checks the fields and fieldsEx attributes, filters and returns the fields that will // really be committed to underlying database driver. func (m *Model) getFieldsFiltered() string { - if m.fieldsEx == "" { - // No filtering, containing special chars. - if gstr.ContainsAny(m.fields, "()") { - return m.fields - } - // No filtering. - if !gstr.ContainsAny(m.fields, ". ") { - return m.db.GetCore().QuoteString(m.fields) - } - return m.fields + if len(m.fieldsEx) == 0 && len(m.fields) == 0 { + return defaultField + } + if len(m.fieldsEx) == 0 && len(m.fields) > 0 { + return m.getFieldsAsStr() } var ( fieldsArray []string - fieldsExSet = gset.NewStrSetFrom(gstr.SplitAndTrim(m.fieldsEx, ",")) + fieldsExSet = gset.NewStrSetFrom(gconv.Strings(m.fieldsEx)) ) - if m.fields != "*" { + if len(m.fields) > 0 { // Filter custom fields with fieldEx. fieldsArray = make([]string, 0, 8) - for _, v := range gstr.SplitAndTrim(m.fields, ",") { - fieldsArray = append(fieldsArray, v[gstr.PosR(v, "-")+1:]) + for _, v := range m.fields { + field := gconv.String(v) + fieldsArray = append(fieldsArray, field[gstr.PosR(field, "-")+1:]) } } else { if gstr.Contains(m.tables, " ") { diff --git a/database/gdb/gdb_model_soft_time.go b/database/gdb/gdb_model_soft_time.go index c2817d12a..73e155275 100644 --- a/database/gdb/gdb_model_soft_time.go +++ b/database/gdb/gdb_model_soft_time.go @@ -15,12 +15,11 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/intlog" + "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gcache" "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/gutil" ) // SoftTimeType custom defines the soft time field type. @@ -184,7 +183,7 @@ func (m *softTimeMaintainer) GetFieldNameAndTypeForDelete( ) } -// getSoftFieldName retrieves and returns the field name of the table for possible key. +// getSoftFieldNameAndType retrieves and returns the field name of the table for possible key. func (m *softTimeMaintainer) getSoftFieldNameAndType( ctx context.Context, schema string, table string, checkFiledNames []string, @@ -206,9 +205,7 @@ func (m *softTimeMaintainer) getSoftFieldNameAndType( return nil, nil } for _, checkFiledName := range checkFiledNames { - fieldName, _ = gutil.MapPossibleItemByKey( - gconv.Map(fieldsMap), checkFiledName, - ) + fieldName = searchFieldNameFromMap(fieldsMap, checkFiledName) if fieldName != "" { fieldType, _ = m.db.CheckLocalTypeForField( ctx, fieldsMap[fieldName].Type, nil, @@ -238,6 +235,23 @@ func (m *softTimeMaintainer) getSoftFieldNameAndType( return } +func searchFieldNameFromMap(fieldsMap map[string]*TableField, key string) string { + if len(fieldsMap) == 0 { + return "" + } + _, ok := fieldsMap[key] + if ok { + return key + } + key = utils.RemoveSymbols(key) + for k := range fieldsMap { + if strings.EqualFold(utils.RemoveSymbols(k), key) { + return k + } + } + return "" +} + // GetWhereConditionForDelete retrieves and returns the condition string for soft deleting. // It supports multiple tables string like: // "user u, user_detail ud" @@ -339,7 +353,7 @@ func (m *softTimeMaintainer) getConditionByFieldNameAndTypeForSoftDeleting( switch m.softTimeOption.SoftTimeType { case SoftTimeTypeAuto: switch fieldType { - case LocalTypeDate, LocalTypeDatetime: + case LocalTypeDate, LocalTypeTime, LocalTypeDatetime: return fmt.Sprintf(`%s IS NULL`, quotedFieldName) case LocalTypeInt, LocalTypeUint, LocalTypeInt64, LocalTypeUint64, LocalTypeBool: return fmt.Sprintf(`%s=0`, quotedFieldName) @@ -368,7 +382,7 @@ func (m *softTimeMaintainer) GetValueByFieldTypeForCreateOrUpdate( var value any if isDeletedField { switch fieldType { - case LocalTypeDate, LocalTypeDatetime: + case LocalTypeDate, LocalTypeTime, LocalTypeDatetime: value = nil default: value = 0 @@ -378,7 +392,7 @@ func (m *softTimeMaintainer) GetValueByFieldTypeForCreateOrUpdate( switch m.softTimeOption.SoftTimeType { case SoftTimeTypeAuto: switch fieldType { - case LocalTypeDate, LocalTypeDatetime: + case LocalTypeDate, LocalTypeTime, LocalTypeDatetime: value = gtime.Now() case LocalTypeInt, LocalTypeUint, LocalTypeInt64, LocalTypeUint64: value = gtime.Timestamp() diff --git a/database/gdb/gdb_model_update.go b/database/gdb/gdb_model_update.go index 2d14e558d..44c04d8e6 100644 --- a/database/gdb/gdb_model_update.go +++ b/database/gdb/gdb_model_update.go @@ -54,7 +54,7 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro ctx, "", m.tablesInit, ) ) - if m.unscoped { + if fieldNameUpdate != "" && (m.unscoped || m.isFieldInFieldsEx(fieldNameUpdate)) { fieldNameUpdate = "" } diff --git a/database/gdb/gdb_model_utility.go b/database/gdb/gdb_model_utility.go index 9a5da8522..79fe878ac 100644 --- a/database/gdb/gdb_model_utility.go +++ b/database/gdb/gdb_model_utility.go @@ -14,6 +14,7 @@ import ( "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/gutil" ) @@ -52,7 +53,7 @@ func (m *Model) getModel() *Model { // Eg: // ID -> id // NICK_Name -> nickname. -func (m *Model) mappingAndFilterToTableFields(table string, fields []string, filter bool) []string { +func (m *Model) mappingAndFilterToTableFields(table string, fields []any, filter bool) []any { var fieldsTable = table if fieldsTable != "" { hasTable, _ := m.db.GetCore().HasTable(fieldsTable) @@ -68,18 +69,24 @@ func (m *Model) mappingAndFilterToTableFields(table string, fields []string, fil if len(fieldsMap) == 0 { return fields } - var outputFieldsArray = make([]string, 0) + var outputFieldsArray = make([]any, 0) fieldsKeyMap := make(map[string]interface{}, len(fieldsMap)) for k := range fieldsMap { fieldsKeyMap[k] = nil } for _, field := range fields { - var inputFieldsArray []string - if gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, field) { - inputFieldsArray = append(inputFieldsArray, field) - } else if gregex.IsMatchString(regularFieldNameWithCommaRegPattern, field) { - inputFieldsArray = gstr.SplitAndTrim(field, ",") - } else { + var ( + fieldStr = gconv.String(field) + inputFieldsArray []string + ) + switch { + case gregex.IsMatchString(regularFieldNameWithoutDotRegPattern, fieldStr): + inputFieldsArray = append(inputFieldsArray, fieldStr) + + case gregex.IsMatchString(regularFieldNameWithCommaRegPattern, fieldStr): + inputFieldsArray = gstr.SplitAndTrim(fieldStr, ",") + + default: // Example: // user.id, user.name // replace(concat_ws(',',lpad(s.id, 6, '0'),s.name),',','') `code` @@ -186,26 +193,26 @@ func (m *Model) doMappingAndFilterForInsertOrUpdateDataMap(data Map, allowOmitEm data = tempMap } - if len(m.fields) > 0 && m.fields != "*" { + if len(m.fields) > 0 { // Keep specified fields. var ( - set = gset.NewStrSetFrom(gstr.SplitAndTrim(m.fields, ",")) + fieldSet = gset.NewStrSetFrom(gconv.Strings(m.fields)) charL, charR = m.db.GetChars() chars = charL + charR ) - set.Walk(func(item string) string { + fieldSet.Walk(func(item string) string { return gstr.Trim(item, chars) }) for k := range data { k = gstr.Trim(k, chars) - if !set.Contains(k) { + if !fieldSet.Contains(k) { delete(data, k) } } } else if len(m.fieldsEx) > 0 { // Filter specified fields. - for _, v := range gstr.SplitAndTrim(m.fieldsEx, ",") { - delete(data, v) + for _, v := range m.fieldsEx { + delete(data, gconv.String(v)) } } return data, nil diff --git a/database/gdb/gdb_model_with.go b/database/gdb/gdb_model_with.go index e259d1186..1bef5a60f 100644 --- a/database/gdb/gdb_model_with.go +++ b/database/gdb/gdb_model_with.go @@ -67,6 +67,9 @@ func (m *Model) WithAll() *Model { // doWithScanStruct handles model association operations feature for single struct. func (m *Model) doWithScanStruct(pointer interface{}) error { + if len(m.withArray) == 0 && m.withAll == false { + return nil + } var ( err error allowedTypeStrArray = make([]string, 0) @@ -183,6 +186,9 @@ func (m *Model) doWithScanStruct(pointer interface{}) error { // doWithScanStructs handles model association operations feature for struct slice. // Also see doWithScanStruct. func (m *Model) doWithScanStructs(pointer interface{}) error { + if len(m.withArray) == 0 && m.withAll == false { + return nil + } if v, ok := pointer.(reflect.Value); ok { pointer = v.Interface() } @@ -312,7 +318,7 @@ func (m *Model) parseWithTagInFieldStruct(field gstructs.Field) (output parseWit array []string key string ) - for _, v := range gstr.SplitAndTrim(ormTag, " ") { + for _, v := range gstr.SplitAndTrim(ormTag, ",") { array = gstr.Split(v, ":") if len(array) == 2 { key = array[0] @@ -321,9 +327,6 @@ func (m *Model) parseWithTagInFieldStruct(field gstructs.Field) (output parseWit data[key] += " " + gstr.Trim(v) } } - for k, v := range data { - data[k] = gstr.TrimRight(v, ",") - } output.With = data[OrmTagForWith] output.Where = data[OrmTagForWithWhere] output.Order = data[OrmTagForWithOrder] diff --git a/database/gdb/gdb_z_mysql_internal_test.go b/database/gdb/gdb_z_mysql_internal_test.go index abf82b6a1..a2428dbee 100644 --- a/database/gdb/gdb_z_mysql_internal_test.go +++ b/database/gdb/gdb_z_mysql_internal_test.go @@ -232,6 +232,38 @@ func Test_parseConfigNodeLink_WithType(t *testing.T) { t.Assert(newNode.Charset, defaultCharset) t.Assert(newNode.Protocol, `tcp`) }) + // https://github.com/gogf/gf/issues/3755 + gtest.C(t, func(t *gtest.T) { + node := &ConfigNode{ + Link: "mysql:user:pwd@tcp(rdsid.mysql.rds.aliyuncs.com)/dbname?charset=utf8&loc=Local", + } + newNode := parseConfigNodeLink(node) + t.Assert(newNode.Type, `mysql`) + t.Assert(newNode.User, `user`) + t.Assert(newNode.Pass, `pwd`) + t.Assert(newNode.Host, `rdsid.mysql.rds.aliyuncs.com`) + t.Assert(newNode.Port, ``) + t.Assert(newNode.Name, `dbname`) + t.Assert(newNode.Extra, `charset=utf8&loc=Local`) + t.Assert(newNode.Charset, `utf8`) + t.Assert(newNode.Protocol, `tcp`) + }) + // https://github.com/gogf/gf/issues/3862 + gtest.C(t, func(t *gtest.T) { + node := &ConfigNode{ + Link: "mysql:username:password@unix(/tmp/mysql.sock)/dbname", + } + newNode := parseConfigNodeLink(node) + t.Assert(newNode.Type, `mysql`) + t.Assert(newNode.User, `username`) + t.Assert(newNode.Pass, `password`) + t.Assert(newNode.Host, `/tmp/mysql.sock`) + t.Assert(newNode.Port, ``) + t.Assert(newNode.Name, `dbname`) + t.Assert(newNode.Extra, ``) + t.Assert(newNode.Charset, `utf8`) + t.Assert(newNode.Protocol, `unix`) + }) } func Test_Func_doQuoteWord(t *testing.T) { diff --git a/database/gredis/gredis_redis.go b/database/gredis/gredis_redis.go index 04d72b472..5b24be32d 100644 --- a/database/gredis/gredis_redis.go +++ b/database/gredis/gredis_redis.go @@ -12,7 +12,6 @@ import ( "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/text/gstr" ) // Redis client. @@ -48,12 +47,7 @@ const ( errorNilRedis = `the Redis object is nil` ) -var ( - errorNilAdapter = gstr.Trim(gstr.Replace(` -redis adapter is not set, missing configuration or adapter register? -possible reference: https://github.com/gogf/gf/tree/master/contrib/nosql/redis -`, "\n", "")) -) +const errorNilAdapter = `redis adapter is not set, missing configuration or adapter register? possible reference: https://github.com/gogf/gf/tree/master/contrib/nosql/redis` // initGroup initializes the group object of redis. func (r *Redis) initGroup() *Redis { diff --git a/debug/gdebug/gdebug_caller.go b/debug/gdebug/gdebug_caller.go index d02ff4ab8..e5863e25f 100644 --- a/debug/gdebug/gdebug_caller.go +++ b/debug/gdebug/gdebug_caller.go @@ -133,16 +133,25 @@ func filterFileByFilters(file string, filters []string) (filtered bool) { // CallerPackage returns the package name of the caller. func CallerPackage() string { function, _, _ := Caller() + // it defines a new internal function to retrieve the package name from caller function name, + // which is for unit testing purpose for core logic of this function. + return getPackageFromCallerFunction(function) +} + +func getPackageFromCallerFunction(function string) string { indexSplit := strings.LastIndexByte(function, '/') if indexSplit == -1 { return function[:strings.IndexByte(function, '.')] - } else { - leftPart := function[:indexSplit+1] - rightPart := function[indexSplit+1:] - indexDot := strings.IndexByte(function, '.') - rightPart = rightPart[:indexDot-1] - return leftPart + rightPart } + var ( + leftPart = function[:indexSplit+1] + rightPart = function[indexSplit+1:] + indexDot = strings.IndexByte(rightPart, '.') + ) + if indexDot >= 0 { + rightPart = rightPart[:indexDot] + } + return leftPart + rightPart } // CallerFunction returns the function name of the caller. diff --git a/debug/gdebug/gdebug_z_unit_internal_test.go b/debug/gdebug/gdebug_z_unit_internal_test.go new file mode 100644 index 000000000..272141479 --- /dev/null +++ b/debug/gdebug/gdebug_z_unit_internal_test.go @@ -0,0 +1,26 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gdebug + +import ( + "testing" +) + +func Test_getPackageFromCallerFunction(t *testing.T) { + dataMap := map[string]string{ + "github.com/gogf/gf/v2/test/a": "github.com/gogf/gf/v2/test/a", + "github.com/gogf/gf/v2/test/a.C": "github.com/gogf/gf/v2/test/a", + "github.com/gogf/gf/v2/test/aa.C": "github.com/gogf/gf/v2/test/aa", + "github.com/gogf/gf/v2/test/gtest.C": "github.com/gogf/gf/v2/test/gtest", + } + for functionName, packageName := range dataMap { + if result := getPackageFromCallerFunction(functionName); result != packageName { + t.Logf(`%s != %s`, result, packageName) + t.Fail() + } + } +} diff --git a/debug/gdebug/gdebug_z_unit_test.go b/debug/gdebug/gdebug_z_unit_test.go index 606a9c4c5..0a8b0f84f 100644 --- a/debug/gdebug/gdebug_z_unit_test.go +++ b/debug/gdebug/gdebug_z_unit_test.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package gdebug_test import ( diff --git a/encoding/ghtml/ghtml.go b/encoding/ghtml/ghtml.go index da0b798cd..34fa027aa 100644 --- a/encoding/ghtml/ghtml.go +++ b/encoding/ghtml/ghtml.go @@ -12,6 +12,8 @@ import ( "reflect" "strings" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" strip "github.com/grokify/html-strip-tags-go" ) @@ -60,15 +62,26 @@ func SpecialCharsDecode(s string) string { } // SpecialCharsMapOrStruct automatically encodes string values/attributes for map/struct. +// +// Note that, if operation on struct, the given parameter `mapOrStruct` should be type of pointer to struct. +// +// For example: +// var m = map{} +// var s = struct{}{} +// OK: SpecialCharsMapOrStruct(m) +// OK: SpecialCharsMapOrStruct(&s) +// Error: SpecialCharsMapOrStruct(s) func SpecialCharsMapOrStruct(mapOrStruct interface{}) error { var ( reflectValue = reflect.ValueOf(mapOrStruct) reflectKind = reflectValue.Kind() + originalKind = reflectKind ) for reflectValue.IsValid() && (reflectKind == reflect.Ptr || reflectKind == reflect.Interface) { reflectValue = reflectValue.Elem() reflectKind = reflectValue.Kind() } + switch reflectKind { case reflect.Map: var ( @@ -82,22 +95,43 @@ func SpecialCharsMapOrStruct(mapOrStruct interface{}) error { reflectValue.SetMapIndex(key, reflect.ValueOf(SpecialChars(mapValue.String()))) case reflect.Interface: if mapValue.Elem().Kind() == reflect.String { - reflectValue.SetMapIndex(key, reflect.ValueOf(SpecialChars(mapValue.Elem().String()))) + reflectValue.SetMapIndex( + key, + reflect.ValueOf(SpecialChars(mapValue.Elem().String())), + ) } + default: } } case reflect.Struct: - var ( - fieldValue reflect.Value - ) + if originalKind != reflect.Ptr { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid input parameter type "%s", should be type of pointer to struct`, + reflect.TypeOf(mapOrStruct).String(), + ) + } + var fieldValue reflect.Value for i := 0; i < reflectValue.NumField(); i++ { fieldValue = reflectValue.Field(i) switch fieldValue.Kind() { case reflect.String: - fieldValue.Set(reflect.ValueOf(SpecialChars(fieldValue.String()))) + fieldValue.Set( + reflect.ValueOf( + SpecialChars(fieldValue.String()), + ), + ) + default: } } + + default: + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `invalid input parameter type "%s"`, + reflect.TypeOf(mapOrStruct).String(), + ) } return nil } diff --git a/encoding/ghtml/ghtml_z_unit_test.go b/encoding/ghtml/ghtml_z_unit_test.go index 8ac444753..41b06912d 100644 --- a/encoding/ghtml/ghtml_z_unit_test.go +++ b/encoding/ghtml/ghtml_z_unit_test.go @@ -78,4 +78,14 @@ func Test_SpecialCharsMapOrStruct_Struct(t *testing.T) { t.Assert(a.Title, `<h1>T</h1>`) t.Assert(a.Content, `<div>C</div>`) }) + + // should error + gtest.C(t, func(t *gtest.T) { + a := A{ + Title: "

T

", + Content: "
C
", + } + err := ghtml.SpecialCharsMapOrStruct(a) + t.AssertNE(err, nil) + }) } diff --git a/encoding/gjson/gjson_api_encoding.go b/encoding/gjson/gjson_api_encoding.go index 7f08f0ccc..23a0ae86f 100644 --- a/encoding/gjson/gjson_api_encoding.go +++ b/encoding/gjson/gjson_api_encoding.go @@ -207,7 +207,7 @@ func (j *Json) ToProperties() ([]byte, error) { return gproperties.Encode(j.Map()) } -// TopropertiesString properties to string +// ToPropertiesString properties to string func (j *Json) ToPropertiesString() (string, error) { b, e := j.ToProperties() return string(b), e @@ -221,7 +221,7 @@ func (j *Json) MustToProperties() []byte { return result } -// MustTopropertiesString +// MustToPropertiesString func (j *Json) MustToPropertiesString() string { return string(j.MustToProperties()) } diff --git a/encoding/gjson/gjson_api_new_load.go b/encoding/gjson/gjson_api_new_load.go index ec45f55df..113e0dc96 100644 --- a/encoding/gjson/gjson_api_new_load.go +++ b/encoding/gjson/gjson_api_new_load.go @@ -7,22 +7,10 @@ package gjson import ( - "bytes" "reflect" - "github.com/gogf/gf/v2/encoding/gini" - "github.com/gogf/gf/v2/encoding/gproperties" - "github.com/gogf/gf/v2/encoding/gtoml" - "github.com/gogf/gf/v2/encoding/gxml" - "github.com/gogf/gf/v2/encoding/gyaml" - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/rwmutex" - "github.com/gogf/gf/v2/os/gfile" - "github.com/gogf/gf/v2/text/gregex" - "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) @@ -57,16 +45,26 @@ func NewWithTag(data interface{}, tags string, safe ...bool) *Json { // or slice for data access reason, or it will make no sense. func NewWithOptions(data interface{}, options Options) *Json { var j *Json - switch data.(type) { - case string, []byte: - if r, err := loadContentWithOptions(data, options); err == nil { + switch result := data.(type) { + case []byte: + if r, err := loadContentWithOptions(result, options); err == nil { j = r - } else { - j = &Json{ - p: &data, - c: byte(defaultSplitChar), - vc: false, - } + break + } + j = &Json{ + p: &data, + c: byte(defaultSplitChar), + vc: false, + } + case string: + if r, err := loadContentWithOptions([]byte(result), options); err == nil { + j = r + break + } + j = &Json{ + p: &data, + c: byte(defaultSplitChar), + vc: false, } default: var ( @@ -98,266 +96,3 @@ func NewWithOptions(data interface{}, options Options) *Json { j.mu = rwmutex.Create(options.Safe) return j } - -// Load loads content from specified file `path`, and creates a Json object from its content. -func Load(path string, safe ...bool) (*Json, error) { - if p, err := gfile.Search(path); err != nil { - return nil, err - } else { - path = p - } - options := Options{ - Type: ContentType(gfile.Ext(path)), - } - if len(safe) > 0 && safe[0] { - options.Safe = true - } - return doLoadContentWithOptions(gfile.GetBytesWithCache(path), options) -} - -// LoadWithOptions creates a Json object from given JSON format content and options. -func LoadWithOptions(data interface{}, options Options) (*Json, error) { - return doLoadContentWithOptions(gconv.Bytes(data), options) -} - -// LoadJson creates a Json object from given JSON format content. -func LoadJson(data interface{}, safe ...bool) (*Json, error) { - option := Options{ - Type: ContentTypeJson, - } - if len(safe) > 0 && safe[0] { - option.Safe = true - } - return doLoadContentWithOptions(gconv.Bytes(data), option) -} - -// LoadXml creates a Json object from given XML format content. -func LoadXml(data interface{}, safe ...bool) (*Json, error) { - option := Options{ - Type: ContentTypeXml, - } - if len(safe) > 0 && safe[0] { - option.Safe = true - } - return doLoadContentWithOptions(gconv.Bytes(data), option) -} - -// LoadIni creates a Json object from given INI format content. -func LoadIni(data interface{}, safe ...bool) (*Json, error) { - option := Options{ - Type: ContentTypeIni, - } - if len(safe) > 0 && safe[0] { - option.Safe = true - } - return doLoadContentWithOptions(gconv.Bytes(data), option) -} - -// LoadYaml creates a Json object from given YAML format content. -func LoadYaml(data interface{}, safe ...bool) (*Json, error) { - option := Options{ - Type: ContentTypeYaml, - } - if len(safe) > 0 && safe[0] { - option.Safe = true - } - return doLoadContentWithOptions(gconv.Bytes(data), option) -} - -// LoadToml creates a Json object from given TOML format content. -func LoadToml(data interface{}, safe ...bool) (*Json, error) { - option := Options{ - Type: ContentTypeToml, - } - if len(safe) > 0 && safe[0] { - option.Safe = true - } - return doLoadContentWithOptions(gconv.Bytes(data), option) -} - -// LoadProperties creates a Json object from given TOML format content. -func LoadProperties(data interface{}, safe ...bool) (*Json, error) { - option := Options{ - Type: ContentTypeProperties, - } - if len(safe) > 0 && safe[0] { - option.Safe = true - } - return doLoadContentWithOptions(gconv.Bytes(data), option) -} - -// LoadContent creates a Json object from given content, it checks the data type of `content` -// automatically, supporting data content type as follows: -// JSON, XML, INI, YAML and TOML. -func LoadContent(data interface{}, safe ...bool) (*Json, error) { - content := gconv.Bytes(data) - if len(content) == 0 { - return New(nil, safe...), nil - } - return LoadContentType(checkDataType(content), content, safe...) -} - -// LoadContentType creates a Json object from given type and content, -// supporting data content type as follows: -// JSON, XML, INI, YAML and TOML. -func LoadContentType(dataType ContentType, data interface{}, safe ...bool) (*Json, error) { - content := gconv.Bytes(data) - if len(content) == 0 { - return New(nil, safe...), nil - } - // ignore UTF8-BOM - if content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF { - content = content[3:] - } - options := Options{ - Type: dataType, - StrNumber: true, - } - if len(safe) > 0 && safe[0] { - options.Safe = true - } - return doLoadContentWithOptions(content, options) -} - -// IsValidDataType checks and returns whether given `dataType` a valid data type for loading. -func IsValidDataType(dataType ContentType) bool { - if dataType == "" { - return false - } - if dataType[0] == '.' { - dataType = dataType[1:] - } - switch dataType { - case - ContentTypeJson, - ContentTypeJs, - ContentTypeXml, - ContentTypeYaml, - ContentTypeYml, - ContentTypeToml, - ContentTypeIni, - ContentTypeProperties: - return true - } - return false -} - -func loadContentWithOptions(data interface{}, options Options) (*Json, error) { - content := gconv.Bytes(data) - if len(content) == 0 { - return NewWithOptions(nil, options), nil - } - if options.Type == "" { - options.Type = checkDataType(content) - } - return loadContentTypeWithOptions(content, options) -} - -func loadContentTypeWithOptions(data interface{}, options Options) (*Json, error) { - content := gconv.Bytes(data) - if len(content) == 0 { - return NewWithOptions(nil, options), nil - } - // ignore UTF8-BOM - if content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF { - content = content[3:] - } - return doLoadContentWithOptions(content, options) -} - -// doLoadContent creates a Json object from given content. -// It supports data content type as follows: -// JSON, XML, INI, YAML and TOML. -func doLoadContentWithOptions(data []byte, options Options) (*Json, error) { - var ( - err error - result interface{} - ) - if len(data) == 0 { - return NewWithOptions(nil, options), nil - } - if options.Type == "" { - options.Type = checkDataType(data) - } - options.Type = ContentType(gstr.TrimLeft( - string(options.Type), "."), - ) - switch options.Type { - case ContentTypeJson, ContentTypeJs: - - case ContentTypeXml: - if data, err = gxml.ToJson(data); err != nil { - return nil, err - } - - case ContentTypeYaml, ContentTypeYml: - if data, err = gyaml.ToJson(data); err != nil { - return nil, err - } - - case ContentTypeToml: - if data, err = gtoml.ToJson(data); err != nil { - return nil, err - } - - case ContentTypeIni: - if data, err = gini.ToJson(data); err != nil { - return nil, err - } - case ContentTypeProperties: - if data, err = gproperties.ToJson(data); err != nil { - return nil, err - } - - default: - err = gerror.NewCodef( - gcode.CodeInvalidParameter, - `unsupported type "%s" for loading`, - options.Type, - ) - } - if err != nil { - return nil, err - } - decoder := json.NewDecoder(bytes.NewReader(data)) - if options.StrNumber { - decoder.UseNumber() - } - if err = decoder.Decode(&result); err != nil { - return nil, err - } - switch result.(type) { - case string, []byte: - return nil, gerror.Newf(`json decoding failed for content: %s`, data) - } - return NewWithOptions(result, options), nil -} - -// checkDataType automatically checks and returns the data type for `content`. -// Note that it uses regular expression for loose checking, you can use LoadXXX/LoadContentType -// functions to load the content for certain content type. -func checkDataType(content []byte) ContentType { - if json.Valid(content) { - return ContentTypeJson - } else if gregex.IsMatch(`^<.+>[\S\s]+<.+>\s*$`, content) { - return ContentTypeXml - } else if !gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*"""[\s\S]+"""`, content) && - !gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*'''[\s\S]+'''`, content) && - ((gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*".+"`, content) || gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*\w+`, content)) || - (gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*".+"`, content) || gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, content))) { - return ContentTypeYaml - } else if !gregex.IsMatch(`^[\s\t\n\r]*;.+`, content) && - !gregex.IsMatch(`[\s\t\n\r]+;.+`, content) && - !gregex.IsMatch(`[\n\r]+[\s\t\w\-]+\.[\s\t\w\-]+\s*=\s*.+`, content) && - (gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, content) || gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content)) { - return ContentTypeToml - } else if gregex.IsMatch(`\[[\w\.]+\]`, content) && - (gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, content) || gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content)) { - // Must contain "[xxx]" section. - return ContentTypeIni - } else if gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content) { - return ContentTypeProperties - } else { - return "" - } -} diff --git a/encoding/gjson/gjson_api_new_load_content.go b/encoding/gjson/gjson_api_new_load_content.go new file mode 100644 index 000000000..7ddda24c1 --- /dev/null +++ b/encoding/gjson/gjson_api_new_load_content.go @@ -0,0 +1,279 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gjson + +import ( + "bytes" + + "github.com/gogf/gf/v2/encoding/gini" + "github.com/gogf/gf/v2/encoding/gproperties" + "github.com/gogf/gf/v2/encoding/gtoml" + "github.com/gogf/gf/v2/encoding/gxml" + "github.com/gogf/gf/v2/encoding/gyaml" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/text/gregex" + "github.com/gogf/gf/v2/text/gstr" +) + +// LoadWithOptions creates a Json object from given JSON format content and options. +func LoadWithOptions(data []byte, options Options) (*Json, error) { + return loadContentWithOptions(data, options) +} + +// LoadJson creates a Json object from given JSON format content. +func LoadJson(data []byte, safe ...bool) (*Json, error) { + var option = Options{ + Type: ContentTypeJson, + } + if len(safe) > 0 && safe[0] { + option.Safe = true + } + return loadContentWithOptions(data, option) +} + +// LoadXml creates a Json object from given XML format content. +func LoadXml(data []byte, safe ...bool) (*Json, error) { + var option = Options{ + Type: ContentTypeXml, + } + if len(safe) > 0 && safe[0] { + option.Safe = true + } + return loadContentWithOptions(data, option) +} + +// LoadIni creates a Json object from given INI format content. +func LoadIni(data []byte, safe ...bool) (*Json, error) { + var option = Options{ + Type: ContentTypeIni, + } + if len(safe) > 0 && safe[0] { + option.Safe = true + } + return loadContentWithOptions(data, option) +} + +// LoadYaml creates a Json object from given YAML format content. +func LoadYaml(data []byte, safe ...bool) (*Json, error) { + var option = Options{ + Type: ContentTypeYaml, + } + if len(safe) > 0 && safe[0] { + option.Safe = true + } + return loadContentWithOptions(data, option) +} + +// LoadToml creates a Json object from given TOML format content. +func LoadToml(data []byte, safe ...bool) (*Json, error) { + var option = Options{ + Type: ContentTypeToml, + } + if len(safe) > 0 && safe[0] { + option.Safe = true + } + return loadContentWithOptions(data, option) +} + +// LoadProperties creates a Json object from given TOML format content. +func LoadProperties(data []byte, safe ...bool) (*Json, error) { + var option = Options{ + Type: ContentTypeProperties, + } + if len(safe) > 0 && safe[0] { + option.Safe = true + } + return loadContentWithOptions(data, option) +} + +// LoadContent creates a Json object from given content, it checks the data type of `content` +// automatically, supporting data content type as follows: +// JSON, XML, INI, YAML and TOML. +func LoadContent(data []byte, safe ...bool) (*Json, error) { + return LoadContentType("", data, safe...) +} + +// LoadContentType creates a Json object from given type and content, +// supporting data content type as follows: +// JSON, XML, INI, YAML and TOML. +func LoadContentType(dataType ContentType, data []byte, safe ...bool) (*Json, error) { + if len(data) == 0 { + return New(nil, safe...), nil + } + var options = Options{ + Type: dataType, + StrNumber: true, + } + if len(safe) > 0 && safe[0] { + options.Safe = true + } + return loadContentWithOptions(data, options) +} + +// IsValidDataType checks and returns whether given `dataType` a valid data type for loading. +func IsValidDataType(dataType ContentType) bool { + if dataType == "" { + return false + } + if dataType[0] == '.' { + dataType = dataType[1:] + } + switch dataType { + case + ContentTypeJson, + ContentTypeJs, + ContentTypeXml, + ContentTypeYaml, + ContentTypeYml, + ContentTypeToml, + ContentTypeIni, + ContentTypeProperties: + return true + } + return false +} + +func trimBOM(data []byte) []byte { + if len(data) < 3 { + return data + } + if data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF { + data = data[3:] + } + return data +} + +// loadContentWithOptions creates a Json object from given content. +// It supports data content type as follows: +// JSON, XML, INI, YAML and TOML. +func loadContentWithOptions(data []byte, options Options) (*Json, error) { + var ( + err error + result interface{} + ) + data = trimBOM(data) + if len(data) == 0 { + return NewWithOptions(nil, options), nil + } + if options.Type == "" { + options.Type, err = checkDataType(data) + if err != nil { + return nil, err + } + } + options.Type = ContentType(gstr.TrimLeft( + string(options.Type), "."), + ) + switch options.Type { + case ContentTypeJson, ContentTypeJs: + + case ContentTypeXml: + data, err = gxml.ToJson(data) + + case ContentTypeYaml, ContentTypeYml: + data, err = gyaml.ToJson(data) + + case ContentTypeToml: + data, err = gtoml.ToJson(data) + + case ContentTypeIni: + data, err = gini.ToJson(data) + + case ContentTypeProperties: + data, err = gproperties.ToJson(data) + + default: + err = gerror.NewCodef( + gcode.CodeInvalidParameter, + `unsupported type "%s" for loading`, + options.Type, + ) + } + if err != nil { + return nil, err + } + + decoder := json.NewDecoder(bytes.NewReader(data)) + if options.StrNumber { + decoder.UseNumber() + } + if err = decoder.Decode(&result); err != nil { + return nil, err + } + switch result.(type) { + case string, []byte: + return nil, gerror.Newf(`json decoding failed for content: %s`, data) + } + return NewWithOptions(result, options), nil +} + +// checkDataType automatically checks and returns the data type for `content`. +// Note that it uses regular expression for loose checking, you can use LoadXXX/LoadContentType +// functions to load the content for certain content type. +// TODO it is not graceful here automatic judging the data type. +// TODO it might be removed in the future, which lets the user explicitly specify the data type not automatic checking. +func checkDataType(data []byte) (ContentType, error) { + switch { + case json.Valid(data): + return ContentTypeJson, nil + + case isXmlContent(data): + return ContentTypeXml, nil + + case isYamlContent(data): + return ContentTypeYaml, nil + + case isTomlContent(data): + return ContentTypeToml, nil + + case isIniContent(data): + // Must contain "[xxx]" section. + return ContentTypeIni, nil + + case isPropertyContent(data): + return ContentTypeProperties, nil + + default: + return "", gerror.NewCode( + gcode.CodeOperationFailed, + `unable auto check the data format type`, + ) + } +} + +func isXmlContent(data []byte) bool { + return gregex.IsMatch(`^\s*<.+>[\S\s]+<.+>\s*$`, data) +} + +func isYamlContent(data []byte) bool { + return !gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*"""[\s\S]+"""`, data) && + !gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*'''[\s\S]+'''`, data) && + ((gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*".+"`, data) || + gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*\w+`, data)) || + (gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*".+"`, data) || + gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, data))) +} + +func isTomlContent(data []byte) bool { + return !gregex.IsMatch(`^[\s\t\n\r]*;.+`, data) && + !gregex.IsMatch(`[\s\t\n\r]+;.+`, data) && + !gregex.IsMatch(`[\n\r]+[\s\t\w\-]+\.[\s\t\w\-]+\s*=\s*.+`, data) && + (gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, data) || + gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, data)) +} + +func isIniContent(data []byte) bool { + return gregex.IsMatch(`\[[\w\.]+\]`, data) && + (gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, data) || + gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, data)) +} + +func isPropertyContent(data []byte) bool { + return gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, data) +} diff --git a/encoding/gjson/gjson_api_new_load_path.go b/encoding/gjson/gjson_api_new_load_path.go new file mode 100644 index 000000000..7cdab5d86 --- /dev/null +++ b/encoding/gjson/gjson_api_new_load_path.go @@ -0,0 +1,34 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gjson + +import "github.com/gogf/gf/v2/os/gfile" + +// Load loads content from specified file `path`, and creates a Json object from its content. +// Deprecated: use LoadPath instead. +func Load(path string, safe ...bool) (*Json, error) { + var isSafe bool + if len(safe) > 0 { + isSafe = safe[0] + } + return LoadPath(path, Options{ + Safe: isSafe, + }) +} + +// LoadPath loads content from specified file `path`, and creates a Json object from its content. +func LoadPath(path string, options Options) (*Json, error) { + if p, err := gfile.Search(path); err != nil { + return nil, err + } else { + path = p + } + if options.Type == "" { + options.Type = ContentType(gfile.Ext(path)) + } + return loadContentWithOptions(gfile.GetBytesWithCache(path), options) +} diff --git a/encoding/gjson/gjson_z_example_load_test.go b/encoding/gjson/gjson_z_example_load_test.go index 102029f6f..812cd2a70 100644 --- a/encoding/gjson/gjson_z_example_load_test.go +++ b/encoding/gjson/gjson_z_example_load_test.go @@ -29,7 +29,7 @@ func ExampleLoad() { } func ExampleLoadJson() { - jsonContent := `{"name":"john", "score":"100"}` + jsonContent := []byte(`{"name":"john", "score":"100"}`) j, _ := gjson.LoadJson(jsonContent) fmt.Println(j.Get("name")) fmt.Println(j.Get("score")) @@ -40,11 +40,13 @@ func ExampleLoadJson() { } func ExampleLoadXml() { - xmlContent := ` - - john - 100 - ` + xmlContent := []byte(` + + + john + 100 + +`) j, _ := gjson.LoadXml(xmlContent) fmt.Println(j.Get("base.name")) fmt.Println(j.Get("base.score")) @@ -55,11 +57,11 @@ func ExampleLoadXml() { } func ExampleLoadIni() { - iniContent := ` - [base] - name = john - score = 100 - ` + iniContent := []byte(` +[base] +name = john +score = 100 +`) j, _ := gjson.LoadIni(iniContent) fmt.Println(j.Get("base.name")) fmt.Println(j.Get("base.score")) @@ -70,10 +72,11 @@ func ExampleLoadIni() { } func ExampleLoadYaml() { - yamlContent := - `base: + yamlContent := []byte(` +base: name: john - score: 100` + score: 100 +`) j, _ := gjson.LoadYaml(yamlContent) fmt.Println(j.Get("base.name")) @@ -85,10 +88,11 @@ func ExampleLoadYaml() { } func ExampleLoadToml() { - tomlContent := - `[base] + tomlContent := []byte(` +[base] name = "john" - score = 100` + score = 100 +`) j, _ := gjson.LoadToml(tomlContent) fmt.Println(j.Get("base.name")) @@ -100,7 +104,7 @@ func ExampleLoadToml() { } func ExampleLoadContent() { - jsonContent := `{"name":"john", "score":"100"}` + jsonContent := []byte(`{"name":"john", "score":"100"}`) j, _ := gjson.LoadContent(jsonContent) @@ -132,11 +136,13 @@ func ExampleLoadContent_UTF8BOM() { } func ExampleLoadContent_Xml() { - xmlContent := ` - - john - 100 - ` + xmlContent := []byte(` + + + john + 100 + +`) x, _ := gjson.LoadContent(xmlContent) @@ -149,16 +155,20 @@ func ExampleLoadContent_Xml() { } func ExampleLoadContentType() { - jsonContent := `{"name":"john", "score":"100"}` - xmlContent := ` - - john - 100 - ` + var ( + jsonContent = []byte(`{"name":"john", "score":"100"}`) + xmlContent = []byte(` + + + john + 100 + +`) + ) j, _ := gjson.LoadContentType("json", jsonContent) x, _ := gjson.LoadContentType("xml", xmlContent) - j1, _ := gjson.LoadContentType("json", "") + j1, _ := gjson.LoadContentType("json", []byte("")) fmt.Println(j.Get("name")) fmt.Println(j.Get("score")) diff --git a/encoding/gjson/gjson_z_example_pattern_test.go b/encoding/gjson/gjson_z_example_pattern_test.go index db5f1308a..020d7bff7 100644 --- a/encoding/gjson/gjson_z_example_pattern_test.go +++ b/encoding/gjson/gjson_z_example_pattern_test.go @@ -51,7 +51,7 @@ func ExampleDecodeToJson_PatternViolenceCheck() { } func ExampleJson_Get_MapSliceChange() { - jsonContent := `{"map":{"key":"value"}, "slice":[59,90]}` + jsonContent := []byte(`{"map":{"key":"value"}, "slice":[59,90]}`) j, _ := gjson.LoadJson(jsonContent) m := j.Get("map").Map() fmt.Println(m) diff --git a/encoding/gjson/gjson_z_example_test.go b/encoding/gjson/gjson_z_example_test.go index d262be3ce..3e6c45f3f 100644 --- a/encoding/gjson/gjson_z_example_test.go +++ b/encoding/gjson/gjson_z_example_test.go @@ -871,13 +871,14 @@ func ExampleJson_IsNil() { } func ExampleJson_Get() { - data := - `{ - "users" : { - "count" : 1, - "array" : ["John", "Ming"] - } - }` + data := []byte(` +{ + "users" : { + "count" : 1, + "array" : ["John", "Ming"] + } +} +`) j, _ := gjson.LoadContent(data) fmt.Println(j.Get(".")) @@ -896,13 +897,14 @@ func ExampleJson_Get() { } func ExampleJson_GetJson() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "array" : ["John", "Ming"] } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -913,13 +915,14 @@ func ExampleJson_GetJson() { } func ExampleJson_GetJsons() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 3, "array" : [{"Age":18,"Name":"John"}, {"Age":20,"Name":"Tom"}] } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -934,16 +937,17 @@ func ExampleJson_GetJsons() { } func ExampleJson_GetJsonMap() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "array" : { "info" : {"Age":18,"Name":"John"}, "addr" : {"City":"Chengdu","Company":"Tencent"} } } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -1056,9 +1060,9 @@ func ExampleJson_Contains() { } func ExampleJson_Len() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "nameArray" : ["Join", "Tom"], "infoMap" : { @@ -1067,7 +1071,8 @@ func ExampleJson_Len() { "addr" : "ChengDu" } } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -1080,13 +1085,14 @@ func ExampleJson_Len() { } func ExampleJson_Append() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "array" : ["John", "Ming"] } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -1099,13 +1105,14 @@ func ExampleJson_Append() { } func ExampleJson_MustAppend() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "array" : ["John", "Ming"] } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -1118,9 +1125,9 @@ func ExampleJson_MustAppend() { } func ExampleJson_Map() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "info" : { "name" : "John", @@ -1128,7 +1135,8 @@ func ExampleJson_Map() { "addr" : "ChengDu" } } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -1139,13 +1147,14 @@ func ExampleJson_Map() { } func ExampleJson_Array() { - data := - `{ - "users" : { + data := []byte(` +{ + "users" : { "count" : 1, "array" : ["John", "Ming"] } - }` + } +`) j, _ := gjson.LoadContent(data) @@ -1156,7 +1165,7 @@ func ExampleJson_Array() { } func ExampleJson_Scan() { - data := `{"name":"john","age":"18"}` + data := []byte(`{"name":"john","age":"18"}`) type BaseInfo struct { Name string @@ -1175,7 +1184,7 @@ func ExampleJson_Scan() { } func ExampleJson_Dump() { - data := `{"name":"john","age":"18"}` + data := []byte(`{"name":"john","age":"18"}`) j, _ := gjson.LoadContent(data) j.Dump() diff --git a/encoding/gjson/gjson_z_unit_feature_json_test.go b/encoding/gjson/gjson_z_unit_feature_json_test.go index 5e3cd3024..542b8e795 100644 --- a/encoding/gjson/gjson_z_unit_feature_json_test.go +++ b/encoding/gjson/gjson_z_unit_feature_json_test.go @@ -49,11 +49,11 @@ func Test_ToJson(t *testing.T) { } func Test_MapAttributeConvert(t *testing.T) { - var data = ` - { + var data = []byte(` +{ "title": {"l1":"标签1","l2":"标签2"} } -` +`) gtest.C(t, func(t *gtest.T) { j, err := gjson.LoadContent(data) gtest.AssertNil(err) diff --git a/encoding/gjson/gjson_z_unit_feature_load_test.go b/encoding/gjson/gjson_z_unit_feature_load_test.go index 51f9a2d8b..4a1f5e098 100644 --- a/encoding/gjson/gjson_z_unit_feature_load_test.go +++ b/encoding/gjson/gjson_z_unit_feature_load_test.go @@ -105,7 +105,8 @@ func Test_Load_XML(t *testing.T) { // XML gtest.C(t, func(t *gtest.T) { - xml := ` + xml := []byte(` + 0 @@ -114,7 +115,8 @@ func Test_Load_XML(t *testing.T) { GF框架 - ` + +`) j, err := gjson.LoadContent(xml) t.AssertNil(err) t.Assert(j.Get("Output.ipageIndex"), "2") @@ -250,10 +252,10 @@ func Test_Load_Basic(t *testing.T) { t.AssertNil(err) t.Assert(j.Interface(), nil) - j, err = gjson.LoadContent(`{"name": "gf"}`) + j, err = gjson.LoadContent([]byte(`{"name": "gf"}`)) t.AssertNil(err) - j, err = gjson.LoadContent(`{"name": "gf"""}`) + j, err = gjson.LoadContent([]byte(`{"name": "gf"""}`)) t.AssertNE(err, nil) j = gjson.New(&g.Map{"name": "gf"}) @@ -263,7 +265,7 @@ func Test_Load_Basic(t *testing.T) { } func Test_Load_Ini(t *testing.T) { - var data = ` + var data = []byte(` ;注释 @@ -277,7 +279,7 @@ enable=true user=root password=password -` +`) gtest.C(t, func(t *gtest.T) { j, err := gjson.LoadContent(data) @@ -320,7 +322,7 @@ enable=true } func Test_Load_YamlWithV3(t *testing.T) { - content := ` + content := []byte(` # CLI tool, only in development environment. # https://goframe.org/pages/viewpage.action?pageId=3673173 gfcli: @@ -355,7 +357,7 @@ gfcli: noModelComment : true overwriteDao : true modelFileForDao : "model_dao.go" -` +`) gtest.C(t, func(t *gtest.T) { _, err := gjson.LoadContent(content) t.AssertNil(err) @@ -363,7 +365,7 @@ gfcli: } func Test_Load_Properties(t *testing.T) { - var data = ` + var data = []byte(` #注释 @@ -375,7 +377,7 @@ DBINFO.type=mysql DBINFO.user=root DBINFO.password=password -` +`) gtest.C(t, func(t *gtest.T) { j, err := gjson.LoadContent(data) diff --git a/encoding/gjson/gjson_z_unit_feature_struct_test.go b/encoding/gjson/gjson_z_unit_feature_struct_test.go index 49f7c0a4a..df13c1b98 100644 --- a/encoding/gjson/gjson_z_unit_feature_struct_test.go +++ b/encoding/gjson/gjson_z_unit_feature_struct_test.go @@ -138,7 +138,7 @@ func Test_Struct1(t *testing.T) { type UserCollectionAddReq struct { BaseInfo []BaseInfoItem `db:"_" json:"baseInfo" field:"_"` } - jsonContent := `{ + jsonContent := []byte(`{ "baseInfo": [{ "idCardNumber": "520101199412141111", "isHouseholder": true, @@ -195,7 +195,8 @@ func Test_Struct1(t *testing.T) { "incomeInfo": [], "liabilityInfo": [] }] -}` +} +`) data := new(UserCollectionAddReq) j, err := gjson.LoadJson(jsonContent, true) t.AssertNil(err) @@ -218,12 +219,14 @@ func Test_Struct(t *testing.T) { Items []*Item `json:"items"` } - txt := `{ - "id":"88888", - "me":{"name":"mikey","day":"20009"}, - "txt":"hello", - "items":null - }` + txt := []byte(` +{ + "id":"88888", + "me":{"name":"mikey","day":"20009"}, + "txt":"hello", + "items":null +} +`) j, err := gjson.LoadContent(txt) t.AssertNil(err) @@ -281,13 +284,15 @@ func Test_Struct_Complicated(t *testing.T) { } gtest.C(t, func(t *gtest.T) { - jsonContent := `{ + jsonContent := []byte(` +{ "certList":[ {"certId":"2023313","certInfo":"{\"address\":\"xxxxxxx\",\"phoneNumber\":\"15084890\",\"companyName\":\"dddd\",\"communityCreditCode\":\"91110111MBE1G2B\",\"operateRange\":\"fff\",\"registerNo\":\"91110111MA00G2B\",\"legalPersonName\":\"rrr\"}","srcType":"1","statusCode":"2"}, {"certId":"2023314","certInfo":"{\"identNo\":\"342224196507051\",\"userRealname\":\"xxxx\",\"identType\":\"01\"}","srcType":"8","statusCode":"0"}, {"certId":"2023322","certInfo":"{\"businessLicense\":\"91110111MA00BE1G\",\"companyName\":\"sssss\",\"communityCreditCode\":\"91110111MA00BE1\"}","srcType":"2","statusCode":"0"} ] -}` +} +`) j, err := gjson.LoadContent(jsonContent) t.AssertNil(err) var response = new(Response) diff --git a/encoding/gjson/gjson_z_unit_internal_test.go b/encoding/gjson/gjson_z_unit_internal_test.go index 853b839c0..118096823 100644 --- a/encoding/gjson/gjson_z_unit_internal_test.go +++ b/encoding/gjson/gjson_z_unit_internal_test.go @@ -18,7 +18,9 @@ func Test_checkDataType(t *testing.T) { bb = """ dig := dig; END;""" `) - t.Assert(checkDataType(data), "toml") + dataType, err := checkDataType(data) + t.AssertNil(err) + t.Assert(dataType, "toml") }) gtest.C(t, func(t *gtest.T) { @@ -32,7 +34,9 @@ dd = 11 disk = "127.0.0.1:6379,0" cache = "127.0.0.1:6379,1" `) - t.Assert(checkDataType(data), "toml") + dataType, err := checkDataType(data) + t.AssertNil(err) + t.Assert(dataType, "toml") }) gtest.C(t, func(t *gtest.T) { @@ -86,7 +90,9 @@ dd = 11 // fmt.Println(gregex.IsMatch(`[\s\t\n\r]+[\w\-]+\s*:\s*".+"`, data)) // fmt.Println(gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, data)) // fmt.Println(gregex.MatchString(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, string(data))) - t.Assert(checkDataType(data), "toml") + dataType, err := checkDataType(data) + t.AssertNil(err) + t.Assert(dataType, "toml") }) gtest.C(t, func(t *gtest.T) { @@ -111,7 +117,9 @@ k8s-inner-api = http://127.0.0.1:8081/kube/add conf_dir = ./config app_conf = ./config/app.ini `) - t.Assert(checkDataType(data), "ini") + dataType, err := checkDataType(data) + t.AssertNil(err) + t.Assert(dataType, "ini") }) gtest.C(t, func(t *gtest.T) { @@ -129,6 +137,8 @@ wget http://consul.infra:8500/v1/kv/app_{{.SwimlaneName}}/{{.RepoName}}/.env.qa? npm run build:qa """ `) - t.Assert(checkDataType(data), "toml") + dataType, err := checkDataType(data) + t.AssertNil(err) + t.Assert(dataType, "toml") }) } diff --git a/encoding/gxml/gxml.go b/encoding/gxml/gxml.go index 2b462de2d..f28d3dbc4 100644 --- a/encoding/gxml/gxml.go +++ b/encoding/gxml/gxml.go @@ -49,6 +49,27 @@ func DecodeWithoutRoot(content []byte) (map[string]interface{}, error) { return m, nil } +// XMLEscapeChars forces escaping invalid characters in attribute and element values. +// NOTE: this is brute force with NO interrogation of '&' being escaped already; if it is +// then '&' will be re-escaped as '&amp;'. +// +/* + The values are: + " " + ' ' + < < + > > + & & +*/ +// +// Note: if XMLEscapeCharsDecoder(true) has been called - or the default, 'false,' value +// has been toggled to 'true' - then XMLEscapeChars(true) is ignored. If XMLEscapeChars(true) +// has already been called before XMLEscapeCharsDecoder(true), XMLEscapeChars(false) is called +// to turn escape encoding on mv.Xml, etc., to prevent double escaping ampersands, '&'. +func XMLEscapeChars(b ...bool) { + mxj.XMLEscapeChars(b...) +} + // Encode encodes map `m` to an XML format content as bytes. // The optional parameter `rootTag` is used to specify the XML root tag. func Encode(m map[string]interface{}, rootTag ...string) ([]byte, error) { diff --git a/encoding/gxml/gxml_z_unit_test.go b/encoding/gxml/gxml_z_unit_test.go index 28a8a993f..e519cda81 100644 --- a/encoding/gxml/gxml_z_unit_test.go +++ b/encoding/gxml/gxml_z_unit_test.go @@ -206,3 +206,28 @@ func TestErrCase(t *testing.T) { } }) } + +func Test_Issue3716(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + xml = `I am a software developer & I love coding.john.doe@example.com<>&'"AAA` + m = map[string]interface{}{ + "Person": map[string]interface{}{ + "Name": "<>&'\"AAA", + "Email": "john.doe@example.com", + "Bio": "I am a software developer & I love coding.", + }, + } + ) + gxml.XMLEscapeChars(true) + defer gxml.XMLEscapeChars(false) + + xb, err := gxml.Encode(m) + t.AssertNil(err) + t.Assert(string(xb), xml) + + dm, err := gxml.Decode(xb) + t.AssertNil(err) + t.Assert(dm, m) + }) +} diff --git a/errors/gcode/gcode.go b/errors/gcode/gcode.go index b3bb1b379..bbbf0e875 100644 --- a/errors/gcode/gcode.go +++ b/errors/gcode/gcode.go @@ -46,7 +46,7 @@ var ( CodeNotFound = localCode{65, "Not Found", nil} // Resource does not exist. CodeInvalidRequest = localCode{66, "Invalid Request", nil} // Invalid request. CodeNecessaryPackageNotImport = localCode{67, "Necessary Package Not Import", nil} // It needs necessary package import. - CodeInternalPanic = localCode{68, "Internal Panic", nil} // An panic occurred internally. + CodeInternalPanic = localCode{68, "Internal Panic", nil} // A panic occurred internally. CodeBusinessValidationFailed = localCode{300, "Business Validation Failed", nil} // Business validation failed. ) diff --git a/errors/gerror/gerror_z_example_test.go b/errors/gerror/gerror_z_example_test.go index 6d828abbd..a0af3762f 100644 --- a/errors/gerror/gerror_z_example_test.go +++ b/errors/gerror/gerror_z_example_test.go @@ -82,3 +82,25 @@ func ExampleIs() { // true // false } + +func ExampleCode() { + err1 := gerror.NewCode(gcode.CodeInternalError, "permission denied") + err2 := gerror.Wrap(err1, "operation failed") + fmt.Println(gerror.Code(err1)) + fmt.Println(gerror.Code(err2)) + + // Output: + // 50:Internal Error + // 50:Internal Error +} + +func ExampleHasCode() { + err1 := gerror.NewCode(gcode.CodeInternalError, "permission denied") + err2 := gerror.Wrap(err1, "operation failed") + fmt.Println(gerror.HasCode(err1, gcode.CodeOK)) + fmt.Println(gerror.HasCode(err2, gcode.CodeInternalError)) + + // Output: + // false + // true +} diff --git a/example/go.mod b/example/go.mod index 4e530f7d0..7a992faf2 100644 --- a/example/go.mod +++ b/example/go.mod @@ -1,61 +1,72 @@ module github.com/gogf/gf/example -go 1.18 +go 1.21 require ( - github.com/gogf/gf/contrib/config/apollo/v2 v2.7.2 - github.com/gogf/gf/contrib/config/consul/v2 v2.7.2 - github.com/gogf/gf/contrib/config/kubecm/v2 v2.7.2 - github.com/gogf/gf/contrib/config/nacos/v2 v2.7.2 - github.com/gogf/gf/contrib/config/polaris/v2 v2.7.2 - github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.2 - github.com/gogf/gf/contrib/metric/otelmetric/v2 v2.7.2 - github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2 - github.com/gogf/gf/contrib/registry/etcd/v2 v2.7.2 - github.com/gogf/gf/contrib/registry/file/v2 v2.7.2 - github.com/gogf/gf/contrib/registry/nacos/v2 v2.7.2 - github.com/gogf/gf/contrib/registry/polaris/v2 v2.7.2 - github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.7.2 - github.com/gogf/gf/contrib/trace/otlpgrpc/v2 v2.7.2 - github.com/gogf/gf/contrib/trace/otlphttp/v2 v2.7.2 - github.com/gogf/gf/v2 v2.7.2 + github.com/gogf/gf/contrib/config/apollo/v2 v2.8.1 + github.com/gogf/gf/contrib/config/consul/v2 v2.8.1 + github.com/gogf/gf/contrib/config/kubecm/v2 v2.8.1 + github.com/gogf/gf/contrib/config/nacos/v2 v2.8.1 + github.com/gogf/gf/contrib/config/polaris/v2 v2.8.1 + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.1 + github.com/gogf/gf/contrib/metric/otelmetric/v2 v2.8.1 + github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.1 + github.com/gogf/gf/contrib/registry/etcd/v2 v2.8.1 + github.com/gogf/gf/contrib/registry/file/v2 v2.8.1 + github.com/gogf/gf/contrib/registry/nacos/v2 v2.8.1 + github.com/gogf/gf/contrib/registry/polaris/v2 v2.8.1 + github.com/gogf/gf/contrib/rpc/grpcx/v2 v2.8.1 + github.com/gogf/gf/contrib/trace/otlpgrpc/v2 v2.8.1 + github.com/gogf/gf/contrib/trace/otlphttp/v2 v2.8.1 + github.com/gogf/gf/v2 v2.8.1 github.com/hashicorp/consul/api v1.24.0 github.com/hashicorp/go-cleanhttp v0.5.2 - github.com/nacos-group/nacos-sdk-go/v2 v2.2.5 - github.com/polarismesh/polaris-go v1.5.5 - github.com/prometheus/client_golang v1.19.0 + github.com/nacos-group/nacos-sdk-go/v2 v2.2.7 + github.com/polarismesh/polaris-go v1.5.8 + github.com/prometheus/client_golang v1.20.2 + go.opentelemetry.io/otel v1.29.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 go.opentelemetry.io/otel/exporters/prometheus v0.46.0 - golang.org/x/time v0.5.0 - google.golang.org/grpc v1.60.1 - google.golang.org/protobuf v1.32.0 + go.opentelemetry.io/otel/sdk v1.29.0 + golang.org/x/time v0.6.0 + google.golang.org/grpc v1.67.1 + google.golang.org/protobuf v1.34.2 k8s.io/client-go v0.27.4 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect - github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect - github.com/alibabacloud-go/tea v1.1.17 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect + github.com/alibabacloud-go/darabonba-encode-util v0.0.2 // indirect + github.com/alibabacloud-go/darabonba-map v0.0.2 // indirect + github.com/alibabacloud-go/darabonba-string v1.0.2 // indirect + github.com/alibabacloud-go/debug v1.0.1 // indirect + github.com/alibabacloud-go/openapi-util v0.1.0 // indirect + github.com/alibabacloud-go/tea v1.2.2 // indirect github.com/alibabacloud-go/tea-utils v1.4.4 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.62.719 // indirect - github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2 // indirect - github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.7 // indirect + github.com/alibabacloud-go/tea-utils/v2 v2.0.3 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.63.7 // indirect + github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 // indirect + github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.9 // indirect github.com/apolloconfig/agollo/v4 v4.3.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dlclark/regexp2 v1.11.2 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect @@ -63,14 +74,14 @@ require ( github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -82,13 +93,13 @@ require ( github.com/imdario/mergo v0.3.6 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -99,12 +110,12 @@ require ( github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/pelletier/go-toml v1.9.3 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/polarismesh/specification v1.4.1 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/polarismesh/specification v1.5.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cast v1.3.1 // indirect @@ -112,34 +123,27 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.8.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect go.etcd.io/etcd/api/v3 v3.5.7 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect go.etcd.io/etcd/client/v3 v3.5.7 // indirect go.opentelemetry.io/contrib/instrumentation/runtime v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/multierr v1.11.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/example/go.sum b/example/go.sum index 7e6a37b3a..ccada6a1c 100644 --- a/example/go.sum +++ b/example/go.sum @@ -169,8 +169,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= @@ -183,20 +183,39 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 h1:NqugFkGxx1TXSh/pBcU00Y6bljgDPaFdh5MUSeJ7e50= +github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= +github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= +github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8= +github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc= +github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= +github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= +github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= +github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg= +github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= +github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY= +github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg= -github.com/alibabacloud-go/tea v1.1.17 h1:05R5DnaJXe9sCNIe8KUgWHC/z6w/VZIwczgUwzRnul8= +github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= +github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA= +github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU= +github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= +github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= github.com/alibabacloud-go/tea-utils v1.4.4 h1:lxCDvNCdTo9FaXKKq45+4vGETQUKNOW/qKTcX9Sk53o= github.com/alibabacloud-go/tea-utils v1.4.4/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw= +github.com/alibabacloud-go/tea-utils/v2 v2.0.3 h1:6OM8vm/6pjQg1a7zc3QNMviaoumnhImRi5V84CnuFkc= +github.com/alibabacloud-go/tea-utils/v2 v2.0.3/go.mod h1:sj1PbjPodAVTqGTA3olprfeeqqmwD0A5OQz94o9EuXQ= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1800/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.719 h1:ZYBHflrrLzobuUZ7RE1MZYskFFVx0JtpkIURmOJFCG8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.719/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= -github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2 h1:rWkH6D2XlXb/Y+tNAQROxBzp3a0p92ni+pXcaHBe/WI= -github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.2.2/go.mod h1:GDtq+Kw+v0fO+j5BrrWiUHbBq7L+hfpzpPfXKOZMFE0= -github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.7 h1:olLiPI2iM8Hqq6vKnSxpM3awCrm9/BeOgHpzQkOYnI4= -github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.7/go.mod h1:oDg1j4kFxnhgftaiLJABkGeSvuEvSF5Lo6UmRAMruX4= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.7 h1:MOFLOVlBI1MvP4I0cwb9cXf83GNcMss1btQqjbp11CM= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.7/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= +github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 h1:nJYyoFP+aqGKgPs9JeZgS1rWQ4NndNR0Zfhh161ZltU= +github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1/go.mod h1:WzGOmFFTlUzXM03CJnHWMQ85UN6QGpOXZocCjwkiyOg= +github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.9 h1:GCzdF5XjQ6LED6wdvEq2MKSlBQmQDkvYRw2S8Qnbo4Y= +github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.9/go.mod h1:xP0KIZry6i7oGPF24vhAPr1Q8vLZRcMcxtft5xDKwCU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apolloconfig/agollo/v4 v4.3.1 h1:NHjd7KqOPmTvYwJidISc9MPBRO8m9UNrH3tijcEVNAY= github.com/apolloconfig/agollo/v4 v4.3.1/go.mod h1:n/7qxpKOTbegygLmO5OKmFWCdy3T+S/zioBGlo457Dk= @@ -214,17 +233,19 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/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= @@ -253,8 +274,9 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.2 h1:/u628IuisSTwri5/UKloiIsH8+qF2Pu7xEQX+yIKg68= +github.com/dlclark/regexp2 v1.11.2/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -273,8 +295,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -291,8 +313,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -305,6 +327,7 @@ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrt github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -342,8 +365,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= @@ -355,6 +378,7 @@ github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4g github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -398,8 +422,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -413,18 +437,19 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.24.0 h1:u2XyStA2j0jnCiVUU7Qyrt8idjRn4ORhK6DlvZ3bWhA= github.com/hashicorp/consul/api v1.24.0/go.mod h1:NZJGRFYruc/80wYowkPFCp1LbGmJC9L8izrwfyVx/Wg= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= +github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -439,6 +464,7 @@ github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -449,11 +475,14 @@ github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5O github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -481,8 +510,6 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288 h1:GuL6co0J2oMb2Rd/hbxZfJz1QlZr+DpIsz3Wcvok65o= -github.com/joy999/nacos-sdk-go v0.0.0-20231120071639-10a34b3e7288/go.mod h1:xF3RcNkFUEIik3RCihkvgORtZXZXlp+OeGK0aUALVYU= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -500,6 +527,8 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -508,10 +537,13 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -533,8 +565,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= @@ -564,15 +596,17 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nacos-group/nacos-sdk-go/v2 v2.2.5 h1:r0wwT7PayEjvEHzWXwr1ROi/JSqzujM4w+1L5ikThzQ= -github.com/nacos-group/nacos-sdk-go/v2 v2.2.5/go.mod h1:OObBon0prVJVPoIbSZxpEkFiBfL0d1LcBtuAMiNn+8c= +github.com/nacos-group/nacos-sdk-go/v2 v2.2.7 h1:wCC1f3/VzIR1WD30YKeJGZAOchYCK/35mLC8qWt6Q6o= +github.com/nacos-group/nacos-sdk-go/v2 v2.2.7/go.mod h1:VYlyDPlQchPC31PmfBustu81vsOkdpCuO5k0dRdQcFc= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= +github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -587,10 +621,12 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/polarismesh/polaris-go v1.5.5 h1:TUxgla21J9Zb3zSynoAA9og0+sYJZ7TpZ2aFwzH7woI= -github.com/polarismesh/polaris-go v1.5.5/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c= -github.com/polarismesh/specification v1.4.1 h1:lTZqeyUhhWuKyr6NDKBwmUrNfcUDvKLxWT/uOq71T5A= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polarismesh/polaris-go v1.5.8 h1:zBZkZBa4wVxsG5Y/6U4PmY9dY/mddXdfNI65edVu6U8= +github.com/polarismesh/polaris-go v1.5.8/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c= github.com/polarismesh/specification v1.4.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU= +github.com/polarismesh/specification v1.5.1 h1:cJ2m0RBepdopGo/e3UpKdsab3NpDZnw5IsVTB1sFc5I= +github.com/polarismesh/specification v1.5.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -599,37 +635,38 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= +github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -672,11 +709,15 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0= github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k= +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -684,6 +725,7 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -706,36 +748,37 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib/instrumentation/runtime v0.49.0 h1:dg9y+7ArpumB6zwImJv47RHfdgOGQ1EMkzP5vLkEnTU= go.opentelemetry.io/contrib/instrumentation/runtime v0.49.0/go.mod h1:Ul4MtXqu/hJBM+v7a6dCF0nHwckPMLpIpLeCi4+zfdw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc= go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= -go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -748,11 +791,15 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -795,6 +842,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -826,6 +874,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -848,8 +897,13 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -874,8 +928,8 @@ golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7Lm golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -889,8 +943,9 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -924,6 +979,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -975,14 +1031,22 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -992,15 +1056,18 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1040,6 +1107,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -1060,7 +1128,9 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 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= @@ -1126,8 +1196,6 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1227,12 +1295,10 @@ google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1268,8 +1334,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1286,8 +1352,9 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/example/trace/README.MD b/example/trace/README.MD new file mode 100644 index 000000000..3fc728b3d --- /dev/null +++ b/example/trace/README.MD @@ -0,0 +1,80 @@ +# OpenTelemetry Protocol (stable) + +Since v1.35, the Jaeger backend can receive trace data from the OpenTelemetry SDKs in their native OpenTelemetry Protocol (OTLP)  . It is no longer necessary to configure the OpenTelemetry SDKs with Jaeger exporters, nor deploy the OpenTelemetry Collector between the OpenTelemetry SDKs and the Jaeger backend. + +The OTLP data is accepted in these formats: (1) binary gRPC, (2) Protobuf over HTTP, (3) JSON over HTTP. For more details on the OTLP receiver see the official documentation  . Note that not all configuration options are supported in jaeger-collector (see --collector.otlp.* CLI Flags ), and only tracing data is accepted, since Jaeger does not store other telemetry types. + +|Port |Protocol |Endpoint |Format| +|---|---|---|---| +|4317 |gRPC |n/a |Protobuf| +|4318 |HTTP |/v1/traces |Protobuf or JSON| + +Two ports, 4317 and 4318, have also been added to the export list, which are used by OTLP receivers to listen for gRPC and HTTP connections. + +## All in One +all-in-one is an executable designed for quick local testing. It includes the Jaeger UI, jaeger-collector, jaeger-query, and jaeger-agent, with an in memory storage component. + +The simplest way to start the all-in-one is to use the pre-built image published to DockerHub (a single command line). + +```shell +docker run --rm --name jaeger \ + -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ + -p 6831:6831/udp \ + -p 6832:6832/udp \ + -p 5778:5778 \ + -p 16686:16686 \ + -p 4317:4317 \ + -p 4318:4318 \ + -p 14250:14250 \ + -p 14268:14268 \ + -p 14269:14269 \ + -p 9411:9411 \ + jaegertracing/all-in-one:1.55 + +``` + +Or run the `jaeger-all-in-one(.exe)` executable from the [binary distribution archives][download]: + +```bash +jaeger-all-in-one --collector.zipkin.host-port=:9411 +``` + +You can then navigate to `http://localhost:16686` to access the Jaeger UI. + +The container exposes the following ports: + +Port | Protocol | Component | Function +----- | ------- | --------- | --- +6831 | UDP | agent | accept `jaeger.thrift` over Thrift-compact protocol (used by most SDKs) +6832 | UDP | agent | accept `jaeger.thrift` over Thrift-binary protocol (used by Node.js SDK) +5775 | UDP | agent | (deprecated) accept `zipkin.thrift` over compact Thrift protocol (used by legacy clients only) +5778 | HTTP | agent | serve configs (sampling, etc.) +16686 | HTTP | query | serve frontend +4317 | HTTP | collector | accept OpenTelemetry Protocol (OTLP) over gRPC +4318 | HTTP | collector | accept OpenTelemetry Protocol (OTLP) over HTTP +14268 | HTTP | collector | accept `jaeger.thrift` directly from clients +14250 | HTTP | collector | accept `model.proto` +9411 | HTTP | collector | Zipkin compatible endpoint (optional) + +https://www.jaegertracing.io/docs/1.55/apis/#opentelemetry-protocol-stable + +Read more details: + +Introducing native support for OpenTelemetry in Jaeger + +https://medium.com/jaegertracing/introducing-native-support-for-opentelemetry-in-jaeger-eb661be8183c + +Better alignment with OpenTelemetry by focusing on OTLP + +https://medium.com/jaegertracing/better-alignment-with-opentelemetry-by-focusing-on-otlp-f3688939073f + + + +# Jaeger + +Open Source, End-to-End Distributed Tracing. Hosted by Cloud Native Computing Foundation. + +https://medium.com/jaegertracing + + +## For more information on distributed tracing initialization, please refer to the content in the [provider](./provider) directory \ No newline at end of file diff --git a/example/trace/grpc-with-db/client/client.go b/example/trace/grpc-with-db/client/client.go index ea0b754f5..22823eca9 100644 --- a/example/trace/grpc-with-db/client/client.go +++ b/example/trace/grpc-with-db/client/client.go @@ -25,12 +25,15 @@ const ( func main() { grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) - var ctx = gctx.New() - shutdown, err := otlpgrpc.Init(serviceName, endpoint, traceToken) + var ( + ctx = gctx.New() + shutdown, err = otlpgrpc.Init(serviceName, endpoint, traceToken) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) StartRequests() } diff --git a/example/trace/grpc-with-db/server/server.go b/example/trace/grpc-with-db/server/server.go index 286890d55..6ef4d3a3c 100644 --- a/example/trace/grpc-with-db/server/server.go +++ b/example/trace/grpc-with-db/server/server.go @@ -38,12 +38,15 @@ const ( func main() { grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) - var ctx = gctx.New() - shutdown, err := otlpgrpc.Init(serviceName, endpoint, traceToken) + var ( + ctx = gctx.New() + shutdown, err = otlpgrpc.Init(serviceName, endpoint, traceToken) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) // Set ORM cache adapter with redis. g.DB().GetCache().SetAdapter(gcache.NewAdapterRedis(g.Redis())) diff --git a/example/trace/http-with-db/client/client.go b/example/trace/http-with-db/client/client.go index c4f4ec5ae..24afdcc70 100644 --- a/example/trace/http-with-db/client/client.go +++ b/example/trace/http-with-db/client/client.go @@ -22,12 +22,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlphttp.Init(serviceName, endpoint, path) + var ( + ctx = gctx.New() + shutdown, err = otlphttp.Init(serviceName, endpoint, path) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) StartRequests() } diff --git a/example/trace/http-with-db/server/server.go b/example/trace/http-with-db/server/server.go index f754f0ea5..fd31dba16 100644 --- a/example/trace/http-with-db/server/server.go +++ b/example/trace/http-with-db/server/server.go @@ -29,12 +29,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlphttp.Init(serviceName, endpoint, path) + var ( + ctx = gctx.New() + shutdown, err = otlphttp.Init(serviceName, endpoint, path) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) // Set ORM cache adapter with redis. g.DB().GetCache().SetAdapter(gcache.NewAdapterRedis(g.Redis())) diff --git a/example/trace/http/client/client.go b/example/trace/http/client/client.go index 84abb05fd..d09226075 100644 --- a/example/trace/http/client/client.go +++ b/example/trace/http/client/client.go @@ -20,12 +20,14 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlphttp.Init(serviceName, endpoint, path) + var ( + ctx = gctx.New() + shutdown, err = otlphttp.Init(serviceName, endpoint, path) + ) if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) StartRequests() } diff --git a/example/trace/http/server/server.go b/example/trace/http/server/server.go index 975dc27e7..2616df9cd 100644 --- a/example/trace/http/server/server.go +++ b/example/trace/http/server/server.go @@ -21,12 +21,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlphttp.Init(serviceName, endpoint, path) + var ( + ctx = gctx.New() + shutdown, err = otlphttp.Init(serviceName, endpoint, path) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) s := g.Server() s.Group("/", func(group *ghttp.RouterGroup) { diff --git a/example/trace/inprocess-grpc/main.go b/example/trace/inprocess-grpc/main.go index 67640ffc5..bf8052ab6 100644 --- a/example/trace/inprocess-grpc/main.go +++ b/example/trace/inprocess-grpc/main.go @@ -23,12 +23,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlpgrpc.Init(serviceName, endpoint, traceToken) + var ( + ctx = gctx.New() + shutdown, err = otlpgrpc.Init(serviceName, endpoint, traceToken) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) ctx, span := gtrace.NewSpan(ctx, "main") defer span.End() diff --git a/example/trace/inprocess/main.go b/example/trace/inprocess/main.go index a6b3849f0..3e603e037 100644 --- a/example/trace/inprocess/main.go +++ b/example/trace/inprocess/main.go @@ -23,12 +23,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlphttp.Init(serviceName, endpoint, path) + var ( + ctx = gctx.New() + shutdown, err = otlphttp.Init(serviceName, endpoint, path) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) ctx, span := gtrace.NewSpan(ctx, "main") defer span.End() diff --git a/example/trace/otlp/grpc/main.go b/example/trace/otlp/grpc/main.go index 224ee5fdc..8703d04b9 100644 --- a/example/trace/otlp/grpc/main.go +++ b/example/trace/otlp/grpc/main.go @@ -21,12 +21,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlpgrpc.Init(serviceName, endpoint, traceToken) + var ( + ctx = gctx.New() + shutdown, err = otlpgrpc.Init(serviceName, endpoint, traceToken) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) StartRequests() } diff --git a/example/trace/otlp/http/main.go b/example/trace/otlp/http/main.go index b1ad9e5fc..4994f882e 100644 --- a/example/trace/otlp/http/main.go +++ b/example/trace/otlp/http/main.go @@ -20,12 +20,15 @@ const ( ) func main() { - var ctx = gctx.New() - shutdown, err := otlphttp.Init(serviceName, endpoint, path) + var ( + ctx = gctx.New() + shutdown, err = otlphttp.Init(serviceName, endpoint, path) + ) + if err != nil { g.Log().Fatal(ctx, err) } - defer shutdown() + defer shutdown(ctx) StartRequests() } diff --git a/example/trace/provider/grpc/main.go b/example/trace/provider/grpc/main.go new file mode 100644 index 000000000..7d5606f1d --- /dev/null +++ b/example/trace/provider/grpc/main.go @@ -0,0 +1,114 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package main provides a simple example for OTLP tracing with gRPC client. +package main + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + "google.golang.org/grpc/encoding/gzip" + + "github.com/gogf/gf/example/trace/provider/internal" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + var ( + serverIP, err = internal.GetLocalIP() + ctx = gctx.New() + ) + if err != nil { + g.Log().Fatal(ctx, err) + } + var res *resource.Resource + if res, err = resource.New(ctx, + // WithFromEnv returns a resource option that sets the resource attributes from the environment. + resource.WithFromEnv(), + // WithProcess returns a resource option that sets the process attributes. + resource.WithProcess(), + // WithTelemetrySDK returns a resource option that sets the telemetry SDK attributes. + resource.WithTelemetrySDK(), + // WithHost returns a resource option that sets the host attributes. + resource.WithHost(), + // WithAttributes returns a resource option that sets the resource attributes. + resource.WithAttributes( + // The name of the service displayed on the traceback end。 + semconv.ServiceNameKey.String(internal.GRPCServiceName), + // The IP address of the server. + semconv.HostNameKey.String(serverIP), + // The IP address of the server. + attribute.String(internal.TracerHostnameTagKey, serverIP), + ), + // WithOS returns a resource option that sets the OS attributes. + resource.WithOS(), + // WithProcessPID returns a resource option that sets the process PID attribute. + resource.WithProcessPID(), + // For more parameters, please customize the selection + ); err != nil { + g.Log().Fatal(ctx, err) + } + + var exporter *otlptrace.Exporter + if exporter, err = otlptrace.New(ctx, otlptracegrpc.NewClient( + // WithInsecure returns an otlptracegrpc.Option that disables transport security for the connection. + otlptracegrpc.WithInsecure(), + // WithEndpoint returns an otlptracegrpc.Option that sets the endpoint to which the exporter is going to send the spans. + otlptracegrpc.WithEndpoint(internal.Endpoint), // Replace the otel Agent Addr with the access point obtained in the prerequisite。 + // WithHeaders returns an otlptracegrpc.Option that sets the headers to be sent with gRPC requests. + otlptracegrpc.WithHeaders(map[string]string{"Authentication": internal.TraceToken}), + // WithCompressor returns an otlptracegrpc.Option that sets the compressor to be used for gRPC requests. + otlptracegrpc.WithCompressor(gzip.Name))); err != nil { + g.Log().Fatal(ctx, err) + } + var shutdown func(ctx context.Context) + // WithSampler sets the sampler for the trace provider. + // 1. AlwaysSample: AlwaysSample is a sampler that samples every trace. + // 2. NeverSample: NeverSample is a sampler that samples no traces. + // 3. ParentBased: ParentBased is a sampler that samples a trace based on the parent span. + // 4. TraceIDRatioBased: TraceIDRatioBased is a sampler that samples a trace based on the TraceID. + // WithResource sets the resource for the trace provider. + // WithSpanProcessor sets the span processor for the trace provider. + // 1. NewSimpleSpanProcessor: NewSimpleSpanProcessor returns a new SimpleSpanProcessor. + // 2. NewBatchSpanProcessor: NewBatchSpanProcessor returns a new BatchSpanProcessor. + // WithRawSpanLimits sets the raw span limits for the trace provider. + if shutdown, err = internal.InitTracer( + // WithSampler returns a trace option that sets the sampler for the trace provider. + // trace.WithSampler(trace.AlwaysSample()), + // trace.WithSampler(trace.NeverSample()), + // trace.WithSampler(trace.ParentBased(trace.AlwaysSample())), + // WithSampler returns a trace option that sets the sampler for the trace provider. + // 1. AlwaysSample: AlwaysSample is a sampler that samples every trace. + // 2. NeverSample: NeverSample is a sampler that samples no traces. + // 3. ParentBased: ParentBased is a sampler that samples a trace based on the parent span. + // 4. TraceIDRatioBased: TraceIDRatioBased is a sampler that samples a trace based on the TraceID. + trace.WithSampler(trace.TraceIDRatioBased(0.1)), + // WithResource returns a trace option that sets the resource for the trace provider. + trace.WithResource(res), + // WithSpanProcessor returns a trace option that sets the span processor for the trace provider. + // trace.WithSpanProcessor(trace.NewSimpleSpanProcessor(exporter)), + // trace.WithSpanProcessor(trace.NewBatchSpanProcessor(exporter)), + // 1. NewSimpleSpanProcessor: NewSimpleSpanProcessor returns a new SimpleSpanProcessor. + // 2. NewBatchSpanProcessor: NewBatchSpanProcessor returns a new BatchSpanProcessor. + trace.WithSpanProcessor(trace.NewBatchSpanProcessor(exporter)), + // WithRawSpanLimits returns a trace option that sets the raw span limits for the trace provider. + trace.WithRawSpanLimits(trace.NewSpanLimits()), + ); err != nil { + g.Log().Fatal(ctx, err) + } + + defer shutdown(ctx) + + internal.StartRequests() +} diff --git a/example/trace/provider/http/main.go b/example/trace/provider/http/main.go new file mode 100644 index 000000000..6f66c7eb9 --- /dev/null +++ b/example/trace/provider/http/main.go @@ -0,0 +1,110 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "context" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + + "github.com/gogf/gf/example/trace/provider/internal" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + var ( + serverIP, err = internal.GetLocalIP() + ctx = gctx.New() + ) + if err != nil { + g.Log().Fatal(ctx, err) + } + var res *resource.Resource + if res, err = resource.New(ctx, + // WithFromEnv returns a resource option that sets the resource attributes from the environment. + resource.WithFromEnv(), + // WithProcess returns a resource option that sets the process attributes. + resource.WithProcess(), + // WithTelemetrySDK returns a resource option that sets the telemetry SDK attributes. + resource.WithTelemetrySDK(), + // WithHost returns a resource option that sets the host attributes. + resource.WithHost(), + // WithAttributes returns a resource option that sets the resource attributes. + resource.WithAttributes( + // The name of the service displayed on the traceback end。 + semconv.ServiceNameKey.String(internal.HTTPServiceName), + // The IP address of the server. + semconv.HostNameKey.String(serverIP), + // The IP address of the server. + attribute.String(internal.TracerHostnameTagKey, serverIP), + ), + // WithOS returns a resource option that sets the OS attributes. + resource.WithOS(), + // WithProcessPID returns a resource option that sets the process PID attribute. + resource.WithProcessPID(), + // For more parameters, please customize the selection + ); err != nil { + g.Log().Fatal(ctx, err) + } + + var exporter *otlptrace.Exporter + if exporter, err = otlptrace.New(ctx, otlptracehttp.NewClient( + // WithEndpoint returns an otlptracehttp.Option that sets the endpoint to which the exporter is going to send the spans. + otlptracehttp.WithEndpoint(internal.HTTPEndpoint), + // WithHeaders returns an otlptracehttp.Option that sets the headers to be sent with HTTP requests. + otlptracehttp.WithURLPath(internal.HTTPPath), + // WithInsecure returns an otlptracehttp.Option that disables secure connection to the collector. + otlptracehttp.WithInsecure(), + // WithCompression returns an otlptracehttp.Option that sets the compression level for the exporter. + otlptracehttp.WithCompression(1))); err != nil { + g.Log().Fatal(ctx, err) + } + var shutdown func(ctx context.Context) + // WithSampler sets the sampler for the trace provider. + // 1. AlwaysSample: AlwaysSample is a sampler that samples every trace. + // 2. NeverSample: NeverSample is a sampler that samples no traces. + // 3. ParentBased: ParentBased is a sampler that samples a trace based on the parent span. + // 4. TraceIDRatioBased: TraceIDRatioBased is a sampler that samples a trace based on the TraceID. + // WithResource sets the resource for the trace provider. + // WithSpanProcessor sets the span processor for the trace provider. + // 1. NewSimpleSpanProcessor: NewSimpleSpanProcessor returns a new SimpleSpanProcessor. + // 2. NewBatchSpanProcessor: NewBatchSpanProcessor returns a new BatchSpanProcessor. + // WithRawSpanLimits sets the raw span limits for the trace provider. + if shutdown, err = internal.InitTracer( + // WithSampler returns a trace option that sets the sampler for the trace provider. + // trace.WithSampler(trace.AlwaysSample()), + // trace.WithSampler(trace.NeverSample()), + // trace.WithSampler(trace.ParentBased(trace.AlwaysSample())), + // WithSampler returns a trace option that sets the sampler for the trace provider. + // 1. AlwaysSample: AlwaysSample is a sampler that samples every trace. + // 2. NeverSample: NeverSample is a sampler that samples no traces. + // 3. ParentBased: ParentBased is a sampler that samples a trace based on the parent span. + // 4. TraceIDRatioBased: TraceIDRatioBased is a sampler that samples a trace based on the TraceID. + trace.WithSampler(trace.TraceIDRatioBased(0.1)), + // WithResource returns a trace option that sets the resource for the trace provider. + trace.WithResource(res), + // WithSpanProcessor returns a trace option that sets the span processor for the trace provider. + // trace.WithSpanProcessor(trace.NewSimpleSpanProcessor(exporter)), + // trace.WithSpanProcessor(trace.NewBatchSpanProcessor(exporter)), + // 1. NewSimpleSpanProcessor: NewSimpleSpanProcessor returns a new SimpleSpanProcessor. + // 2. NewBatchSpanProcessor: NewBatchSpanProcessor returns a new BatchSpanProcessor. + trace.WithSpanProcessor(trace.NewBatchSpanProcessor(exporter)), + // WithRawSpanLimits returns a trace option that sets the raw span limits for the trace provider. + trace.WithRawSpanLimits(trace.NewSpanLimits()), + ); err != nil { + g.Log().Fatal(ctx, err) + } + defer shutdown(ctx) + + internal.StartRequests() +} diff --git a/example/trace/provider/internal/consts.go b/example/trace/provider/internal/consts.go new file mode 100644 index 000000000..153c0720c --- /dev/null +++ b/example/trace/provider/internal/consts.go @@ -0,0 +1,17 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package internal + +const ( + GRPCServiceName = "otlp-grpc-client" + Endpoint = "tracing-analysis-dc-bj.aliyuncs.com:8090" + TraceToken = "******_******" + HTTPServiceName = "otlp-http-client" + HTTPEndpoint = "tracing-analysis-dc-hz.aliyuncs.com" + HTTPPath = "adapt_******_******/api/otlp/traces" + TracerHostnameTagKey = "hostname" +) diff --git a/example/trace/provider/internal/provider.go b/example/trace/provider/internal/provider.go new file mode 100644 index 000000000..f456d8028 --- /dev/null +++ b/example/trace/provider/internal/provider.go @@ -0,0 +1,57 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package internal + +import ( + "context" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/trace" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/gipv4" +) + +// InitTracer initializes and registers `otlpgrpc` or `otlphttp` to global TracerProvider. +func InitTracer(opts ...trace.TracerProviderOption) (func(ctx context.Context), error) { + tracerProvider := trace.NewTracerProvider(opts...) + // Set the global propagator to traceContext (not set by default). + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) + otel.SetTracerProvider(tracerProvider) + + return func(ctx context.Context) { + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + // Shutdown waits for exported trace spans to be uploaded. + if err := tracerProvider.Shutdown(ctx); err != nil { + g.Log().Errorf(ctx, "Shutdown tracerProvider failed err:%+v", err) + } else { + g.Log().Debug(ctx, "Shutdown tracerProvider success") + } + }, nil +} + +// GetLocalIP returns the IP address of the server. +func GetLocalIP() (string, error) { + var intranetIPArray, err = gipv4.GetIntranetIpArray() + if err != nil { + return "", err + } + + if len(intranetIPArray) == 0 { + if intranetIPArray, err = gipv4.GetIpArray(); err != nil { + return "", err + } + } + var hostIP = "NoHostIpFound" + if len(intranetIPArray) > 0 { + hostIP = intranetIPArray[0] + } + return hostIP, nil +} diff --git a/example/trace/provider/internal/request.go b/example/trace/provider/internal/request.go new file mode 100644 index 000000000..d90f72457 --- /dev/null +++ b/example/trace/provider/internal/request.go @@ -0,0 +1,24 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package internal + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/gtrace" + "github.com/gogf/gf/v2/os/gctx" +) + +// StartRequests starts requests. +func StartRequests() { + ctx, span := gtrace.NewSpan(gctx.New(), "StartRequests") + defer span.End() + + ctx = gtrace.SetBaggageValue(ctx, "name", "john") + + content := g.Client().GetContent(ctx, "http://127.0.0.1:8199/hello") + g.Log().Print(ctx, content) +} diff --git a/frame/g/g.go b/frame/g/g.go index 20bf37205..5c196c5cb 100644 --- a/frame/g/g.go +++ b/frame/g/g.go @@ -4,7 +4,10 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package g provides commonly used type/function defines and coupled calling for creating commonly used objects. +// Package g provides commonly used type/function defines and coupled calling for creating commonly-used objects. +// +// Note that, using package g might make the compiled binary a little bit bigger, as it imports a few frequently-used +// packages whatever you use them or not. package g import ( diff --git a/go.mod b/go.mod index 650a4fdae..c03407db6 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,22 @@ module github.com/gogf/gf/v2 -go 1.21 +go 1.22 require ( github.com/BurntSushi/toml v1.4.0 github.com/clbanning/mxj/v2 v2.7.0 github.com/emirpasic/gods v1.18.1 - github.com/fatih/color v1.17.0 + github.com/fatih/color v1.18.0 github.com/fsnotify/fsnotify v1.7.0 github.com/gorilla/websocket v1.5.3 github.com/grokify/html-strip-tags-go v0.1.0 github.com/magiconair/properties v1.8.7 github.com/olekukonko/tablewriter v0.0.5 - go.opentelemetry.io/otel v1.28.0 - go.opentelemetry.io/otel/sdk v1.28.0 - go.opentelemetry.io/otel/trace v1.28.0 - golang.org/x/net v0.27.0 - golang.org/x/text v0.16.0 + go.opentelemetry.io/otel v1.32.0 + go.opentelemetry.io/otel/sdk v1.32.0 + go.opentelemetry.io/otel/trace v1.32.0 + golang.org/x/net v0.31.0 + golang.org/x/text v0.20.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -26,8 +26,8 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/rivo/uniseg v0.4.7 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - golang.org/x/sys v0.22.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + golang.org/x/sys v0.27.0 // indirect ) diff --git a/go.sum b/go.sum index ac69af362..e9ed755b6 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -31,8 +31,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -42,22 +42,22 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/deepcopy/deepcopy_test.go b/internal/deepcopy/deepcopy_test.go index 060001ed7..fa3e4a187 100644 --- a/internal/deepcopy/deepcopy_test.go +++ b/internal/deepcopy/deepcopy_test.go @@ -908,7 +908,7 @@ func TestPointerToStruct(t *testing.T) { } } -func TestIssue9(t *testing.T) { +func Test_Issue9(t *testing.T) { // simple pointer copy x := 42 testA := map[string]*int{ diff --git a/internal/utils/utils_str.go b/internal/utils/utils_str.go index d22245733..9f1089d50 100644 --- a/internal/utils/utils_str.go +++ b/internal/utils/utils_str.go @@ -58,7 +58,10 @@ func IsNumeric(s string) bool { return false } for i := 0; i < length; i++ { - if s[i] == '-' && i == 0 { + if (s[i] == '-' || s[i] == '+') && i == 0 { + if length == 1 { + return false + } continue } if s[i] == '.' { diff --git a/internal/utils/utils_z_unit_test.go b/internal/utils/utils_z_unit_test.go index 259091d5f..8c73eeac1 100644 --- a/internal/utils/utils_z_unit_test.go +++ b/internal/utils/utils_z_unit_test.go @@ -95,3 +95,34 @@ func Test_CanCallIsNil(t *testing.T) { t.Assert(utils.CanCallIsNil(reflect.ValueOf(iUnsafePointer)), true) }) } + +func Test_IsNumeric(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + t.Assert(utils.IsNumeric("12345"), true) + t.Assert(utils.IsNumeric("-12345"), true) + t.Assert(utils.IsNumeric("+12345"), true) + t.Assert(utils.IsNumeric("123.45"), true) + t.Assert(utils.IsNumeric("-123.45"), true) + t.Assert(utils.IsNumeric("+123.45"), true) + t.Assert(utils.IsNumeric("1+23"), false) + t.Assert(utils.IsNumeric("123a45"), false) + t.Assert(utils.IsNumeric("123.45.67"), false) + t.Assert(utils.IsNumeric(""), false) + t.Assert(utils.IsNumeric("1e10"), false) + t.Assert(utils.IsNumeric("123 45"), false) + t.Assert(utils.IsNumeric("!!!"), false) + t.Assert(utils.IsNumeric("-a23"), false) + t.Assert(utils.IsNumeric("+a23"), false) + t.Assert(utils.IsNumeric("1+23"), false) + t.Assert(utils.IsNumeric("1-23"), false) + t.Assert(utils.IsNumeric("123."), false) + t.Assert(utils.IsNumeric(".123"), false) + t.Assert(utils.IsNumeric("123.a"), false) + t.Assert(utils.IsNumeric("a.123"), false) + t.Assert(utils.IsNumeric("+"), false) + t.Assert(utils.IsNumeric("-"), false) + t.Assert(utils.IsNumeric("."), false) + t.Assert(utils.IsNumeric("-."), false) + t.Assert(utils.IsNumeric("+."), false) + }) +} diff --git a/net/gclient/gclient.go b/net/gclient/gclient.go index 44b99e2a3..f15880843 100644 --- a/net/gclient/gclient.go +++ b/net/gclient/gclient.go @@ -84,17 +84,13 @@ func New() *Client { func (c *Client) Clone() *Client { newClient := New() *newClient = *c - if len(c.header) > 0 { - newClient.header = make(map[string]string) - for k, v := range c.header { - newClient.header[k] = v - } + newClient.header = make(map[string]string, len(c.header)) + for k, v := range c.header { + newClient.header[k] = v } - if len(c.cookies) > 0 { - newClient.cookies = make(map[string]string) - for k, v := range c.cookies { - newClient.cookies[k] = v - } + newClient.cookies = make(map[string]string, len(c.cookies)) + for k, v := range c.cookies { + newClient.cookies[k] = v } return newClient } diff --git a/net/gclient/gclient_observability.go b/net/gclient/gclient_observability.go index 6b0323f18..f45efaa8b 100644 --- a/net/gclient/gclient_observability.go +++ b/net/gclient/gclient_observability.go @@ -9,7 +9,6 @@ package gclient import ( "context" "fmt" - "io" "net/http" "net/http/httptrace" @@ -21,7 +20,6 @@ import ( "github.com/gogf/gf/v2" "github.com/gogf/gf/v2/internal/httputil" - "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gmetric" @@ -39,10 +37,8 @@ const ( tracingEventHttpRequest = "http.request" tracingEventHttpRequestHeaders = "http.request.headers" tracingEventHttpRequestBaggage = "http.request.baggage" - tracingEventHttpRequestBody = "http.request.body" tracingEventHttpResponse = "http.response" tracingEventHttpResponseHeaders = "http.response.headers" - tracingEventHttpResponseBody = "http.response.body" tracingMiddlewareHandled gctx.StrKey = `MiddlewareClientTracingHandled` ) @@ -102,17 +98,11 @@ func internalMiddlewareObservability(c *Client, r *http.Request) (response *Resp return } - reqBodyContentBytes, _ := io.ReadAll(response.Body) - response.Body = utils.NewReadCloser(reqBodyContentBytes, false) - - resBodyContent, err := gtrace.SafeContentForHttp(reqBodyContentBytes, response.Header) - if err != nil { - span.SetStatus(codes.Error, fmt.Sprintf(`converting safe content failed: %s`, err.Error())) - } - span.AddEvent(tracingEventHttpResponse, trace.WithAttributes( - attribute.String(tracingEventHttpResponseHeaders, gconv.String(httputil.HeaderToMap(response.Header))), - attribute.String(tracingEventHttpResponseBody, resBodyContent), + attribute.String( + tracingEventHttpResponseHeaders, + gconv.String(httputil.HeaderToMap(response.Header)), + ), )) return } diff --git a/net/gclient/gclient_request.go b/net/gclient/gclient_request.go index 53aa744c1..be1c2ad0f 100644 --- a/net/gclient/gclient_request.go +++ b/net/gclient/gclient_request.go @@ -167,7 +167,10 @@ func (c *Client) prepareRequest(ctx context.Context, method, url string, data .. if !gstr.ContainsI(url, httpProtocolName) { url = httpProtocolName + `://` + url } - var params string + var ( + params string + allowFileUploading = true + ) if len(data) > 0 { switch c.header[httpHeaderContentType] { case httpHeaderContentTypeJson: @@ -181,6 +184,7 @@ func (c *Client) prepareRequest(ctx context.Context, method, url string, data .. params = string(b) } } + allowFileUploading = false case httpHeaderContentTypeXml: switch data[0].(type) { @@ -193,6 +197,8 @@ func (c *Client) prepareRequest(ctx context.Context, method, url string, data .. params = string(b) } } + allowFileUploading = false + default: params = httputil.BuildParams(data[0], c.noUrlEncode) } @@ -223,14 +229,18 @@ func (c *Client) prepareRequest(ctx context.Context, method, url string, data .. return nil, err } } else { - if strings.Contains(params, httpParamFileHolder) { + if allowFileUploading && strings.Contains(params, httpParamFileHolder) { // File uploading request. var ( - buffer = bytes.NewBuffer(nil) - writer = multipart.NewWriter(buffer) + buffer = bytes.NewBuffer(nil) + writer = multipart.NewWriter(buffer) + isFileUploading = false ) for _, item := range strings.Split(params, "&") { array := strings.Split(item, "=") + if len(array) < 2 { + continue + } if len(array[1]) > 6 && strings.Compare(array[1][0:6], httpParamFileHolder) == 0 { path := array[1][6:] if !gfile.Exists(path) { @@ -241,43 +251,50 @@ func (c *Client) prepareRequest(ctx context.Context, method, url string, data .. formFileName = gfile.Basename(path) formFieldName = array[0] ) + // it sets post content type as `application/octet-stream` if file, err = writer.CreateFormFile(formFieldName, formFileName); err != nil { - err = gerror.Wrapf(err, `CreateFormFile failed with "%s", "%s"`, formFieldName, formFileName) - return nil, err - } else { - var f *os.File - if f, err = gfile.Open(path); err != nil { - return nil, err - } - if _, err = io.Copy(file, f); err != nil { - err = gerror.Wrapf(err, `io.Copy failed from "%s" to form "%s"`, path, formFieldName) - _ = f.Close() - return nil, err - } - _ = f.Close() + return nil, gerror.Wrapf( + err, `CreateFormFile failed with "%s", "%s"`, formFieldName, formFileName, + ) } + var f *os.File + if f, err = gfile.Open(path); err != nil { + return nil, err + } + if _, err = io.Copy(file, f); err != nil { + _ = f.Close() + return nil, gerror.Wrapf( + err, `io.Copy failed from "%s" to form "%s"`, path, formFieldName, + ) + } + if err = f.Close(); err != nil { + return nil, gerror.Wrapf(err, `close file descriptor failed for "%s"`, path) + } + isFileUploading = true } else { var ( fieldName = array[0] fieldValue = array[1] ) if err = writer.WriteField(fieldName, fieldValue); err != nil { - err = gerror.Wrapf(err, `write form field failed with "%s", "%s"`, fieldName, fieldValue) - return nil, err + return nil, gerror.Wrapf( + err, `write form field failed with "%s", "%s"`, fieldName, fieldValue, + ) } } } // Close finishes the multipart message and writes the trailing // boundary end line to the output. if err = writer.Close(); err != nil { - err = gerror.Wrapf(err, `form writer close failed`) - return nil, err + return nil, gerror.Wrapf(err, `form writer close failed`) } if req, err = http.NewRequest(method, url, buffer); err != nil { - err = gerror.Wrapf(err, `http.NewRequest failed for method "%s" and URL "%s"`, method, url) - return nil, err - } else { + return nil, gerror.Wrapf( + err, `http.NewRequest failed for method "%s" and URL "%s"`, method, url, + ) + } + if isFileUploading { req.Header.Set(httpHeaderContentType, writer.FormDataContentType()) } } else { @@ -286,18 +303,17 @@ func (c *Client) prepareRequest(ctx context.Context, method, url string, data .. if req, err = http.NewRequest(method, url, bytes.NewReader(paramBytes)); err != nil { err = gerror.Wrapf(err, `http.NewRequest failed for method "%s" and URL "%s"`, method, url) return nil, err - } else { - if v, ok := c.header[httpHeaderContentType]; ok { - // Custom Content-Type. - req.Header.Set(httpHeaderContentType, v) - } else if len(paramBytes) > 0 { - if (paramBytes[0] == '[' || paramBytes[0] == '{') && json.Valid(paramBytes) { - // Auto-detecting and setting the post content format: JSON. - req.Header.Set(httpHeaderContentType, httpHeaderContentTypeJson) - } else if gregex.IsMatchString(httpRegexParamJson, params) { - // If the parameters passed like "name=value", it then uses form type. - req.Header.Set(httpHeaderContentType, httpHeaderContentTypeForm) - } + } + if v, ok := c.header[httpHeaderContentType]; ok { + // Custom Content-Type. + req.Header.Set(httpHeaderContentType, v) + } else if len(paramBytes) > 0 { + if (paramBytes[0] == '[' || paramBytes[0] == '{') && json.Valid(paramBytes) { + // Auto-detecting and setting the post content format: JSON. + req.Header.Set(httpHeaderContentType, httpHeaderContentTypeJson) + } else if gregex.IsMatchString(httpRegexParamJson, params) { + // If the parameters passed like "name=value", it then uses form type. + req.Header.Set(httpHeaderContentType, httpHeaderContentTypeForm) } } } diff --git a/net/gclient/gclient_tracer_tracing.go b/net/gclient/gclient_tracer_tracing.go index 6c61ebe69..566138bdb 100644 --- a/net/gclient/gclient_tracer_tracing.go +++ b/net/gclient/gclient_tracer_tracing.go @@ -218,14 +218,8 @@ func (ct *clientTracerTracing) WroteRequest(info httptrace.WroteRequestInfo) { ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, info.Err)) } - reqBodyContent, err := gtrace.SafeContentForHttp(ct.requestBody, ct.request.Header) - if err != nil { - ct.span.SetStatus(codes.Error, fmt.Sprintf(`converting safe content failed: %s`, err.Error())) - } - ct.span.AddEvent(tracingEventHttpRequest, trace.WithAttributes( attribute.String(tracingEventHttpRequestHeaders, gconv.String(ct.headers)), attribute.String(tracingEventHttpRequestBaggage, gtrace.GetBaggageMap(ct.Context).String()), - attribute.String(tracingEventHttpRequestBody, reqBodyContent), )) } diff --git a/net/gclient/gclient_z_unit_issue_test.go b/net/gclient/gclient_z_unit_issue_test.go new file mode 100644 index 000000000..e3203f3e1 --- /dev/null +++ b/net/gclient/gclient_z_unit_issue_test.go @@ -0,0 +1,82 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gclient_test + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/gclient" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/guid" +) + +func Test_Issue3748(t *testing.T) { + s := g.Server(guid.S()) + s.BindHandler("/", func(r *ghttp.Request) { + r.Response.Write( + r.GetBody(), + ) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + clientHost := fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()) + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + client := gclient.New() + client.SetHeader("Content-Type", "application/json") + data := map[string]interface{}{ + "name": "@file:", + "value": "json", + } + client.SetPrefix(clientHost) + content := client.PostContent(ctx, "/", data) + t.Assert(content, `{"name":"@file:","value":"json"}`) + }) + + gtest.C(t, func(t *gtest.T) { + client := gclient.New() + client.SetHeader("Content-Type", "application/xml") + data := map[string]interface{}{ + "name": "@file:", + "value": "xml", + } + client.SetPrefix(clientHost) + content := client.PostContent(ctx, "/", data) + t.Assert(content, `@file:xml`) + }) + + gtest.C(t, func(t *gtest.T) { + client := gclient.New() + client.SetHeader("Content-Type", "application/x-www-form-urlencoded") + data := map[string]interface{}{ + "name": "@file:", + "value": "x-www-form-urlencoded", + } + client.SetPrefix(clientHost) + content := client.PostContent(ctx, "/", data) + t.Assert(strings.Contains(content, `Content-Disposition: form-data; name="value"`), true) + t.Assert(strings.Contains(content, `Content-Disposition: form-data; name="name"`), true) + t.Assert(strings.Contains(content, "\r\n@file:"), true) + t.Assert(strings.Contains(content, "\r\nx-www-form-urlencoded"), true) + }) + + gtest.C(t, func(t *gtest.T) { + client := gclient.New() + data := "@file:" + client.SetPrefix(clientHost) + _, err := client.Post(ctx, "/", data) + t.AssertNil(err) + }) +} diff --git a/net/gclient/gclient_z_unit_test.go b/net/gclient/gclient_z_unit_test.go index 64c48dd48..d6e8c6f2f 100644 --- a/net/gclient/gclient_z_unit_test.go +++ b/net/gclient/gclient_z_unit_test.go @@ -177,6 +177,40 @@ func Test_Client_Chain_Header(t *testing.T) { t.Assert(c.HeaderRaw("test1: 1234567890\ntest2: abcdefg").GetContent(ctx, "/header1"), "1234567890") t.Assert(c.HeaderRaw("test1: 1234567890\ntest2: abcdefg").GetContent(ctx, "/header2"), "abcdefg") }) + gtest.C(t, func(t *gtest.T) { + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + t.Assert(c.GetContent(ctx, "/header1"), "") + + copyWithHeader := c.Header(g.MapStrStr{"test1": "1234567890"}) + t.Assert(copyWithHeader.GetContent(ctx, "/header1"), "1234567890") + + t.Assert(c.GetContent(ctx, "/header1"), "") + }) +} + +func Test_Client_Chain_Cookie(t *testing.T) { + s := g.Server(guid.S()) + s.BindHandler("/cookie", func(r *ghttp.Request) { + r.Response.Write(r.Cookie.Get("test", "def")) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + t.Assert(c.GetContent(ctx, "/cookie"), "def") + + copyWithCookie := c.Cookie(g.MapStrStr{"test": "1234567890"}) + t.Assert(copyWithCookie.GetContent(ctx, "/cookie"), "1234567890") + + t.Assert(c.GetContent(ctx, "/cookie"), "def") + }) } func Test_Client_Chain_Context(t *testing.T) { diff --git a/net/ghttp/ghttp_middleware_handler_response.go b/net/ghttp/ghttp_middleware_handler_response.go index d78b4c194..574db5081 100644 --- a/net/ghttp/ghttp_middleware_handler_response.go +++ b/net/ghttp/ghttp_middleware_handler_response.go @@ -7,6 +7,7 @@ package ghttp import ( + "mime" "net/http" "github.com/gogf/gf/v2/errors/gcode" @@ -20,6 +21,17 @@ type DefaultHandlerResponse struct { Data interface{} `json:"data" dc:"Result data for certain request according API definition"` } +const ( + contentTypeEventStream = "text/event-stream" + contentTypeOctetStream = "application/octet-stream" + contentTypeMixedReplace = "multipart/x-mixed-replace" +) + +var ( + // streamContentType is the content types for stream response. + streamContentType = []string{contentTypeEventStream, contentTypeOctetStream, contentTypeMixedReplace} +) + // MiddlewareHandlerResponse is the default middleware handling handler response object and its error. func MiddlewareHandlerResponse(r *Request) { r.Middleware.Next() @@ -29,6 +41,14 @@ func MiddlewareHandlerResponse(r *Request) { return } + // It does not output common response content if it is stream response. + mediaType, _, _ := mime.ParseMediaType(r.Response.Header().Get("Content-Type")) + for _, ct := range streamContentType { + if mediaType == ct { + return + } + } + var ( msg string err = r.GetError() diff --git a/net/ghttp/ghttp_middleware_tracing.go b/net/ghttp/ghttp_middleware_tracing.go index f5d125183..8e1559153 100644 --- a/net/ghttp/ghttp_middleware_tracing.go +++ b/net/ghttp/ghttp_middleware_tracing.go @@ -9,7 +9,6 @@ package ghttp import ( "context" "fmt" - "io" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -18,9 +17,7 @@ import ( "go.opentelemetry.io/otel/trace" "github.com/gogf/gf/v2" - "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/httputil" - "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/util/gconv" @@ -31,10 +28,8 @@ const ( tracingEventHttpRequest = "http.request" tracingEventHttpRequestHeaders = "http.request.headers" tracingEventHttpRequestBaggage = "http.request.baggage" - tracingEventHttpRequestBody = "http.request.body" tracingEventHttpResponse = "http.response" tracingEventHttpResponseHeaders = "http.response.headers" - tracingEventHttpResponseBody = "http.response.body" tracingEventHttpRequestUrl = "http.request.url" tracingMiddlewareHandled gctx.StrKey = `MiddlewareServerTracingHandled` ) @@ -80,24 +75,10 @@ func internalMiddlewareServerTracing(r *Request) { return } - // Request content logging. - reqBodyContentBytes, err := io.ReadAll(r.Body) - if err != nil { - r.SetError(gerror.Wrap(err, `read request body failed`)) - span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err)) - return - } - r.Body = utils.NewReadCloser(reqBodyContentBytes, false) - reqBodyContent, err := gtrace.SafeContentForHttp(reqBodyContentBytes, r.Header) - if err != nil { - span.SetStatus(codes.Error, fmt.Sprintf(`converting safe content failed: %s`, err.Error())) - } - span.AddEvent(tracingEventHttpRequest, trace.WithAttributes( attribute.String(tracingEventHttpRequestUrl, r.URL.String()), attribute.String(tracingEventHttpRequestHeaders, gconv.String(httputil.HeaderToMap(r.Header))), attribute.String(tracingEventHttpRequestBaggage, gtrace.GetBaggageMap(ctx).String()), - attribute.String(tracingEventHttpRequestBody, reqBodyContent), )) // Continue executing. @@ -109,18 +90,14 @@ func internalMiddlewareServerTracing(r *Request) { } // Error logging. - if err = r.GetError(); err != nil { + if err := r.GetError(); err != nil { span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err)) } - // Response content logging. - resBodyContent, err := gtrace.SafeContentForHttp(r.Response.Buffer(), r.Response.Header()) - if err != nil { - span.SetStatus(codes.Error, fmt.Sprintf(`converting safe content failed: %s`, err.Error())) - } - span.AddEvent(tracingEventHttpResponse, trace.WithAttributes( - attribute.String(tracingEventHttpResponseHeaders, gconv.String(httputil.HeaderToMap(r.Response.Header()))), - attribute.String(tracingEventHttpResponseBody, resBodyContent), + attribute.String( + tracingEventHttpResponseHeaders, + gconv.String(httputil.HeaderToMap(r.Response.Header())), + ), )) } diff --git a/net/ghttp/ghttp_response_cors.go b/net/ghttp/ghttp_response_cors.go index 59772f552..7a80fe647 100644 --- a/net/ghttp/ghttp_response_cors.go +++ b/net/ghttp/ghttp_response_cors.go @@ -64,8 +64,8 @@ func (r *Response) DefaultCORSOptions() CORSOptions { if origin := r.Request.Header.Get("Origin"); origin != "" { options.AllowOrigin = origin } else if referer := r.Request.Referer(); referer != "" { - if p := gstr.PosR(referer, "/", 6); p != -1 { - options.AllowOrigin = referer[:p] + if ref, err := url.Parse(referer); err == nil { + options.AllowOrigin = ref.Scheme + "://" + ref.Host } else { options.AllowOrigin = referer } diff --git a/net/ghttp/ghttp_server.go b/net/ghttp/ghttp_server.go index 75944a489..80976ee97 100644 --- a/net/ghttp/ghttp_server.go +++ b/net/ghttp/ghttp_server.go @@ -247,7 +247,13 @@ func (s *Server) Start() error { // If this is a child process, it then notifies its parent exit. if gproc.IsChild() { - gtimer.SetTimeout(ctx, time.Duration(s.config.GracefulTimeout)*time.Second, func(ctx context.Context) { + var gracefulTimeout = time.Duration(s.config.GracefulTimeout) * time.Second + gtimer.SetTimeout(ctx, gracefulTimeout, func(ctx context.Context) { + intlog.Printf( + ctx, + `pid[%d]: notice parent server graceful shuttingdown, ppid: %d`, + gproc.Pid(), gproc.PPid(), + ) if err := gproc.Send(gproc.PPid(), []byte("exit"), adminGProcCommGroup); err != nil { intlog.Errorf(ctx, `server error in process communication: %+v`, err) } diff --git a/net/ghttp/ghttp_server_admin.go b/net/ghttp/ghttp_server_admin.go index 2928493a4..109cacb13 100644 --- a/net/ghttp/ghttp_server_admin.go +++ b/net/ghttp/ghttp_server_admin.go @@ -36,8 +36,14 @@ func (p *utilAdmin) Index(r *Request) {

Pid: {{.pid}}

File Path: {{.path}}

-

Restart

-

Shutdown

+

+Restart +please make sure it is running using standalone binary not from IDE or "go run" +

+

+Shutdown +graceful shutdown the server +

`, data) @@ -89,7 +95,7 @@ func (s *Server) Shutdown() error { // Only shut down current servers. // It may have multiple underlying http servers. for _, v := range s.servers { - v.close(ctx) + v.shutdown(ctx) } return nil } diff --git a/net/ghttp/ghttp_server_admin_process.go b/net/ghttp/ghttp_server_admin_process.go index 3c8687824..31313f6aa 100644 --- a/net/ghttp/ghttp_server_admin_process.go +++ b/net/ghttp/ghttp_server_admin_process.go @@ -21,6 +21,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/intlog" + "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/os/gtime" @@ -55,7 +56,10 @@ var ( // The optional parameter `newExeFilePath` specifies the new binary file for creating process. func RestartAllServer(ctx context.Context, newExeFilePath string) error { if !gracefulEnabled { - return gerror.NewCode(gcode.CodeInvalidOperation, "graceful reload feature is disabled") + return gerror.NewCode( + gcode.CodeInvalidOperation, + "graceful reload feature is disabled", + ) } serverActionLocker.Lock() defer serverActionLocker.Unlock() @@ -115,13 +119,16 @@ func checkActionFrequency() error { // forkReloadProcess creates a new child process and copies the fd to child process. func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error { var ( - path = os.Args[0] + binaryPath = os.Args[0] ) if len(newExeFilePath) > 0 && newExeFilePath[0] != "" { - path = newExeFilePath[0] + binaryPath = newExeFilePath[0] + } + if !gfile.Exists(binaryPath) { + return gerror.Newf(`binary file path "%s" does not exist`, binaryPath) } var ( - p = gproc.NewProcess(path, os.Args[1:], os.Environ()) + p = gproc.NewProcess(binaryPath, os.Args[1:], os.Environ()) sfm = getServerFdMap() ) for name, m := range sfm { @@ -145,9 +152,9 @@ func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error { buffer, _ := gjson.Encode(sfm) p.Env = append(p.Env, adminActionReloadEnvKey+"="+string(buffer)) if _, err := p.Start(ctx); err != nil { - glog.Errorf( + intlog.Errorf( ctx, - "%d: fork process failed, error:%s, %s", + "%d: fork process failed, error: %s, %s", gproc.Pid(), err.Error(), string(buffer), ) return err @@ -254,7 +261,7 @@ func shutdownWebServersGracefully(ctx context.Context, signal os.Signal) { gproc.Pid(), signal.String(), ) } else { - glog.Printf(ctx, "%d: server gracefully shutting down by api", gproc.Pid()) + glog.Printf(ctx, "pid[%d]: server gracefully shutting down by api", gproc.Pid()) } serverMapping.RLockFunc(func(m map[string]interface{}) { for _, v := range m { diff --git a/net/ghttp/ghttp_server_config.go b/net/ghttp/ghttp_server_config.go index 22163051e..219b1f4ca 100644 --- a/net/ghttp/ghttp_server_config.go +++ b/net/ghttp/ghttp_server_config.go @@ -230,6 +230,19 @@ type ServerConfig struct { SwaggerPath string `json:"swaggerPath"` // SwaggerPath specifies the swagger UI path for route registering. SwaggerUITemplate string `json:"swaggerUITemplate"` // SwaggerUITemplate specifies the swagger UI custom template + // ====================================================================================================== + // Graceful reload & shutdown. + // ====================================================================================================== + + // Graceful enables graceful reload feature for all servers of the process. + Graceful bool `json:"graceful"` + + // GracefulTimeout set the maximum survival time (seconds) of the parent process. + GracefulTimeout int `json:"gracefulTimeout"` + + // GracefulShutdownTimeout set the maximum survival time (seconds) before stopping the server. + GracefulShutdownTimeout int `json:"gracefulShutdownTimeout"` + // ====================================================================================================== // Other. // ====================================================================================================== @@ -254,15 +267,6 @@ type ServerConfig struct { // DumpRouterMap specifies whether automatically dumps router map when server starts. DumpRouterMap bool `json:"dumpRouterMap"` - - // Graceful enables graceful reload feature for all servers of the process. - Graceful bool `json:"graceful"` - - // GracefulTimeout set the maximum survival time (seconds) of the parent process. - GracefulTimeout uint8 `json:"gracefulTimeout"` - - // GracefulShutdownTimeout set the maximum survival time (seconds) before stopping the server. - GracefulShutdownTimeout uint8 `json:"gracefulShutdownTimeout"` } // NewConfig creates and returns a ServerConfig object with default configurations. @@ -384,7 +388,12 @@ func (s *Server) SetConfig(c ServerConfig) error { } // SetAddr sets the listening address for the server. -// The address is like ':80', '0.0.0.0:80', '127.0.0.1:80', '180.18.99.10:80', etc. +// The address is like: +// SetAddr(":80") +// SetAddr("0.0.0.0:80") +// SetAddr("127.0.0.1:80") +// SetAddr("180.18.99.10:80") +// etc. func (s *Server) SetAddr(address string) { s.config.Address = address } diff --git a/net/ghttp/ghttp_server_config_api.go b/net/ghttp/ghttp_server_config_api.go new file mode 100644 index 000000000..d9a66d3cb --- /dev/null +++ b/net/ghttp/ghttp_server_config_api.go @@ -0,0 +1,23 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package ghttp + +// SetSwaggerPath sets the SwaggerPath for server. +func (s *Server) SetSwaggerPath(path string) { + s.config.SwaggerPath = path +} + +// SetSwaggerUITemplate sets the Swagger template for server. +func (s *Server) SetSwaggerUITemplate(swaggerUITemplate string) { + s.config.SwaggerUITemplate = swaggerUITemplate +} + +// SetOpenApiPath sets the OpenApiPath for server. +// For example: SetOpenApiPath("/api.json") +func (s *Server) SetOpenApiPath(path string) { + s.config.OpenApiPath = path +} diff --git a/net/ghttp/ghttp_server_config_mess.go b/net/ghttp/ghttp_server_config_mess.go index 441138778..c822eb914 100644 --- a/net/ghttp/ghttp_server_config_mess.go +++ b/net/ghttp/ghttp_server_config_mess.go @@ -27,17 +27,34 @@ func (s *Server) SetFormParsingMemory(maxMemory int64) { s.config.FormParsingMemory = maxMemory } -// SetSwaggerPath sets the SwaggerPath for server. -func (s *Server) SetSwaggerPath(path string) { - s.config.SwaggerPath = path +// SetGraceful sets the Graceful for server. +func (s *Server) SetGraceful(graceful bool) { + s.config.Graceful = graceful + // note: global setting. + gracefulEnabled = graceful } -// SetSwaggerUITemplate sets the Swagger template for server. -func (s *Server) SetSwaggerUITemplate(swaggerUITemplate string) { - s.config.SwaggerUITemplate = swaggerUITemplate +// GetGraceful returns the Graceful for server. +func (s *Server) GetGraceful() bool { + return s.config.Graceful } -// SetOpenApiPath sets the OpenApiPath for server. -func (s *Server) SetOpenApiPath(path string) { - s.config.OpenApiPath = path +// SetGracefulTimeout sets the GracefulTimeout for server. +func (s *Server) SetGracefulTimeout(gracefulTimeout int) { + s.config.GracefulTimeout = gracefulTimeout +} + +// GetGracefulTimeout returns the GracefulTimeout for server. +func (s *Server) GetGracefulTimeout() int { + return s.config.GracefulTimeout +} + +// SetGracefulShutdownTimeout sets the GracefulShutdownTimeout for server. +func (s *Server) SetGracefulShutdownTimeout(gracefulShutdownTimeout int) { + s.config.GracefulShutdownTimeout = gracefulShutdownTimeout +} + +// GetGracefulShutdownTimeout returns the GracefulShutdownTimeout for server. +func (s *Server) GetGracefulShutdownTimeout() int { + return s.config.GracefulShutdownTimeout } diff --git a/net/ghttp/ghttp_server_graceful.go b/net/ghttp/ghttp_server_graceful.go index cc3c30157..a86475378 100644 --- a/net/ghttp/ghttp_server_graceful.go +++ b/net/ghttp/ghttp_server_graceful.go @@ -259,6 +259,7 @@ func (s *gracefulServer) getRawListener() net.Listener { } // close shuts down the server forcibly. +// for graceful shutdown, please use gracefulServer.shutdown. func (s *gracefulServer) close(ctx context.Context) { if s.status.Val() == ServerStatusStopped { return diff --git a/net/ghttp/ghttp_server_pprof.go b/net/ghttp/ghttp_server_pprof.go index eb37f4626..3477d68a6 100644 --- a/net/ghttp/ghttp_server_pprof.go +++ b/net/ghttp/ghttp_server_pprof.go @@ -23,12 +23,13 @@ const ( defaultPProfPattern = "/debug/pprof" ) -// StartPProfServer starts and runs a new server for pprof. -func StartPProfServer(port int, pattern ...string) { - s := GetServer(defaultPProfServerName) +// StartPProfServer starts and runs a new server for pprof in another goroutine. +func StartPProfServer(address string, pattern ...string) (s *Server, err error) { + s = GetServer(defaultPProfServerName) s.EnablePProf(pattern...) - s.SetPort(port) - s.Run() + s.SetAddr(address) + err = s.Start() + return } // EnablePProf enables PProf feature for server. diff --git a/net/ghttp/ghttp_server_service_handler.go b/net/ghttp/ghttp_server_service_handler.go index d7c2cac05..76de26aaa 100644 --- a/net/ghttp/ghttp_server_service_handler.go +++ b/net/ghttp/ghttp_server_service_handler.go @@ -221,28 +221,6 @@ func (s *Server) checkAndCreateFuncInfo( } */ - // The request struct should be named as `xxxReq`. - reqStructName := trimGeneric(reflectType.In(1).String()) - if !gstr.HasSuffix(reqStructName, `Req`) { - err = gerror.NewCodef( - gcode.CodeInvalidParameter, - `invalid struct naming for request: defined as "%s", but it should be named with "Req" suffix like "XxxReq"`, - reqStructName, - ) - return - } - - // The response struct should be named as `xxxRes`. - resStructName := trimGeneric(reflectType.Out(0).String()) - if !gstr.HasSuffix(resStructName, `Res`) { - err = gerror.NewCodef( - gcode.CodeInvalidParameter, - `invalid struct naming for response: defined as "%s", but it should be named with "Res" suffix like "XxxRes"`, - resStructName, - ) - return - } - funcInfo.IsStrictRoute = true inputObject = reflect.New(funcInfo.Type.In(1).Elem()) diff --git a/net/ghttp/ghttp_z_unit_feature_config_test.go b/net/ghttp/ghttp_z_unit_feature_config_test.go index e408e4f62..c84cf2425 100644 --- a/net/ghttp/ghttp_z_unit_feature_config_test.go +++ b/net/ghttp/ghttp_z_unit_feature_config_test.go @@ -163,3 +163,42 @@ func Test_ClientMaxBodySize_File(t *testing.T) { ) }) } + +func Test_Config_Graceful(t *testing.T) { + var ( + defaultConfig = ghttp.NewConfig() + expect = true + ) + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + t.Assert(s.GetGraceful(), defaultConfig.Graceful) + s.SetGraceful(expect) + t.Assert(s.GetGraceful(), expect) + }) +} + +func Test_Config_GracefulTimeout(t *testing.T) { + var ( + defaultConfig = ghttp.NewConfig() + expect = 3 + ) + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + t.Assert(s.GetGracefulTimeout(), defaultConfig.GracefulTimeout) + s.SetGracefulTimeout(expect) + t.Assert(s.GetGracefulTimeout(), expect) + }) +} + +func Test_Config_GracefulShutdownTimeout(t *testing.T) { + var ( + defaultConfig = ghttp.NewConfig() + expect = 10 + ) + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + t.Assert(s.GetGracefulShutdownTimeout(), defaultConfig.GracefulShutdownTimeout) + s.SetGracefulShutdownTimeout(expect) + t.Assert(s.GetGracefulShutdownTimeout(), expect) + }) +} diff --git a/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go b/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go index 2678e3227..67c5d2749 100644 --- a/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go +++ b/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go @@ -774,6 +774,49 @@ func Test_MiddlewareHandlerGzipResponse(t *testing.T) { }) } +func Test_MiddlewareHandlerStreamResponse(t *testing.T) { + s := g.Server(guid.S()) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Middleware(ghttp.MiddlewareHandlerResponse) + + group.GET("/stream/event", func(r *ghttp.Request) { + r.Response.Header().Set("Content-Type", "text/event-stream") + }) + + group.GET("/stream/octet", func(r *ghttp.Request) { + r.Response.Header().Set("Content-Type", "application/octet-stream") + }) + + group.GET("/stream/mixed", func(r *ghttp.Request) { + r.Response.Header().Set("Content-Type", "multipart/x-mixed-replace") + }) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + rsp, err := client.Get(ctx, "/stream/event") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "") + + rsp, err = client.Get(ctx, "/stream/octet") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "") + + rsp, err = client.Get(ctx, "/stream/mixed") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "") + }) +} + type testTracerProvider struct { noop.TracerProvider } diff --git a/net/ghttp/ghttp_z_unit_feature_pprof_test.go b/net/ghttp/ghttp_z_unit_feature_pprof_test.go index 75ad0bc8f..d6b355e7e 100644 --- a/net/ghttp/ghttp_z_unit_feature_pprof_test.go +++ b/net/ghttp/ghttp_z_unit_feature_pprof_test.go @@ -14,6 +14,7 @@ import ( "time" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" . "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/guid" ) @@ -29,30 +30,37 @@ func TestServer_EnablePProf(t *testing.T) { client := g.Client() client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) - r, err := client.Get(ctx, "/pprof/index") - Assert(err, nil) - Assert(r.StatusCode, 200) - r.Close() - - r, err = client.Get(ctx, "/pprof/cmdline") - Assert(err, nil) - Assert(r.StatusCode, 200) - r.Close() - - //r, err = client.Get(ctx, "/pprof/profile") - //Assert(err, nil) - //Assert(r.StatusCode, 200) - //r.Close() - - r, err = client.Get(ctx, "/pprof/symbol") - Assert(err, nil) - Assert(r.StatusCode, 200) - r.Close() - - r, err = client.Get(ctx, "/pprof/trace") - Assert(err, nil) - Assert(r.StatusCode, 200) - r.Close() + urlPaths := []string{ + "/pprof/index", "/pprof/cmdline", "/pprof/symbol", "/pprof/trace", + } + for _, urlPath := range urlPaths { + r, err := client.Get(ctx, urlPath) + AssertNil(err) + Assert(r.StatusCode, 200) + AssertNil(r.Close()) + } + }) +} + +func TestServer_StartPProfServer(t *testing.T) { + C(t, func(t *T) { + s, err := ghttp.StartPProfServer(":0") + t.AssertNil(err) + + defer ghttp.ShutdownAllServer(ctx) + + time.Sleep(100 * time.Millisecond) + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d/debug", s.GetListenedPort())) + + urlPaths := []string{ + "/pprof/index", "/pprof/cmdline", "/pprof/symbol", "/pprof/trace", + } + for _, urlPath := range urlPaths { + r, err := client.Get(ctx, urlPath) + AssertNil(err) + Assert(r.StatusCode, 200) + AssertNil(r.Close()) + } }) - } diff --git a/net/ghttp/ghttp_z_unit_issue_test.go b/net/ghttp/ghttp_z_unit_issue_test.go index 3f56dd952..d0d17b847 100644 --- a/net/ghttp/ghttp_z_unit_issue_test.go +++ b/net/ghttp/ghttp_z_unit_issue_test.go @@ -568,3 +568,53 @@ func Test_Issue3245(t *testing.T) { t.Assert(c.GetContent(ctx, "/hello?nickname=oldme"), expect) }) } + +type ItemSecondThird struct { + SecondID uint64 `json:"secondId,string"` + ThirdID uint64 `json:"thirdId,string"` +} +type ItemFirst struct { + ID uint64 `json:"id,string"` + ItemSecondThird +} +type ItemInput struct { + ItemFirst +} +type Issue3789Req struct { + g.Meta `path:"/hello" method:"GET"` + ItemInput +} +type Issue3789Res struct { + ItemInput +} + +type Issue3789 struct{} + +func (Issue3789) Say(ctx context.Context, req *Issue3789Req) (res *Issue3789Res, err error) { + res = &Issue3789Res{ + ItemInput: req.ItemInput, + } + return +} + +// https://github.com/gogf/gf/issues/3789 +func Test_Issue3789(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s := g.Server() + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3789), + ) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + expect := `{"code":0,"message":"","data":{"id":"0","secondId":"2","thirdId":"3"}}` + t.Assert(c.GetContent(ctx, "/hello?id=&secondId=2&thirdId=3"), expect) + }) +} diff --git a/net/gipv4/gipv4.go b/net/gipv4/gipv4.go index ea52f9131..df0c3d6dd 100644 --- a/net/gipv4/gipv4.go +++ b/net/gipv4/gipv4.go @@ -6,33 +6,16 @@ // // Package gipv4 provides useful API for IPv4 address handling. + package gipv4 import ( - "encoding/binary" "fmt" - "net" "strconv" "github.com/gogf/gf/v2/text/gregex" ) -// Ip2long converts ip address to an uint32 integer. -func Ip2long(ip string) uint32 { - netIp := net.ParseIP(ip) - if netIp == nil { - return 0 - } - return binary.BigEndian.Uint32(netIp.To4()) -} - -// Long2ip converts an uint32 integer ip address to its string type address. -func Long2ip(long uint32) string { - ipByte := make([]byte, 4) - binary.BigEndian.PutUint32(ipByte, long) - return net.IP(ipByte).String() -} - // Validate checks whether given `ip` a valid IPv4 address. func Validate(ip string) bool { return gregex.IsMatchString(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`, ip) diff --git a/net/gipv4/gipv4_convert.go b/net/gipv4/gipv4_convert.go new file mode 100644 index 000000000..47d82555c --- /dev/null +++ b/net/gipv4/gipv4_convert.go @@ -0,0 +1,59 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +// + +// Package gipv4 provides useful API for IPv4 address handling. + +package gipv4 + +import ( + "encoding/binary" + "net" +) + +// IpToLongBigEndian converts ip address to an uint32 integer with big endian. +func IpToLongBigEndian(ip string) uint32 { + netIp := net.ParseIP(ip) + if netIp == nil { + return 0 + } + return binary.BigEndian.Uint32(netIp.To4()) +} + +// LongToIpBigEndian converts an uint32 integer ip address to its string type address with big endian. +func LongToIpBigEndian(long uint32) string { + ipByte := make([]byte, 4) + binary.BigEndian.PutUint32(ipByte, long) + return net.IP(ipByte).String() +} + +// IpToLongLittleEndian converts ip address to an uint32 integer with little endian. +func IpToLongLittleEndian(ip string) uint32 { + netIp := net.ParseIP(ip) + if netIp == nil { + return 0 + } + return binary.LittleEndian.Uint32(netIp.To4()) +} + +// LongToIpLittleEndian converts an uint32 integer ip address to its string type address with little endian. +func LongToIpLittleEndian(long uint32) string { + ipByte := make([]byte, 4) + binary.LittleEndian.PutUint32(ipByte, long) + return net.IP(ipByte).String() +} + +// Ip2long converts ip address to an uint32 integer. +// Deprecated: Use IpToLongBigEndian instead. +func Ip2long(ip string) uint32 { + return IpToLongBigEndian(ip) +} + +// Long2ip converts an uint32 integer ip address to its string type address. +// Deprecated: Use LongToIpBigEndian instead. +func Long2ip(long uint32) string { + return LongToIpBigEndian(long) +} diff --git a/net/gipv4/gipv4_z_unit_convert_test.go b/net/gipv4/gipv4_z_unit_convert_test.go new file mode 100644 index 000000000..19ef9c5f5 --- /dev/null +++ b/net/gipv4/gipv4_z_unit_convert_test.go @@ -0,0 +1,54 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gipv4_test + +import ( + "testing" + + "github.com/gogf/gf/v2/net/gipv4" + "github.com/gogf/gf/v2/test/gtest" +) + +const ( + ipv4 string = "192.168.1.1" + longBigEndian uint32 = 3232235777 + longLittleEndian uint32 = 16885952 +) + +func TestIpToLongBigEndian(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var u = gipv4.IpToLongBigEndian(ipv4) + t.Assert(u, longBigEndian) + + var u2 = gipv4.Ip2long(ipv4) + t.Assert(u2, longBigEndian) + }) +} + +func TestLongToIpBigEndian(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s = gipv4.LongToIpBigEndian(longBigEndian) + t.Assert(s, ipv4) + + var s2 = gipv4.Long2ip(longBigEndian) + t.Assert(s2, ipv4) + }) +} + +func TestIpToLongLittleEndian(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var u = gipv4.IpToLongLittleEndian(ipv4) + t.Assert(u, longLittleEndian) + }) +} + +func TestLongToIpLittleEndian(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s = gipv4.LongToIpLittleEndian(longLittleEndian) + t.Assert(s, ipv4) + }) +} diff --git a/net/goai/goai.go b/net/goai/goai.go index d248374af..9228b89dc 100644 --- a/net/goai/goai.go +++ b/net/goai/goai.go @@ -63,8 +63,14 @@ const ( ) const ( - validationRuleKeyForRequired = `required` - validationRuleKeyForIn = `in:` + validationRuleKeyForRequired = `required` + validationRuleKeyForIn = `in:` + validationRuleKeyForMax = `max:` + validationRuleKeyForMin = `min:` + validationRuleKeyForLength = `length:` + validationRuleKeyForMaxLength = `max-length:` + validationRuleKeyForMinLength = `min-length:` + validationRuleKeyForBetween = `between:` ) var ( @@ -227,6 +233,10 @@ func formatRefToBytes(ref string) []byte { return []byte(fmt.Sprintf(`{"$ref":"#/components/schemas/%s"}`, ref)) } +func formatRefAndDescToBytes(ref, desc string) []byte { + return []byte(fmt.Sprintf(`{"$ref":"#/components/schemas/%s","description":"%s"}`, ref, desc)) +} + func isValidParameterName(key string) bool { return key != "-" } diff --git a/net/goai/goai_example.go b/net/goai/goai_example.go index 61b75d4fb..34ec816c2 100644 --- a/net/goai/goai_example.go +++ b/net/goai/goai_example.go @@ -7,7 +7,13 @@ package goai import ( + "fmt" + + "github.com/gogf/gf/v2/encoding/gjson" + "github.com/gogf/gf/v2/internal/empty" "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gres" ) // Example is specified by OpenAPI/Swagger 3.0 standard. @@ -25,6 +31,61 @@ type ExampleRef struct { Value *Example } +func (e *Examples) applyExamplesFile(path string) error { + if empty.IsNil(e) { + return nil + } + var json string + if resource := gres.Get(path); resource != nil { + json = string(resource.Content()) + } else { + absolutePath := gfile.RealPath(path) + if absolutePath != "" { + json = gfile.GetContents(absolutePath) + } + } + if json == "" { + return nil + } + var data interface{} + err := gjson.Unmarshal([]byte(json), &data) + if err != nil { + return err + } + err = e.applyExamplesData(data) + if err != nil { + return err + } + return nil +} + +func (e *Examples) applyExamplesData(data interface{}) error { + if empty.IsNil(e) || empty.IsNil(data) { + return nil + } + + switch v := data.(type) { + case map[string]interface{}: + for key, value := range v { + (*e)[key] = &ExampleRef{ + Value: &Example{ + Value: value, + }, + } + } + case []interface{}: + for i, value := range v { + (*e)[fmt.Sprintf("example %d", i+1)] = &ExampleRef{ + Value: &Example{ + Value: value, + }, + } + } + default: + } + return nil +} + func (r ExampleRef) MarshalJSON() ([]byte, error) { if r.Ref != "" { return formatRefToBytes(r.Ref), nil diff --git a/net/goai/goai_path.go b/net/goai/goai_path.go index d3667638c..2d5ac6576 100644 --- a/net/goai/goai_path.go +++ b/net/goai/goai_path.go @@ -85,14 +85,13 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { } var ( - mime string - path = Path{XExtensions: make(XExtensions)} - inputMetaMap = gmeta.Data(inputObject.Interface()) - outputMetaMap = gmeta.Data(outputObject.Interface()) - isInputStructEmpty = oai.doesStructHasNoFields(inputObject.Interface()) - inputStructTypeName = oai.golangTypeToSchemaName(inputObject.Type()) - outputStructTypeName = oai.golangTypeToSchemaName(outputObject.Type()) - operation = Operation{ + mime string + path = Path{XExtensions: make(XExtensions)} + inputMetaMap = gmeta.Data(inputObject.Interface()) + outputMetaMap = gmeta.Data(outputObject.Interface()) + isInputStructEmpty = oai.doesStructHasNoFields(inputObject.Interface()) + inputStructTypeName = oai.golangTypeToSchemaName(inputObject.Type()) + operation = Operation{ Responses: map[string]ResponseRef{}, XExtensions: make(XExtensions), } @@ -129,7 +128,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { ) } - if err := oai.addSchema(inputObject.Interface(), outputObject.Interface()); err != nil { + if err := oai.addSchema(inputObject.Interface()); err != nil { return err } @@ -199,15 +198,16 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { if operation.RequestBody.Value == nil { var ( requestBody = RequestBody{ - Required: true, - Content: map[string]MediaType{}, + Content: map[string]MediaType{}, } ) // Supported mime types of request. var ( - contentTypes = oai.Config.ReadContentTypes - tagMimeValue = gmeta.Get(inputObject.Interface(), gtag.Mime).String() + contentTypes = oai.Config.ReadContentTypes + tagMimeValue = gmeta.Get(inputObject.Interface(), gtag.Mime).String() + tagRequiredValue = gmeta.Get(inputObject.Interface(), gtag.Required).Bool() ) + requestBody.Required = tagRequiredValue if tagMimeValue != "" { contentTypes = gstr.SplitAndTrim(tagMimeValue, ",") } @@ -234,48 +234,44 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { } // ================================================================================================================= - // Response. + // Default Response. // ================================================================================================================= - if _, ok := operation.Responses[responseOkKey]; !ok { - var ( - response = Response{ - Content: map[string]MediaType{}, - XExtensions: make(XExtensions), + status := responseOkKey + if statusValue, ok := outputMetaMap[gtag.Status]; ok { + statusCode := gconv.Int(statusValue) + if statusCode < 100 || statusCode >= 600 { + return gerror.Newf("Invalid HTTP status code: %s", statusValue) + } + status = statusValue + } + if _, ok := operation.Responses[status]; !ok { + response, err := oai.getResponseFromObject(outputObject.Interface(), true) + if err != nil { + return err + } + operation.Responses[status] = ResponseRef{Value: response} + } + + // ================================================================================================================= + // Other Responses. + // ================================================================================================================= + if enhancedResponse, ok := outputObject.Interface().(IEnhanceResponseStatus); ok { + for statusCode, data := range enhancedResponse.EnhanceResponseStatus() { + if statusCode < 100 || statusCode >= 600 { + return gerror.Newf("Invalid HTTP status code: %d", statusCode) } - ) - if len(outputMetaMap) > 0 { - if err := oai.tagMapToResponse(outputMetaMap, &response); err != nil { - return err + if data.Response == nil { + continue + } + status := gconv.String(statusCode) + if _, ok := operation.Responses[status]; !ok { + response, err := oai.getResponseFromObject(data, false) + if err != nil { + return err + } + operation.Responses[status] = ResponseRef{Value: response} } } - // Supported mime types of response. - var ( - contentTypes = oai.Config.ReadContentTypes - tagMimeValue = gmeta.Get(outputObject.Interface(), gtag.Mime).String() - refInput = getResponseSchemaRefInput{ - BusinessStructName: outputStructTypeName, - CommonResponseObject: oai.Config.CommonResponse, - CommonResponseDataField: oai.Config.CommonResponseDataField, - } - ) - if tagMimeValue != "" { - contentTypes = gstr.SplitAndTrim(tagMimeValue, ",") - } - for _, v := range contentTypes { - // If customized response mime type, it then ignores common response feature. - if tagMimeValue != "" { - refInput.CommonResponseObject = nil - refInput.CommonResponseDataField = "" - } - schemaRef, err := oai.getResponseSchemaRef(refInput) - if err != nil { - return err - } - response.Content[v] = MediaType{ - Schema: schemaRef, - } - } - operation.Responses[responseOkKey] = ResponseRef{Value: &response} } // Remove operation body duplicated properties. diff --git a/net/goai/goai_requestbody.go b/net/goai/goai_requestbody.go index 353923ac0..d9c1858db 100644 --- a/net/goai/goai_requestbody.go +++ b/net/goai/goai_requestbody.go @@ -54,7 +54,17 @@ func (oai *OpenApiV3) getRequestSchemaRef(in getRequestSchemaRefInput) (*SchemaR if err != nil { return nil, err } - if in.RequestDataField == "" && bizRequestStructSchemaRef != nil { + + if bizRequestStructSchemaRef == nil { + return &SchemaRef{ + Value: schema, + }, nil + } + + if in.RequestDataField == "" && bizRequestStructSchemaRef.Value != nil { + // Append bizRequest. + schema.Required = append(schema.Required, bizRequestStructSchemaRef.Value.Required...) + // Normal request. bizRequestStructSchemaRef.Value.Properties.Iterator(func(key string, ref SchemaRef) bool { schema.Properties.Set(key, ref) diff --git a/net/goai/goai_response.go b/net/goai/goai_response.go index ce702eda1..1f81365f6 100644 --- a/net/goai/goai_response.go +++ b/net/goai/goai_response.go @@ -12,6 +12,24 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +// EnhancedStatusCode is http status for response. +type EnhancedStatusCode = int + +// EnhancedStatusType is the structure for certain response status. +// Currently, it only supports `Response` and `Examples`. +// `Response` is the response structure +// `Examples` is the examples for the response, map[string]interface{}, []interface{} are supported. +type EnhancedStatusType struct { + Response any + Examples any +} + +// IEnhanceResponseStatus is used to enhance the documentation of the response. +// Normal response structure could implement this interface to provide more information. +type IEnhanceResponseStatus interface { + EnhanceResponseStatus() map[EnhancedStatusCode]EnhancedStatusType +} + // Response is specified by OpenAPI/Swagger 3.0 standard. type Response struct { Description string `json:"description"` diff --git a/net/goai/goai_response_ref.go b/net/goai/goai_response_ref.go index 495aada71..683aa1233 100644 --- a/net/goai/goai_response_ref.go +++ b/net/goai/goai_response_ref.go @@ -12,6 +12,8 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/os/gstructs" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gmeta" + "github.com/gogf/gf/v2/util/gtag" ) type ResponseRef struct { @@ -22,6 +24,98 @@ type ResponseRef struct { // Responses is specified by OpenAPI/Swagger 3.0 standard. type Responses map[string]ResponseRef +// object could be someObject.Interface() +// There may be some difference between someObject.Type() and reflect.TypeOf(object). +func (oai *OpenApiV3) getResponseFromObject(data interface{}, isDefault bool) (*Response, error) { + var object interface{} + enhancedResponse, isEnhanced := data.(EnhancedStatusType) + if isEnhanced { + object = enhancedResponse.Response + } else { + object = data + } + // Add object schema to oai + if err := oai.addSchema(object); err != nil { + return nil, err + } + var ( + metaMap = gmeta.Data(object) + response = &Response{ + Content: map[string]MediaType{}, + XExtensions: make(XExtensions), + } + ) + if len(metaMap) > 0 { + if err := oai.tagMapToResponse(metaMap, response); err != nil { + return nil, err + } + } + // Supported mime types of response. + var ( + contentTypes = oai.Config.ReadContentTypes + tagMimeValue = gmeta.Get(object, gtag.Mime).String() + refInput = getResponseSchemaRefInput{ + BusinessStructName: oai.golangTypeToSchemaName(reflect.TypeOf(object)), + CommonResponseObject: oai.Config.CommonResponse, + CommonResponseDataField: oai.Config.CommonResponseDataField, + } + ) + + // If customized response mime type, it then ignores common response feature. + if tagMimeValue != "" { + contentTypes = gstr.SplitAndTrim(tagMimeValue, ",") + refInput.CommonResponseObject = nil + refInput.CommonResponseDataField = "" + } + + // If it is not default status, check if it has any fields. + // If so, it would override the common response. + if !isDefault { + fields, _ := gstructs.Fields(gstructs.FieldsInput{ + Pointer: object, + RecursiveOption: gstructs.RecursiveOptionEmbeddedNoTag, + }) + if len(fields) > 0 { + refInput.CommonResponseObject = nil + refInput.CommonResponseDataField = "" + } + } + + // Generate response example from meta data. + responseExamplePath := metaMap[gtag.ResponseExampleShort] + if responseExamplePath == "" { + responseExamplePath = metaMap[gtag.ResponseExample] + } + examples := make(Examples) + if responseExamplePath != "" { + if err := examples.applyExamplesFile(responseExamplePath); err != nil { + return nil, err + } + } + + // Override examples from enhanced response. + if isEnhanced { + err := examples.applyExamplesData(enhancedResponse.Examples) + if err != nil { + return nil, err + } + } + + // Generate response schema from input. + schemaRef, err := oai.getResponseSchemaRef(refInput) + if err != nil { + return nil, err + } + + for _, contentType := range contentTypes { + response.Content[contentType] = MediaType{ + Schema: schemaRef, + Examples: examples, + } + } + return response, nil +} + func (r ResponseRef) MarshalJSON() ([]byte, error) { if r.Ref != "" { return formatRefToBytes(r.Ref), nil diff --git a/net/goai/goai_shema.go b/net/goai/goai_shema.go index f8a6be2d8..9d1e1e712 100644 --- a/net/goai/goai_shema.go +++ b/net/goai/goai_shema.go @@ -8,6 +8,7 @@ package goai import ( "reflect" + "strings" "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gset" @@ -176,7 +177,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) { // struct. structFields, _ := gstructs.Fields(gstructs.FieldsInput{ Pointer: object, - RecursiveOption: gstructs.RecursiveOptionEmbeddedNoTag, + RecursiveOption: gstructs.RecursiveOptionEmbedded, }) schema.Type = TypeObject for _, structField := range structFields { @@ -204,6 +205,56 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) { if validationRuleSet.Contains(validationRuleKeyForRequired) { schema.Required = append(schema.Required, key) } + + // Extract validation rules to schema. like min, max, length + lstRules := gstr.Split(ref.Value.ValidationRules, "|") + for _, rule := range lstRules { + if strings.HasPrefix(rule, validationRuleKeyForMax) { + if ref.Value.Type == "integer" || ref.Value.Type == "number" { + f := gconv.Float64(rule[4:]) + ref.Value.Max = &f + } + } + + if strings.HasPrefix(rule, validationRuleKeyForMaxLength) { + maxlength := gconv.Uint64(rule[11:]) + ref.Value.MaxLength = &maxlength + } + + if strings.HasPrefix(rule, validationRuleKeyForMin) { + if ref.Value.Type == "integer" || ref.Value.Type == "number" { + f := gconv.Float64(rule[4:]) + ref.Value.Min = &f + } + } + + if strings.HasPrefix(rule, validationRuleKeyForMinLength) { + minlength := gconv.Uint64(rule[11:]) + ref.Value.MinLength = minlength + } + + if strings.HasPrefix(rule, validationRuleKeyForLength) { + lengthRule := gstr.Split(rule[7:], ",") + if len(lengthRule) == 2 { + minlength := gconv.Uint64(lengthRule[0]) + ref.Value.MinLength = minlength + maxlength := gconv.Uint64(lengthRule[1]) + ref.Value.MaxLength = &maxlength + } + } + + if strings.HasPrefix(rule, validationRuleKeyForBetween) { + if ref.Value.Type == "integer" || ref.Value.Type == "number" { + lengthRule := gstr.Split(rule[8:], ",") + if len(lengthRule) == 2 { + minimum := gconv.Float64(lengthRule[0]) + ref.Value.Min = &minimum + maximum := gconv.Float64(lengthRule[1]) + ref.Value.Max = &maximum + } + } + } + } } if !isValidParameterName(key) { ignoreProperties = append(ignoreProperties, key) diff --git a/net/goai/goai_shema_ref.go b/net/goai/goai_shema_ref.go index 1147618ca..63eef6894 100644 --- a/net/goai/goai_shema_ref.go +++ b/net/goai/goai_shema_ref.go @@ -19,8 +19,9 @@ import ( type SchemaRefs []SchemaRef type SchemaRef struct { - Ref string - Value *Schema + Ref string + Description string + Value *Schema } // isEmbeddedStructDefinition checks and returns whether given golang type is embedded struct definition, like: @@ -57,6 +58,7 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap case reflect.Ptr, reflect.Array, reflect.Slice: pkgPath = golangType.Elem().PkgPath() typeName = golangType.Elem().Name() + default: } } @@ -70,7 +72,7 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap } if len(tagMap) > 0 { - if err := oai.tagMapToSchema(tagMap, schema); err != nil { + if err = oai.tagMapToSchema(tagMap, schema); err != nil { return nil, err } if oaiType == TypeArray && schema.Type == TypeFile { @@ -78,7 +80,7 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap } } schemaRef.Value = schema - switch oaiType { + switch schema.Type { case TypeString, TypeFile: // Nothing to do. case TypeInteger: @@ -141,11 +143,9 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap case reflect.Interface: // Specially for interface type. - var ( - structTypeName = oai.golangTypeToSchemaName(golangType) - ) + var structTypeName = oai.golangTypeToSchemaName(golangType) if oai.Components.Schemas.Get(structTypeName) == nil { - if err := oai.addSchema(reflect.New(golangType).Interface()); err != nil { + if err = oai.addSchema(reflect.New(golangType).Interface()); err != nil { return nil, err } } @@ -164,12 +164,13 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap } else { var structTypeName = oai.golangTypeToSchemaName(golangType) if oai.Components.Schemas.Get(structTypeName) == nil { - if err := oai.addSchema(golangTypeInstance); err != nil { + if err = oai.addSchema(golangTypeInstance); err != nil { return nil, err } } schemaRef.Ref = structTypeName - schemaRef.Value = nil + schemaRef.Value = schema + schemaRef.Description = schema.Description } } } @@ -178,7 +179,7 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap func (r SchemaRef) MarshalJSON() ([]byte, error) { if r.Ref != "" { - return formatRefToBytes(r.Ref), nil + return formatRefAndDescToBytes(r.Ref, r.Description), nil } return json.Marshal(r.Value) } diff --git a/net/goai/goai_z_unit_issue_test.go b/net/goai/goai_z_unit_issue_test.go new file mode 100644 index 000000000..67fed9a26 --- /dev/null +++ b/net/goai/goai_z_unit_issue_test.go @@ -0,0 +1,351 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package goai_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/gogf/gf/v2/encoding/gjson" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/net/goai" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/guid" +) + +var ctx = context.Background() + +type Issue3664DefaultReq struct { + g.Meta `path:"/default" method:"post"` + Name string +} +type Issue3664DefaultRes struct{} + +type Issue3664RequiredTagReq struct { + g.Meta `path:"/required-tag" required:"true" method:"post"` + Name string +} +type Issue3664RequiredTagRes struct{} + +type Issue3664 struct{} + +func (Issue3664) Default(ctx context.Context, req *Issue3664DefaultReq) (res *Issue3664DefaultRes, err error) { + res = &Issue3664DefaultRes{} + return +} + +func (Issue3664) RequiredTag( + ctx context.Context, req *Issue3664RequiredTagReq, +) (res *Issue3664RequiredTagRes, err error) { + res = &Issue3664RequiredTagRes{} + return +} + +// https://github.com/gogf/gf/issues/3664 +func Test_Issue3664(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3664), + ) + }) + s.SetLogger(nil) + s.SetOpenApiPath("/api.json") + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + apiContent := c.GetBytes(ctx, "/api.json") + j, err := gjson.LoadJson(apiContent) + t.AssertNil(err) + t.Assert(j.Get(`paths./default.post.requestBody.required`).String(), "") + t.Assert(j.Get(`paths./required-tag.post.requestBody.required`).String(), "true") + }) +} + +type Issue3135DefaultReq struct { + g.Meta `path:"/demo/colors" method:"POST" summary:"颜色 - 保存" tags:"颜色管理" description:"颜色 - 保存"` + ID uint64 `json:"id,string" dc:"ID" v:"id-zero"` + Color string `json:"color" dc:"颜色值16进制表示法" v:"required|max-length:10"` + Rgba *gjson.Json `json:"rgba" dc:"颜色值RGBA表示法" v:"required|json" type:"string"` +} +type Issue3135DefaultRes struct{} + +type Issue3135 struct{} + +func (Issue3135) Default(ctx context.Context, req *Issue3135DefaultReq) (res *Issue3135DefaultRes, err error) { + res = &Issue3135DefaultRes{} + return +} + +// https://github.com/gogf/gf/issues/3135 +func Test_Issue3135(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3135), + ) + }) + s.SetLogger(nil) + s.SetOpenApiPath("/api.json") + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + + var ( + api = s.GetOpenApi() + reqPath = "github.com.gogf.gf.v2.net.goai_test.Issue3135DefaultReq" + rgbType = api.Components.Schemas.Get(reqPath).Value.Properties.Get("rgba").Value.Type + requiredArray = api.Components.Schemas.Get(reqPath).Value.Required + ) + t.Assert(rgbType, "string") + t.AssertIN("rgba", requiredArray) + }) +} + +type Issue3889CommonRes struct { + g.Meta `mime:"application/json"` + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data"` +} + +type Issue3889Req struct { + g.Meta `path:"/default" method:"post"` + Name string +} +type Issue3889Res struct { + g.Meta `status:"201" resEg:"testdata/Issue3889JsonFile/201.json"` + Info string `json:"info" eg:"Created!"` +} + +// Example case +type Issue3889Res401 struct{} + +// Override case 1 +type Issue3889Res402 struct { + g.Meta `mime:"application/json"` +} + +// Override case 2 +type Issue3889Res403 struct { + Code int `json:"code"` + Message string `json:"message"` +} + +// Common response case +type Issue3889Res404 struct{} + +var Issue3889ErrorRes = map[int][]gcode.Code{ + 401: { + gcode.New(1, "Aha, 401 - 1", nil), + gcode.New(2, "Aha, 401 - 2", nil), + }, +} + +func (r Issue3889Res) EnhanceResponseStatus() map[goai.EnhancedStatusCode]goai.EnhancedStatusType { + Codes401 := Issue3889ErrorRes[401] + // iterate Codes401 to generate Examples + var Examples401 []interface{} + for _, code := range Codes401 { + example := Issue3889CommonRes{ + Code: code.Code(), + Message: code.Message(), + Data: nil, + } + Examples401 = append(Examples401, example) + } + return map[goai.EnhancedStatusCode]goai.EnhancedStatusType{ + 401: { + Response: Issue3889Res401{}, + Examples: Examples401, + }, + 402: { + Response: Issue3889Res402{}, + }, + 403: { + Response: Issue3889Res403{}, + }, + 404: { + Response: Issue3889Res404{}, + }, + 500: { + Response: struct{}{}, + }, + 501: {}, + } +} + +type Issue3889 struct{} + +func (Issue3889) Default(ctx context.Context, req *Issue3889Req) (res *Issue3889Res, err error) { + res = &Issue3889Res{} + return +} + +// https://github.com/gogf/gf/issues/3889 +func Test_Issue3889(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + openapi := s.GetOpenApi() + openapi.Config.CommonResponse = Issue3889CommonRes{} + openapi.Config.CommonResponseDataField = `Data` + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3889), + ) + }) + s.SetLogger(nil) + s.SetOpenApiPath("/api.json") + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + apiContent := c.GetBytes(ctx, "/api.json") + j, err := gjson.LoadJson(apiContent) + + t.AssertNil(err) + t.Assert(j.Get(`paths./default.post.responses.200`).String(), "") + t.AssertNE(j.Get(`paths./default.post.responses.201`).String(), "") + t.AssertNE(j.Get(`paths./default.post.responses.401`).String(), "") + t.AssertNE(j.Get(`paths./default.post.responses.402`).String(), "") + t.AssertNE(j.Get(`paths./default.post.responses.403`).String(), "") + t.AssertNE(j.Get(`paths./default.post.responses.404`).String(), "") + t.AssertNE(j.Get(`paths./default.post.responses.500`).String(), "") + t.Assert(j.Get(`paths./default.post.responses.501`).String(), "") + // Check content + commonResponseSchema := `{"properties":{"code":{"format":"int","type":"integer"},"data":{"properties":{},"type":"object"},"message":{"format":"string","type":"string"}},"type":"object"}` + Status201ExamplesContent := `{"code 1":{"value":{"code":1,"data":"Good","message":"Aha, 201 - 1"}},"code 2":{"value":{"code":2,"data":"Not Bad","message":"Aha, 201 - 2"}}}` + Status401ExamplesContent := `{"example 1":{"value":{"code":1,"data":null,"message":"Aha, 401 - 1"}},"example 2":{"value":{"code":2,"data":null,"message":"Aha, 401 - 2"}}}` + Status402SchemaContent := `{"$ref":"#/components/schemas/github.com.gogf.gf.v2.net.goai_test.Issue3889Res402","description":""}` + Issue3889Res403Ref := `{"$ref":"#/components/schemas/github.com.gogf.gf.v2.net.goai_test.Issue3889Res403","description":""}` + + t.Assert(j.Get(`paths./default.post.responses.201.content.application/json.examples`).String(), Status201ExamplesContent) + t.Assert(j.Get(`paths./default.post.responses.401.content.application/json.examples`).String(), Status401ExamplesContent) + t.Assert(j.Get(`paths./default.post.responses.402.content.application/json.schema`).String(), Status402SchemaContent) + t.Assert(j.Get(`paths./default.post.responses.403.content.application/json.schema`).String(), Issue3889Res403Ref) + t.Assert(j.Get(`paths./default.post.responses.404.content.application/json.schema`).String(), commonResponseSchema) + t.Assert(j.Get(`paths./default.post.responses.500.content.application/json.schema`).String(), commonResponseSchema) + + api := s.GetOpenApi() + reqPath := "github.com.gogf.gf.v2.net.goai_test.Issue3889Res403" + schema := api.Components.Schemas.Get(reqPath).Value + + Issue3889Res403Schema := `{"properties":{"code":{"format":"int","type":"integer"},"message":{"format":"string","type":"string"}},"type":"object"}` + t.Assert(schema, Issue3889Res403Schema) + }) +} + +type Issue3930DefaultReq struct { + g.Meta `path:"/user/{id}" method:"get" tags:"User" summary:"Get one user"` + Id int64 `v:"required" dc:"user id"` +} +type Issue3930DefaultRes struct { + *Issue3930User `dc:"user"` +} +type Issue3930User struct { + Id uint `json:"id" orm:"id" description:"user id"` // user id +} + +type Issue3930 struct{} + +func (Issue3930) Default(ctx context.Context, req *Issue3930DefaultReq) (res *Issue3930DefaultRes, err error) { + res = &Issue3930DefaultRes{} + return +} + +// https://github.com/gogf/gf/issues/3930 +func Test_Issue3930(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3930), + ) + }) + s.SetLogger(nil) + s.SetOpenApiPath("/api.json") + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + + var ( + api = s.GetOpenApi() + reqPath = "github.com.gogf.gf.v2.net.goai_test.Issue3930DefaultRes" + ) + t.AssertNE(api.Components.Schemas.Get(reqPath).Value.Properties.Get("id"), nil) + }) +} + +type Issue3235DefaultReq struct { + g.Meta `path:"/user/{id}" method:"get" tags:"User" summary:"Get one user"` + Id int64 `v:"required" dc:"user id"` +} +type Issue3235DefaultRes struct { + Name string `dc:"test name desc"` + User *Issue3235User `dc:"test user desc"` +} +type Issue3235User struct { + Id uint `json:"id" orm:"id" description:"user id"` // user id +} + +type Issue3235 struct{} + +func (Issue3235) Default(ctx context.Context, req *Issue3235DefaultReq) (res *Issue3235DefaultRes, err error) { + res = &Issue3235DefaultRes{} + return +} + +// https://github.com/gogf/gf/issues/3235 +func Test_Issue3235(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3235), + ) + }) + s.SetLogger(nil) + s.SetOpenApiPath("/api.json") + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + + var ( + api = s.GetOpenApi() + reqPath = "github.com.gogf.gf.v2.net.goai_test.Issue3235DefaultRes" + ) + + t.Assert(api.Components.Schemas.Get(reqPath).Value.Properties.Get("Name").Value.Description, + "test name desc") + t.Assert(api.Components.Schemas.Get(reqPath).Value.Properties.Get("User").Description, + "test user desc") + }) +} diff --git a/net/goai/goai_z_unit_test.go b/net/goai/goai_z_unit_test.go index 323be669b..f7e5d53a4 100644 --- a/net/goai/goai_z_unit_test.go +++ b/net/goai/goai_z_unit_test.go @@ -54,13 +54,21 @@ func Test_Basic(t *testing.T) { t.AssertNil(err) // Schema asserts. t.Assert(len(oai.Components.Schemas.Map()), 2) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject) - t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`appId`).Value.Type, goai.TypeInteger) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString) + var ( + schemaCreate = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`) + schemaSetSpecInfo = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`) + ) - t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) + t.Assert(schemaCreate.Value.Type, goai.TypeObject) + t.Assert(len(schemaCreate.Value.Properties.Map()), 7) + t.Assert(schemaCreate.Value.Properties.Get(`appId`).Value.Type, goai.TypeInteger) + t.Assert(schemaCreate.Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString) + + t.Assert(len(schemaSetSpecInfo.Value.Properties.Map()), 3) + t.Assert(schemaSetSpecInfo.Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) + + // Schema Required. + t.AssertEQ(schemaCreate.Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) }) } @@ -114,17 +122,26 @@ func TestOpenApiV3_Add(t *testing.T) { // fmt.Println(oai.String()) // Schema asserts. t.Assert(len(oai.Components.Schemas.Map()), 3) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject) - t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7) - t.Assert(len(oai.Paths["/test1/{appId}"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) - t.Assert(len(oai.Paths["/test1/{appId}"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) + var ( + schemaCreate = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`) + schemaSetSpecInfo = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`) + schemaTest1 = oai.Paths["/test1/{appId}"].Put.RequestBody.Value.Content["application/json"].Schema + ) + t.Assert(schemaCreate.Value.Type, goai.TypeObject) + + t.Assert(len(schemaCreate.Value.Properties.Map()), 7) + t.Assert(len(schemaTest1.Value.Properties.Map()), 5) + t.Assert(len(schemaTest1.Value.Properties.Map()), 5) t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[0].Value.Schema.Value.Type, goai.TypeInteger) t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[1].Value.Schema.Value.Type, goai.TypeString) - t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) + t.Assert(len(schemaSetSpecInfo.Value.Properties.Map()), 3) + t.Assert(schemaSetSpecInfo.Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) + + // Schema Required. + t.AssertEQ(schemaCreate.Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) // Paths. t.Assert(len(oai.Paths), 1) @@ -168,8 +185,11 @@ func TestOpenApiV3_Add_Recursive(t *testing.T) { t.AssertNil(err) // Schema asserts. t.Assert(len(oai.Components.Schemas.Map()), 3) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Type, goai.TypeObject) - t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Properties.Map()), 3) + var ( + schemaCategoryTreeItem = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`) + ) + t.Assert(schemaCategoryTreeItem.Value.Type, goai.TypeObject) + t.Assert(len(schemaCategoryTreeItem.Value.Properties.Map()), 3) }) } @@ -285,7 +305,16 @@ func TestOpenApiV3_CommonRequest(t *testing.T) { // Schema asserts. t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) + var ( + schemaPut = oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + schemaRes = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`) + ) + t.Assert(len(schemaPut.Value.Properties.Map()), 3) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaRes.Value.Required, []string{"product", "templateName", "version", "txID"}) }) } @@ -346,10 +375,23 @@ func TestOpenApiV3_CommonRequest_WithoutDataField_Setting(t *testing.T) { // fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 4) t.Assert(len(oai.Paths), 1) + + var ( + schemaIndexPut = oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema + schemaIndexPost = oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema + schemaPutReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.PutReq`) + schemaRes = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`) + ) + t.Assert(len(oai.Paths["/index"].Put.Parameters), 2) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) + t.Assert(len(schemaIndexPut.Value.Properties.Map()), 3) t.Assert(len(oai.Paths["/index"].Post.Parameters), 0) - t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) + t.Assert(len(schemaIndexPost.Value.Properties.Map()), 5) + + // Schema Required. + t.AssertEQ(schemaPutReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaPutReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaRes.Value.Required, []string{"product", "templateName", "version", "txID"}) }) } @@ -389,7 +431,14 @@ func TestOpenApiV3_CommonRequest_EmptyRequest(t *testing.T) { // fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) + var ( + schemaIndex = oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + ) + t.Assert(len(schemaIndex.Value.Properties.Map()), 3) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) }) } @@ -460,10 +509,21 @@ func TestOpenApiV3_CommonRequest_SubDataField(t *testing.T) { // fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 5) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 2) - t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1) - t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 4) + var ( + schemaIndexPut = oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema + schemaIndexPost = oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema + schemaPutReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.PutReq`) + schemaRes = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`) + ) + t.Assert(len(schemaIndexPut.Value.Properties.Map()), 1) + t.Assert(len(schemaIndexPut.Value.Properties.Get(`Request`).Value.Properties.Map()), 2) + t.Assert(len(schemaIndexPost.Value.Properties.Map()), 1) + t.Assert(len(schemaIndexPost.Value.Properties.Get(`Request`).Value.Properties.Map()), 4) + + // Schema Required. + t.AssertEQ(schemaPutReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaPutReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaRes.Value.Required, []string{"product", "templateName", "version", "txID"}) }) } @@ -492,9 +552,9 @@ func TestOpenApiV3_CommonRequest_Files(t *testing.T) { }) t.AssertNil(err) - // fmt.Println(oai.String()) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Properties.Get("files").Value.Type, goai.TypeArray) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Properties.Get("file").Value.Type, goai.TypeFile) + var schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + t.Assert(schemaReq.Value.Properties.Get("files").Value.Type, goai.TypeArray) + t.Assert(schemaReq.Value.Properties.Get("file").Value.Type, goai.TypeFile) }) } @@ -537,15 +597,23 @@ func TestOpenApiV3_CommonResponse(t *testing.T) { }) t.AssertNil(err) - //g.Dump(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()) // Schema asserts. t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) + var ( + schemaIndexGet = oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + schemaRes = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`) + ) + t.Assert(len(schemaIndexGet.Value.Properties.Map()), 3) t.Assert( - oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get("data").Value.Description, + schemaIndexGet.Value.Properties.Get("data").Value.Description, `Result data for certain request according API definition`, ) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaRes.Value.Required, []string{"product", "templateName", "version", "txID"}) }) } @@ -590,7 +658,16 @@ func TestOpenApiV3_CommonResponse_WithoutDataField_Setting(t *testing.T) { fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8) + var ( + schemaIndexGet = oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + schemaRes = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`) + ) + t.Assert(len(schemaIndexGet.Value.Properties.Map()), 8) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaRes.Value.Required, []string{"product", "templateName", "version", "txID"}) }) } @@ -630,8 +707,16 @@ func TestOpenApiV3_CommonResponse_EmptyResponse(t *testing.T) { // fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Ref, `github.com.gogf.gf.v2.net.goai_test.Req`) - t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) + var ( + schemaIndexPut = oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema + schemeIndexPut200 = oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + ) + t.Assert(schemaIndexPut.Ref, `github.com.gogf.gf.v2.net.goai_test.Req`) + t.Assert(len(schemeIndexPut200.Value.Properties.Map()), 3) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) }) } @@ -686,8 +771,17 @@ func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) { // fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 4) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get(`Response`).Value.Properties.Map()), 7) + var ( + schemaGet = oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + schemaRes = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`) + ) + t.Assert(len(schemaGet.Value.Properties.Map()), 1) + t.Assert(len(schemaGet.Value.Properties.Get(`Response`).Value.Properties.Map()), 7) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) + t.AssertEQ(schemaRes.Value.Required, []string{"product", "templateName", "version", "txID"}) }) } @@ -703,7 +797,7 @@ func TestOpenApiV3_ShortTags(t *testing.T) { } type CreateResourceReq struct { CommonReq - gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum" dc:"CreateResourceReq des"` + gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"sm" dc:"CreateResourceReq des"` Name string `dc:"实例名称"` Product string `dc:"业务类型"` Region string `v:"required" dc:"区域"` @@ -738,15 +832,21 @@ func TestOpenApiV3_ShortTags(t *testing.T) { Object: f, }) t.AssertNil(err) - // fmt.Println(oai.String()) + // Schema asserts. t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(oai.Paths[`/test1/{appId}`].Summary, ``) t.Assert(oai.Paths[`/test1/{appId}`].Description, ``) - t.Assert(oai.Paths[`/test1/{appId}`].Put.Summary, `CreateResourceReq sum`) + t.Assert(oai.Paths[`/test1/{appId}`].Put.Summary, `sm`) t.Assert(oai.Paths[`/test1/{appId}`].Put.Description, `CreateResourceReq des`) t.Assert(oai.Paths[`/test1/{appId}`].Put.Parameters[1].Value.Schema.Value.Description, `资源Id`) - t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`Name`).Value.Description, `实例名称`) + var ( + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`) + ) + t.Assert(schemaReq.Value.Properties.Get(`Name`).Value.Description, `实例名称`) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) }) } @@ -875,6 +975,10 @@ func Test_Required_In_Schema(t *testing.T) { "CLOUD_SSD", "CLOUD_HSSD", }) + + // Schema Required. + var schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`) + t.AssertEQ(schemaReq.Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) }) } @@ -906,7 +1010,12 @@ func Test_Properties_In_Sequence(t *testing.T) { Object: req, }) t.AssertNil(err) - fmt.Println(oai) + + // Schema Required. + var schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.ResourceCreateReq`) + t.AssertEQ(schemaReq.Value.Required, []string{ + "AppId", "Uin", "CreateUin", "Product", "Region", "Zone", "Tenant", + }) }) } @@ -950,7 +1059,8 @@ func TestOpenApiV3_Ignore_Parameter(t *testing.T) { // fmt.Println(oai.String()) t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/test"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8) + var schemaTest = oai.Paths["/test"].Get.Responses["200"].Value.Content["application/json"].Schema + t.Assert(len(schemaTest.Value.Properties.Map()), 8) }) } @@ -971,12 +1081,16 @@ func Test_EnumOfSchemaItems(t *testing.T) { }) t.AssertNil(err) + var schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`) t.Assert( - oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. + schemaReq.Value. Properties.Get(`Members`).Value. Items.Value.Enum, g.Slice{"a", "b", "c"}, ) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"Members"}) }) } @@ -998,22 +1112,11 @@ func Test_AliasNameOfAttribute(t *testing.T) { }) t.AssertNil(err) - t.Assert( - oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. - Properties.Get(`Name`), nil, - ) - t.Assert( - oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. - Properties.Get(`Age`), nil, - ) - t.AssertNE( - oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. - Properties.Get(`n`), nil, - ) - t.AssertNE( - oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. - Properties.Get(`a`), nil, - ) + var schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`) + t.Assert(schemaReq.Value.Properties.Get(`Name`), nil) + t.Assert(schemaReq.Value.Properties.Get(`Age`), nil) + t.AssertNE(schemaReq.Value.Properties.Get(`n`), nil) + t.AssertNE(schemaReq.Value.Properties.Get(`a`), nil) }) } @@ -1039,7 +1142,7 @@ func Test_EmbeddedStructAttribute(t *testing.T) { b, err := json.Marshal(oai) t.AssertNil(err) - t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateResourceReq":{"properties":{"Name":{"description":"This is name.","format":"string","type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) + t.Assert(b, gtest.DataContent("EmbeddedStructAttribute", "expect.json")) }) } @@ -1063,7 +1166,7 @@ func Test_NameFromJsonTag(t *testing.T) { b, err := json.Marshal(oai) t.AssertNil(err) - t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) + t.Assert(b, gtest.DataContent("NameFromJsonTag", "expect1.json")) }) // GET gtest.C(t, func(t *gtest.T) { @@ -1084,7 +1187,7 @@ func Test_NameFromJsonTag(t *testing.T) { b, err := json.Marshal(oai) t.AssertNil(err) fmt.Println(string(b)) - t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) + t.Assert(b, gtest.DataContent("NameFromJsonTag", "expect2.json")) }) } @@ -1097,8 +1200,8 @@ func TestOpenApiV3_PathSecurity(t *testing.T) { type Req struct { gmeta.Meta `method:"PUT" security:"apiKey"` // 这里的apiKey要和openApi定义的key一致 - Product string `json:"product" v:"required" description:"Unique product key"` - Name string `json:"name" v:"required" description:"Instance name"` + Product string `json:"product" v:"required" description:"Unique product key"` + Name string `json:"name" v:"required" description:"Instance name"` } type Res struct{} @@ -1137,7 +1240,14 @@ func TestOpenApiV3_PathSecurity(t *testing.T) { t.Assert(len(oai.Components.SecuritySchemes), 1) t.Assert(oai.Components.SecuritySchemes["apiKey"].Value.Type, "apiKey") t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) + var ( + schemaIndex = oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema + schemaReq = oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`) + ) + t.Assert(len(schemaIndex.Value.Properties.Map()), 3) + + // Schema Required. + t.AssertEQ(schemaReq.Value.Required, []string{"product", "name"}) }) } @@ -1197,10 +1307,22 @@ func Test_Enums(t *testing.T) { t.AssertNil(err) var reqKey = "github.com.gogf.gf.v2.net.goai_test.Req" t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil) - t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status1").Value.Enum, g.Slice{"a", "b"}) - t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status2").Value.Enum, g.Slice{"a", "b"}) - t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status3").Value.Items.Value.Enum, g.Slice{"a", "b"}) - t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status4").Value.Items.Value.Enum, g.Slice{"a", "b"}) + t.Assert( + oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status1").Value.Enum, + g.Slice{"a", "b"}, + ) + t.Assert( + oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status2").Value.Enum, + g.Slice{"a", "b"}, + ) + t.Assert( + oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status3").Value.Items.Value.Enum, + g.Slice{"a", "b"}, + ) + t.Assert( + oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status4").Value.Items.Value.Enum, + g.Slice{"a", "b"}, + ) }) } @@ -1220,6 +1342,38 @@ func Test_XExtension(t *testing.T) { Object: req, }) t.AssertNil(err) - t.Assert(oai.String(), `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.GetListReq":{"properties":{"Page":{"default":1,"description":"Page number","format":"int","type":"integer","x-sort":"1"},"Size":{"default":10,"description":"Size for per page.","format":"int","type":"integer","x-sort":"2"}},"type":"object","x-group":"User/Info"}}},"info":{"title":"","version":""},"paths":null}`) + t.Assert(oai.String(), gtest.DataContent("XExtension", "expect.json")) + }) +} + +func Test_ValidationRules(t *testing.T) { + type Req struct { + g.Meta `path:"/rules" method:"POST" tags:"Rules" summary:"Validation rules."` + Name string `v:"required|min-length:3|max-length:32#required|min|max" dc:"Name"` + Age int `v:"required|min:1|max:100" dc:"Age"` + Grade int `v:"between:1,12#please enter the correct grade." dc:"Grade"` + Address string `v:"length:3,64" dc:"Address"` + } + + gtest.C(t, func(t *gtest.T) { + var ( + err error + oai = goai.New() + req = new(Req) + ) + err = oai.Add(goai.AddInput{ + Object: req, + }) + t.AssertNil(err) + + schema := oai.Components.Schemas.Get("github.com.gogf.gf.v2.net.goai_test.Req").Value + t.Assert(schema.Properties.Get("Name").Value.MinLength, 3) + t.Assert(schema.Properties.Get("Name").Value.MaxLength, 32) + t.Assert(schema.Properties.Get("Age").Value.Min, 1.0) + t.Assert(schema.Properties.Get("Age").Value.Max, 100.0) + t.Assert(schema.Properties.Get("Grade").Value.Min, 1.0) + t.Assert(schema.Properties.Get("Grade").Value.Max, 12.0) + t.Assert(schema.Properties.Get("Address").Value.MinLength, 3) + t.Assert(schema.Properties.Get("Address").Value.MaxLength, 64) }) } diff --git a/net/goai/testdata/EmbeddedStructAttribute/expect.json b/net/goai/testdata/EmbeddedStructAttribute/expect.json new file mode 100644 index 000000000..8b1af2a19 --- /dev/null +++ b/net/goai/testdata/EmbeddedStructAttribute/expect.json @@ -0,0 +1 @@ +{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateResourceReq":{"properties":{"Name":{"description":"This is name.","format":"string","type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null} \ No newline at end of file diff --git a/net/goai/testdata/Issue3889JsonFile/201.json b/net/goai/testdata/Issue3889JsonFile/201.json new file mode 100644 index 000000000..04938cc60 --- /dev/null +++ b/net/goai/testdata/Issue3889JsonFile/201.json @@ -0,0 +1,12 @@ +{ + "code 1": { + "code": 1, + "message": "Aha, 201 - 1", + "data": "Good" + }, + "code 2": { + "code": 2, + "message": "Aha, 201 - 2", + "data": "Not Bad" + } +} \ No newline at end of file diff --git a/net/goai/testdata/NameFromJsonTag/expect1.json b/net/goai/testdata/NameFromJsonTag/expect1.json new file mode 100644 index 000000000..8728a4b04 --- /dev/null +++ b/net/goai/testdata/NameFromJsonTag/expect1.json @@ -0,0 +1 @@ +{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null} \ No newline at end of file diff --git a/net/goai/testdata/NameFromJsonTag/expect2.json b/net/goai/testdata/NameFromJsonTag/expect2.json new file mode 100644 index 000000000..8728a4b04 --- /dev/null +++ b/net/goai/testdata/NameFromJsonTag/expect2.json @@ -0,0 +1 @@ +{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null} \ No newline at end of file diff --git a/net/goai/testdata/XExtension/expect.json b/net/goai/testdata/XExtension/expect.json new file mode 100644 index 000000000..4c03df752 --- /dev/null +++ b/net/goai/testdata/XExtension/expect.json @@ -0,0 +1 @@ +{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.GetListReq":{"properties":{"Page":{"default":1,"description":"Page number","format":"int","type":"integer","x-sort":"1"},"Size":{"default":10,"description":"Size for per page.","format":"int","type":"integer","x-sort":"2"}},"type":"object","x-group":"User/Info"}}},"info":{"title":"","version":""},"paths":null} \ No newline at end of file diff --git a/net/gudp/gudp_conn.go b/net/gudp/gudp_conn.go index ed4b61fd3..d12994ba9 100644 --- a/net/gudp/gudp_conn.go +++ b/net/gudp/gudp_conn.go @@ -14,85 +14,33 @@ import ( "github.com/gogf/gf/v2/errors/gerror" ) -// Conn handles the UDP connection. -type Conn struct { - *net.UDPConn // Underlying UDP connection. - remoteAddr *net.UDPAddr // Remote address. - deadlineRecv time.Time // Timeout point for reading data. - deadlineSend time.Time // Timeout point for writing data. - bufferWaitRecv time.Duration // Interval duration for reading buffer. +// localConn provides common operations for udp connection. +type localConn struct { + *net.UDPConn // Underlying UDP connection. + deadlineRecv time.Time // Timeout point for reading data. + deadlineSend time.Time // Timeout point for writing data. } const ( defaultRetryInterval = 100 * time.Millisecond // Retry interval. defaultReadBufferSize = 1024 // (Byte)Buffer size. - receiveAllWaitTimeout = time.Millisecond // Default interval for reading buffer. ) +// Retry holds the retry options. +// TODO replace with standalone retry package. type Retry struct { Count int // Max retry count. Interval time.Duration // Retry interval. } -// NewConn creates UDP connection to `remoteAddress`. -// The optional parameter `localAddress` specifies the local address for connection. -func NewConn(remoteAddress string, localAddress ...string) (*Conn, error) { - if conn, err := NewNetConn(remoteAddress, localAddress...); err == nil { - return NewConnByNetConn(conn), nil - } else { - return nil, err - } -} - -// NewConnByNetConn creates an UDP connection object with given *net.UDPConn object. -func NewConnByNetConn(udp *net.UDPConn) *Conn { - return &Conn{ - UDPConn: udp, - deadlineRecv: time.Time{}, - deadlineSend: time.Time{}, - bufferWaitRecv: receiveAllWaitTimeout, - } -} - -// Send writes data to remote address. -func (c *Conn) Send(data []byte, retry ...Retry) (err error) { - for { - if c.remoteAddr != nil { - _, err = c.WriteToUDP(data, c.remoteAddr) - } else { - _, err = c.Write(data) - } - if err != nil { - // Connection closed. - if err == io.EOF { - return err - } - // Still failed even after retrying. - if len(retry) == 0 || retry[0].Count == 0 { - err = gerror.Wrap(err, `Write data failed`) - return err - } - if len(retry) > 0 { - retry[0].Count-- - if retry[0].Interval == 0 { - retry[0].Interval = defaultRetryInterval - } - time.Sleep(retry[0].Interval) - } - } else { - return nil - } - } -} - // Recv receives and returns data from remote address. -// The parameter `buffer` is used for customizing the receiving buffer size. If `buffer` <= 0, -// it uses the default buffer size, which is 1024 byte. +// The parameter `buffer` is used for customizing the receiving buffer size. +// If `buffer` <= 0, it uses the default buffer size, which is 1024 byte. // // There's package border in UDP protocol, we can receive a complete package if specified // buffer size is big enough. VERY NOTE that we should receive the complete package in once // or else the leftover package data would be dropped. -func (c *Conn) Recv(buffer int, retry ...Retry) ([]byte, error) { +func (c *localConn) Recv(buffer int, retry ...Retry) ([]byte, *net.UDPAddr, error) { var ( err error // Reading error size int // Reading size @@ -106,9 +54,6 @@ func (c *Conn) Recv(buffer int, retry ...Retry) ([]byte, error) { } for { size, remoteAddr, err = c.ReadFromUDP(data) - if err == nil { - c.remoteAddr = remoteAddr - } if err != nil { // Connection closed. if err == io.EOF { @@ -131,51 +76,11 @@ func (c *Conn) Recv(buffer int, retry ...Retry) ([]byte, error) { } break } - return data[:size], err -} - -// SendRecv writes data to connection and blocks reading response. -func (c *Conn) SendRecv(data []byte, receive int, retry ...Retry) ([]byte, error) { - if err := c.Send(data, retry...); err != nil { - return nil, err - } - return c.Recv(receive, retry...) -} - -// RecvWithTimeout reads data from remote address with timeout. -func (c *Conn) RecvWithTimeout(length int, timeout time.Duration, retry ...Retry) (data []byte, err error) { - if err = c.SetDeadlineRecv(time.Now().Add(timeout)); err != nil { - return nil, err - } - defer func() { - _ = c.SetDeadlineRecv(time.Time{}) - }() - data, err = c.Recv(length, retry...) - return -} - -// SendWithTimeout writes data to connection with timeout. -func (c *Conn) SendWithTimeout(data []byte, timeout time.Duration, retry ...Retry) (err error) { - if err = c.SetDeadlineSend(time.Now().Add(timeout)); err != nil { - return err - } - defer func() { - _ = c.SetDeadlineSend(time.Time{}) - }() - err = c.Send(data, retry...) - return -} - -// SendRecvWithTimeout writes data to connection and reads response with timeout. -func (c *Conn) SendRecvWithTimeout(data []byte, receive int, timeout time.Duration, retry ...Retry) ([]byte, error) { - if err := c.Send(data, retry...); err != nil { - return nil, err - } - return c.RecvWithTimeout(receive, timeout, retry...) + return data[:size], remoteAddr, err } // SetDeadline sets the read and write deadlines associated with the connection. -func (c *Conn) SetDeadline(t time.Time) (err error) { +func (c *localConn) SetDeadline(t time.Time) (err error) { if err = c.UDPConn.SetDeadline(t); err == nil { c.deadlineRecv = t c.deadlineSend = t @@ -186,7 +91,7 @@ func (c *Conn) SetDeadline(t time.Time) (err error) { } // SetDeadlineRecv sets the read deadline associated with the connection. -func (c *Conn) SetDeadlineRecv(t time.Time) (err error) { +func (c *localConn) SetDeadlineRecv(t time.Time) (err error) { if err = c.SetReadDeadline(t); err == nil { c.deadlineRecv = t } else { @@ -196,7 +101,7 @@ func (c *Conn) SetDeadlineRecv(t time.Time) (err error) { } // SetDeadlineSend sets the deadline of sending for current connection. -func (c *Conn) SetDeadlineSend(t time.Time) (err error) { +func (c *localConn) SetDeadlineSend(t time.Time) (err error) { if err = c.SetWriteDeadline(t); err == nil { c.deadlineSend = t } else { @@ -204,15 +109,3 @@ func (c *Conn) SetDeadlineSend(t time.Time) (err error) { } return err } - -// SetBufferWaitRecv sets the buffer waiting timeout when reading all data from connection. -// The waiting duration cannot be too long which might delay receiving data from remote address. -func (c *Conn) SetBufferWaitRecv(d time.Duration) { - c.bufferWaitRecv = d -} - -// RemoteAddr returns the remote address of current UDP connection. -// Note that it cannot use c.conn.RemoteAddr() as it is nil. -func (c *Conn) RemoteAddr() net.Addr { - return c.remoteAddr -} diff --git a/net/gudp/gudp_conn_client_conn.go b/net/gudp/gudp_conn_client_conn.go new file mode 100644 index 000000000..e62842d42 --- /dev/null +++ b/net/gudp/gudp_conn_client_conn.go @@ -0,0 +1,69 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gudp + +import ( + "io" + "time" + + "github.com/gogf/gf/v2/errors/gerror" +) + +// ClientConn holds the client side connection. +type ClientConn struct { + *localConn +} + +// NewClientConn creates UDP connection to `remoteAddress`. +// The optional parameter `localAddress` specifies the local address for connection. +func NewClientConn(remoteAddress string, localAddress ...string) (*ClientConn, error) { + udpConn, err := NewNetConn(remoteAddress, localAddress...) + if err != nil { + return nil, err + } + return &ClientConn{ + localConn: &localConn{ + UDPConn: udpConn, + }, + }, nil +} + +// Send writes data to remote address. +func (c *ClientConn) Send(data []byte, retry ...Retry) (err error) { + for { + _, err = c.Write(data) + if err == nil { + return nil + } + // Connection closed. + if err == io.EOF { + return err + } + // Still failed even after retrying. + if len(retry) == 0 || retry[0].Count == 0 { + return gerror.Wrap(err, `Write data failed`) + } + if len(retry) > 0 { + retry[0].Count-- + if retry[0].Interval == 0 { + retry[0].Interval = defaultRetryInterval + } + time.Sleep(retry[0].Interval) + continue + } + return err + } +} + +// SendRecv writes data to connection and blocks reading response. +func (c *ClientConn) SendRecv(data []byte, receive int, retry ...Retry) ([]byte, error) { + if err := c.Send(data, retry...); err != nil { + return nil, err + } + result, _, err := c.Recv(receive, retry...) + return result, err +} diff --git a/net/gudp/gudp_conn_server_conn.go b/net/gudp/gudp_conn_server_conn.go new file mode 100644 index 000000000..56a5a0baf --- /dev/null +++ b/net/gudp/gudp_conn_server_conn.go @@ -0,0 +1,56 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gudp + +import ( + "io" + "net" + "time" + + "github.com/gogf/gf/v2/errors/gerror" +) + +// ServerConn holds the server side connection. +type ServerConn struct { + *localConn +} + +// NewServerConn creates an udp connection that listens to `localAddress`. +func NewServerConn(listenedConn *net.UDPConn) *ServerConn { + return &ServerConn{ + localConn: &localConn{ + UDPConn: listenedConn, + }, + } +} + +// Send writes data to remote address. +func (c *ServerConn) Send(data []byte, remoteAddr *net.UDPAddr, retry ...Retry) (err error) { + for { + _, err = c.WriteToUDP(data, remoteAddr) + if err == nil { + return nil + } + // Connection closed. + if err == io.EOF { + return err + } + // Still failed even after retrying. + if len(retry) == 0 || retry[0].Count == 0 { + return gerror.Wrap(err, `Write data failed`) + } + if len(retry) > 0 { + retry[0].Count-- + if retry[0].Interval == 0 { + retry[0].Interval = defaultRetryInterval + } + time.Sleep(retry[0].Interval) + continue + } + return err + } +} diff --git a/net/gudp/gudp_func.go b/net/gudp/gudp_func.go index be2770f6f..32e4e8a05 100644 --- a/net/gudp/gudp_func.go +++ b/net/gudp/gudp_func.go @@ -52,7 +52,7 @@ func NewNetConn(remoteAddress string, localAddress ...string) (*net.UDPConn, err // Send writes data to `address` using UDP connection and then closes the connection. // Note that it is used for short connection usage. func Send(address string, data []byte, retry ...Retry) error { - conn, err := NewConn(address) + conn, err := NewClientConn(address) if err != nil { return err } @@ -63,7 +63,7 @@ func Send(address string, data []byte, retry ...Retry) error { // SendRecv writes data to `address` using UDP connection, reads response and then closes the connection. // Note that it is used for short connection usage. func SendRecv(address string, data []byte, receive int, retry ...Retry) ([]byte, error) { - conn, err := NewConn(address) + conn, err := NewClientConn(address) if err != nil { return nil, err } @@ -72,6 +72,8 @@ func SendRecv(address string, data []byte, receive int, retry ...Retry) ([]byte, } // MustGetFreePort performs as GetFreePort, but it panics if any error occurs. +// Deprecated: the port might be used soon after they were returned, please use `:0` as the listening +// address which asks system to assign a free port instead. func MustGetFreePort() (port int) { port, err := GetFreePort() if err != nil { @@ -81,6 +83,8 @@ func MustGetFreePort() (port int) { } // GetFreePort retrieves and returns a port that is free. +// Deprecated: the port might be used soon after they were returned, please use `:0` as the listening +// address which asks system to assign a free port instead. func GetFreePort() (port int, err error) { var ( network = `udp` @@ -108,6 +112,8 @@ func GetFreePort() (port int, err error) { } // GetFreePorts retrieves and returns specified number of ports that are free. +// Deprecated: the ports might be used soon after they were returned, please use `:0` as the listening +// address which asks system to assign a free port instead. func GetFreePorts(count int) (ports []int, err error) { var ( network = `udp` diff --git a/net/gudp/gudp_server.go b/net/gudp/gudp_server.go index c60edd8e9..0ace0996e 100644 --- a/net/gudp/gudp_server.go +++ b/net/gudp/gudp_server.go @@ -29,18 +29,29 @@ const ( // Server is the UDP server. type Server struct { - mu sync.Mutex // Used for Server.listen concurrent safety. -- The golang test with data race checks this. - conn *Conn // UDP server connection object. - address string // UDP server listening address. - handler func(*Conn) // Handler for UDP connection. + // Used for Server.listen concurrent safety. + // The golang test with data race checks this. + mu sync.Mutex + + // UDP server connection object. + conn *ServerConn + + // UDP server listening address. + address string + + // Handler for UDP connection. + handler ServerHandler } +// ServerHandler handles all server connections. +type ServerHandler func(conn *ServerConn) + var ( // serverMapping is used for instance name to its UDP server mappings. serverMapping = gmap.NewStrAnyMap(true) ) -// GetServer creates and returns an UDP server instance with given name. +// GetServer creates and returns an udp server instance with given name. func GetServer(name ...interface{}) *Server { serverName := defaultServer if len(name) > 0 && name[0] != "" { @@ -54,10 +65,10 @@ func GetServer(name ...interface{}) *Server { return s } -// NewServer creates and returns an UDP server. +// NewServer creates and returns an udp server. // The optional parameter `name` is used to specify its name, which can be used for // GetServer function to retrieve its instance. -func NewServer(address string, handler func(*Conn), name ...string) *Server { +func NewServer(address string, handler ServerHandler, name ...string) *Server { s := &Server{ address: address, handler: handler, @@ -74,7 +85,7 @@ func (s *Server) SetAddress(address string) { } // SetHandler sets the connection handler for UDP server. -func (s *Server) SetHandler(handler func(*Conn)) { +func (s *Server) SetHandler(handler ServerHandler) { s.handler = handler } @@ -93,21 +104,23 @@ func (s *Server) Close() (err error) { // Run starts listening UDP connection. func (s *Server) Run() error { if s.handler == nil { - err := gerror.NewCode(gcode.CodeMissingConfiguration, "start running failed: socket handler not defined") - return err + return gerror.NewCode( + gcode.CodeMissingConfiguration, + "start running failed: socket handler not defined", + ) } addr, err := net.ResolveUDPAddr("udp", s.address) if err != nil { err = gerror.Wrapf(err, `net.ResolveUDPAddr failed for address "%s"`, s.address) return err } - conn, err := net.ListenUDP("udp", addr) + listenedConn, err := net.ListenUDP("udp", addr) if err != nil { err = gerror.Wrapf(err, `net.ListenUDP failed for address "%s"`, s.address) return err } s.mu.Lock() - s.conn = NewConnByNetConn(conn) + s.conn = NewServerConn(listenedConn) s.mu.Unlock() s.handler(s.conn) return nil diff --git a/net/gudp/gudp_z_unit_test.go b/net/gudp/gudp_z_unit_test.go index ca7b794bd..505d59e11 100644 --- a/net/gudp/gudp_z_unit_test.go +++ b/net/gudp/gudp_z_unit_test.go @@ -25,17 +25,17 @@ var ( ) func startUDPServer(addr string) *gudp.Server { - s := gudp.NewServer(addr, func(conn *gudp.Conn) { + s := gudp.NewServer(addr, func(conn *gudp.ServerConn) { defer conn.Close() for { - data, err := conn.Recv(-1) + data, remote, err := conn.Recv(-1) if err != nil { if err != io.EOF { glog.Error(context.TODO(), err) } break } - if err = conn.Send(data); err != nil { + if err = conn.Send(data, remote); err != nil { glog.Error(context.TODO(), err) } } @@ -47,12 +47,12 @@ func startUDPServer(addr string) *gudp.Server { func Test_Basic(t *testing.T) { var ctx = context.TODO() - s := gudp.NewServer(gudp.FreePortAddress, func(conn *gudp.Conn) { + s := gudp.NewServer(gudp.FreePortAddress, func(conn *gudp.ServerConn) { defer conn.Close() for { - data, err := conn.Recv(-1) + data, remote, err := conn.Recv(-1) if len(data) > 0 { - if err := conn.Send(append([]byte("> "), data...)); err != nil { + if err = conn.Send(append([]byte("> "), data...), remote); err != nil { glog.Error(ctx, err) } } @@ -63,15 +63,17 @@ func Test_Basic(t *testing.T) { }) go s.Run() defer s.Close() + time.Sleep(100 * time.Millisecond) + // gudp.Conn.Send gtest.C(t, func(t *gtest.T) { for i := 0; i < 100; i++ { - conn, err := gudp.NewConn(s.GetListenedAddress()) + conn, err := gudp.NewClientConn(s.GetListenedAddress()) t.AssertNil(err) t.Assert(conn.Send([]byte(gconv.String(i))), nil) - t.AssertNil(conn.RemoteAddr()) - result, err := conn.Recv(-1) + t.AssertNE(conn.RemoteAddr(), nil) + result, _, err := conn.Recv(-1) t.AssertNil(err) t.AssertNE(conn.RemoteAddr(), nil) t.Assert(string(result), fmt.Sprintf(`> %d`, i)) @@ -81,49 +83,15 @@ func Test_Basic(t *testing.T) { // gudp.Conn.SendRecv gtest.C(t, func(t *gtest.T) { for i := 0; i < 100; i++ { - conn, err := gudp.NewConn(s.GetListenedAddress()) + conn, err := gudp.NewClientConn(s.GetListenedAddress()) t.AssertNil(err) - _, err = conn.SendRecv([]byte(gconv.String(i)), -1) - t.AssertNil(err) - //t.Assert(string(result), fmt.Sprintf(`> %d`, i)) - conn.Close() - } - }) - // gudp.Conn.SendWithTimeout - gtest.C(t, func(t *gtest.T) { - for i := 0; i < 100; i++ { - conn, err := gudp.NewConn(s.GetListenedAddress()) - t.AssertNil(err) - err = conn.SendWithTimeout([]byte(gconv.String(i)), time.Second) - t.AssertNil(err) - conn.Close() - } - }) - // gudp.Conn.RecvWithTimeout - gtest.C(t, func(t *gtest.T) { - for i := 0; i < 100; i++ { - conn, err := gudp.NewConn(s.GetListenedAddress()) - t.AssertNil(err) - err = conn.Send([]byte(gconv.String(i))) - t.AssertNil(err) - conn.SetBufferWaitRecv(time.Millisecond * 100) - result, err := conn.RecvWithTimeout(-1, time.Second) - t.AssertNil(err) - t.Assert(string(result), fmt.Sprintf(`> %d`, i)) - conn.Close() - } - }) - // gudp.Conn.SendRecvWithTimeout - gtest.C(t, func(t *gtest.T) { - for i := 0; i < 100; i++ { - conn, err := gudp.NewConn(s.GetListenedAddress()) - t.AssertNil(err) - result, err := conn.SendRecvWithTimeout([]byte(gconv.String(i)), -1, time.Second) + result, err := conn.SendRecv([]byte(gconv.String(i)), -1) t.AssertNil(err) t.Assert(string(result), fmt.Sprintf(`> %d`, i)) conn.Close() } }) + // gudp.Send gtest.C(t, func(t *gtest.T) { for i := 0; i < 100; i++ { @@ -145,12 +113,12 @@ func Test_Basic(t *testing.T) { // the rest data would be dropped. func Test_Buffer(t *testing.T) { var ctx = context.TODO() - s := gudp.NewServer(gudp.FreePortAddress, func(conn *gudp.Conn) { + s := gudp.NewServer(gudp.FreePortAddress, func(conn *gudp.ServerConn) { defer conn.Close() for { - data, err := conn.Recv(1) + data, remote, err := conn.Recv(-1) if len(data) > 0 { - if err := conn.Send(data); err != nil { + if err = conn.Send(data, remote); err != nil { glog.Error(ctx, err) } } @@ -165,12 +133,12 @@ func Test_Buffer(t *testing.T) { gtest.C(t, func(t *gtest.T) { result, err := gudp.SendRecv(s.GetListenedAddress(), []byte("123"), -1) t.AssertNil(err) - t.Assert(string(result), "1") + t.Assert(string(result), "123") }) gtest.C(t, func(t *gtest.T) { result, err := gudp.SendRecv(s.GetListenedAddress(), []byte("456"), -1) t.AssertNil(err) - t.Assert(string(result), "4") + t.Assert(string(result), "456") }) } @@ -178,7 +146,7 @@ func Test_NewConn(t *testing.T) { s := startUDPServer(gudp.FreePortAddress) gtest.C(t, func(t *gtest.T) { - conn, err := gudp.NewConn(s.GetListenedAddress(), fmt.Sprintf("127.0.0.1:%d", gudp.MustGetFreePort())) + conn, err := gudp.NewClientConn(s.GetListenedAddress(), fmt.Sprintf("127.0.0.1:%d", gudp.MustGetFreePort())) t.AssertNil(err) conn.SetDeadline(time.Now().Add(time.Second)) t.Assert(conn.Send(sendData), nil) @@ -186,13 +154,13 @@ func Test_NewConn(t *testing.T) { }) gtest.C(t, func(t *gtest.T) { - conn, err := gudp.NewConn(s.GetListenedAddress(), fmt.Sprintf("127.0.0.1:%d", 99999)) + conn, err := gudp.NewClientConn(s.GetListenedAddress(), fmt.Sprintf("127.0.0.1:%d", 99999)) t.AssertNil(conn) t.AssertNE(err, nil) }) gtest.C(t, func(t *gtest.T) { - conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", 99999)) + conn, err := gudp.NewClientConn(fmt.Sprintf("127.0.0.1:%d", 99999)) t.AssertNil(conn) t.AssertNE(err, nil) }) @@ -207,12 +175,15 @@ func Test_GetFreePorts(t *testing.T) { } func Test_Server(t *testing.T) { - gudp.NewServer(gudp.FreePortAddress, func(conn *gudp.Conn) { + var ctx = context.TODO() + gudp.NewServer(gudp.FreePortAddress, func(conn *gudp.ServerConn) { defer conn.Close() for { - data, err := conn.Recv(1) + data, remote, err := conn.Recv(-1) if len(data) > 0 { - conn.Send(data) + if err = conn.Send(data, remote); err != nil { + glog.Error(ctx, err) + } } if err != nil { break @@ -226,11 +197,8 @@ func Test_Server(t *testing.T) { server = gudp.GetServer("TestUDPServer") t.AssertNE(server, nil) server.SetAddress("127.0.0.1:8888") - server.SetHandler(func(conn *gudp.Conn) { - defer conn.Close() - for { - conn.Send([]byte("OtherHandle")) - } + server.SetHandler(func(conn *gudp.ServerConn) { + _ = conn.Send([]byte("OtherHandle"), nil) }) }) } diff --git a/os/gcache/gcache.go b/os/gcache/gcache.go index 645508b78..8aaf6652f 100644 --- a/os/gcache/gcache.go +++ b/os/gcache/gcache.go @@ -17,7 +17,7 @@ import ( ) // Func is the cache function that calculates and returns the value. -type Func func(ctx context.Context) (value interface{}, err error) +type Func = func(ctx context.Context) (value interface{}, err error) const ( DurationNoExpire = time.Duration(0) // Expire duration that never expires. diff --git a/os/gcache/gcache_adapter_memory.go b/os/gcache/gcache_adapter_memory.go index 9502b5491..aceb0dc39 100644 --- a/os/gcache/gcache_adapter_memory.go +++ b/os/gcache/gcache_adapter_memory.go @@ -21,24 +21,12 @@ import ( // AdapterMemory is an adapter implements using memory. type AdapterMemory struct { - // cap limits the size of the cache pool. - // If the size of the cache exceeds the cap, - // the cache expiration process performs according to the LRU algorithm. - // It is 0 in default which means no limits. - cap int - data *adapterMemoryData // data is the underlying cache data which is stored in a hash table. - expireTimes *adapterMemoryExpireTimes // expireTimes is the expiring key to its timestamp mapping, which is used for quick indexing and deleting. - expireSets *adapterMemoryExpireSets // expireSets is the expiring timestamp to its key set mapping, which is used for quick indexing and deleting. - lru *adapterMemoryLru // lru is the LRU manager, which is enabled when attribute cap > 0. - lruGetList *glist.List // lruGetList is the LRU history according to Get function. - eventList *glist.List // eventList is the asynchronous event list for internal data synchronization. - closed *gtype.Bool // closed controls the cache closed or not. -} - -// Internal cache item. -type adapterMemoryItem struct { - v interface{} // Value. - e int64 // Expire timestamp in milliseconds. + data *memoryData // data is the underlying cache data which is stored in a hash table. + expireTimes *memoryExpireTimes // expireTimes is the expiring key to its timestamp mapping, which is used for quick indexing and deleting. + expireSets *memoryExpireSets // expireSets is the expiring timestamp to its key set mapping, which is used for quick indexing and deleting. + lru *memoryLru // lru is the LRU manager, which is enabled when attribute cap > 0. + eventList *glist.List // eventList is the asynchronous event list for internal data synchronization. + closed *gtype.Bool // closed controls the cache closed or not. } // Internal event item. @@ -53,21 +41,28 @@ const ( defaultMaxExpire = 9223372036854 ) -// NewAdapterMemory creates and returns a new memory cache object. -func NewAdapterMemory(lruCap ...int) Adapter { +// NewAdapterMemory creates and returns a new adapter_memory cache object. +func NewAdapterMemory() *AdapterMemory { + return doNewAdapterMemory() +} + +// NewAdapterMemoryLru creates and returns a new adapter_memory cache object with LRU. +func NewAdapterMemoryLru(cap int) *AdapterMemory { + c := doNewAdapterMemory() + c.lru = newMemoryLru(cap) + return c +} + +// doNewAdapterMemory creates and returns a new adapter_memory cache object. +func doNewAdapterMemory() *AdapterMemory { c := &AdapterMemory{ - data: newAdapterMemoryData(), - lruGetList: glist.New(true), - expireTimes: newAdapterMemoryExpireTimes(), - expireSets: newAdapterMemoryExpireSets(), + data: newMemoryData(), + expireTimes: newMemoryExpireTimes(), + expireSets: newMemoryExpireSets(), eventList: glist.New(true), closed: gtype.NewBool(), } - if len(lruCap) > 0 { - c.cap = lruCap[0] - c.lru = newMemCacheLru(c) - } - // Here may be a "timer leak" if adapter is manually changed from memory adapter. + // Here may be a "timer leak" if adapter is manually changed from adapter_memory adapter. // Do not worry about this, as adapter is less changed, and it does nothing if it's not used. gtimer.AddSingleton(context.Background(), time.Second, c.syncEventAndClearExpired) return c @@ -78,8 +73,9 @@ func NewAdapterMemory(lruCap ...int) Adapter { // It does not expire if `duration` == 0. // It deletes the keys of `data` if `duration` < 0 or given `value` is nil. func (c *AdapterMemory) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error { + defer c.handleLruKey(ctx, key) expireTime := c.getInternalExpire(duration) - c.data.Set(key, adapterMemoryItem{ + c.data.Set(key, memoryDataItem{ v: value, e: expireTime, }) @@ -108,6 +104,11 @@ func (c *AdapterMemory) SetMap(ctx context.Context, data map[interface{}]interfa e: expireTime, }) } + if c.lru != nil { + for key := range data { + c.handleLruKey(ctx, key) + } + } return nil } @@ -118,6 +119,7 @@ func (c *AdapterMemory) SetMap(ctx context.Context, data map[interface{}]interfa // It does not expire if `duration` == 0. // It deletes the `key` if `duration` < 0 or given `value` is nil. func (c *AdapterMemory) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (bool, error) { + defer c.handleLruKey(ctx, key) isContained, err := c.Contains(ctx, key) if err != nil { return false, err @@ -140,6 +142,7 @@ func (c *AdapterMemory) SetIfNotExist(ctx context.Context, key interface{}, valu // It does not expire if `duration` == 0. // It deletes the `key` if `duration` < 0 or given `value` is nil. func (c *AdapterMemory) SetIfNotExistFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (bool, error) { + defer c.handleLruKey(ctx, key) isContained, err := c.Contains(ctx, key) if err != nil { return false, err @@ -166,6 +169,7 @@ func (c *AdapterMemory) SetIfNotExistFunc(ctx context.Context, key interface{}, // Note that it differs from function `SetIfNotExistFunc` is that the function `f` is executed within // writing mutex lock for concurrent safety purpose. func (c *AdapterMemory) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (bool, error) { + defer c.handleLruKey(ctx, key) isContained, err := c.Contains(ctx, key) if err != nil { return false, err @@ -185,10 +189,7 @@ func (c *AdapterMemory) SetIfNotExistFuncLock(ctx context.Context, key interface func (c *AdapterMemory) Get(ctx context.Context, key interface{}) (*gvar.Var, error) { item, ok := c.data.Get(key) if ok && !item.IsExpired() { - // Adding to LRU history if LRU feature is enabled. - if c.cap > 0 { - c.lruGetList.PushBack(key) - } + c.handleLruKey(ctx, key) return gvar.New(item.v), nil } return nil, nil @@ -202,6 +203,7 @@ func (c *AdapterMemory) Get(ctx context.Context, key interface{}) (*gvar.Var, er // It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing // if `value` is a function and the function result is nil. func (c *AdapterMemory) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (*gvar.Var, error) { + defer c.handleLruKey(ctx, key) v, err := c.Get(ctx, key) if err != nil { return nil, err @@ -220,6 +222,7 @@ func (c *AdapterMemory) GetOrSet(ctx context.Context, key interface{}, value int // It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing // if `value` is a function and the function result is nil. func (c *AdapterMemory) GetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (*gvar.Var, error) { + defer c.handleLruKey(ctx, key) v, err := c.Get(ctx, key) if err != nil { return nil, err @@ -248,6 +251,7 @@ func (c *AdapterMemory) GetOrSetFunc(ctx context.Context, key interface{}, f Fun // Note that it differs from function `GetOrSetFunc` is that the function `f` is executed within // writing mutex lock for concurrent safety purpose. func (c *AdapterMemory) GetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (*gvar.Var, error) { + defer c.handleLruKey(ctx, key) v, err := c.Get(ctx, key) if err != nil { return nil, err @@ -274,6 +278,7 @@ func (c *AdapterMemory) Contains(ctx context.Context, key interface{}) (bool, er // It returns -1 if the `key` does not exist in the cache. func (c *AdapterMemory) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) { if item, ok := c.data.Get(key); ok { + c.handleLruKey(ctx, key) return time.Duration(item.e-gtime.TimestampMilli()) * time.Millisecond, nil } return -1, nil @@ -282,6 +287,11 @@ func (c *AdapterMemory) GetExpire(ctx context.Context, key interface{}) (time.Du // Remove deletes one or more keys from cache, and returns its value. // If multiple keys are given, it returns the value of the last deleted item. func (c *AdapterMemory) Remove(ctx context.Context, keys ...interface{}) (*gvar.Var, error) { + defer c.lru.Remove(keys...) + return c.doRemove(ctx, keys...) +} + +func (c *AdapterMemory) doRemove(_ context.Context, keys ...interface{}) (*gvar.Var, error) { var removedKeys []interface{} removedKeys, value, err := c.data.Remove(keys...) if err != nil { @@ -290,7 +300,7 @@ func (c *AdapterMemory) Remove(ctx context.Context, keys ...interface{}) (*gvar. for _, key := range removedKeys { c.eventList.PushBack(&adapterMemoryEvent{ k: key, - e: gtime.TimestampMilli() - 1000000, + e: gtime.TimestampMilli() - 1000, }) } return gvar.New(value), nil @@ -303,6 +313,9 @@ func (c *AdapterMemory) Remove(ctx context.Context, keys ...interface{}) (*gvar. // It does nothing if `key` does not exist in the cache. func (c *AdapterMemory) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) { v, exist, err := c.data.Update(key, value) + if exist { + c.handleLruKey(ctx, key) + } return gvar.New(v), exist, err } @@ -321,6 +334,7 @@ func (c *AdapterMemory) UpdateExpire(ctx context.Context, key interface{}, durat k: key, e: newExpireTime, }) + c.handleLruKey(ctx, key) } return } @@ -348,14 +362,13 @@ func (c *AdapterMemory) Values(ctx context.Context) ([]interface{}, error) { // Clear clears all data of the cache. // Note that this function is sensitive and should be carefully used. func (c *AdapterMemory) Clear(ctx context.Context) error { - return c.data.Clear() + c.data.Clear() + c.lru.Clear() + return nil } // Close closes the cache. func (c *AdapterMemory) Close(ctx context.Context) error { - if c.cap > 0 { - c.lru.Close() - } c.closed.Set(true) return nil } @@ -390,9 +403,9 @@ func (c *AdapterMemory) makeExpireKey(expire int64) int64 { } // syncEventAndClearExpired does the asynchronous task loop: -// 1. Asynchronously process the data in the event list, -// and synchronize the results to the `expireTimes` and `expireSets` properties. -// 2. Clean up the expired key-value pair data. +// 1. Asynchronously process the data in the event list, +// and synchronize the results to the `expireTimes` and `expireSets` properties. +// 2. Clean up the expired key-value pair data. func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) { if c.closed.Val() { gtimer.Exit() @@ -403,9 +416,9 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) { oldExpireTime int64 newExpireTime int64 ) - // ======================== - // Data Synchronization. - // ======================== + // ================================ + // Data expiration synchronization. + // ================================ for { v := c.eventList.PopFront() if v == nil { @@ -416,45 +429,33 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) { oldExpireTime = c.expireTimes.Get(event.k) // Calculating the new expiration time set. newExpireTime = c.makeExpireKey(event.e) + // Expiration changed for this key. if newExpireTime != oldExpireTime { c.expireSets.GetOrNew(newExpireTime).Add(event.k) if oldExpireTime != 0 { c.expireSets.GetOrNew(oldExpireTime).Remove(event.k) } - // Updating the expired time for . + // Updating the expired time for `event.k`. c.expireTimes.Set(event.k, newExpireTime) } - // Adding the key the LRU history by writing operations. - if c.cap > 0 { - c.lru.Push(event.k) - } } - // Processing expired keys from LRU. - if c.cap > 0 { - if c.lruGetList.Len() > 0 { - for { - if v := c.lruGetList.PopFront(); v != nil { - c.lru.Push(v) - } else { - break - } - } - } - c.lru.SyncAndClear(ctx) - } - // ======================== - // Data Cleaning up. - // ======================== + // ================================= + // Data expiration auto cleaning up. + // ================================= var ( - expireSet *gset.Set - ek = c.makeExpireKey(gtime.TimestampMilli()) - eks = []int64{ek - 1000, ek - 2000, ek - 3000, ek - 4000, ek - 5000} + expireSet *gset.Set + expireTime int64 + currentEk = c.makeExpireKey(gtime.TimestampMilli()) ) - for _, expireTime := range eks { + // auto removing expiring key set for latest seconds. + for i := int64(1); i <= 5; i++ { + expireTime = currentEk - i*1000 if expireSet = c.expireSets.Get(expireTime); expireSet != nil { // Iterating the set to delete all keys in it. expireSet.Iterator(func(key interface{}) bool { - c.clearByKey(key) + c.deleteExpiredKey(key) + // remove auto expired key for lru. + c.lru.Remove(key) return true }) // Deleting the set after all of its keys are deleted. @@ -463,17 +464,22 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) { } } +func (c *AdapterMemory) handleLruKey(ctx context.Context, keys ...interface{}) { + if c.lru == nil { + return + } + if evictedKeys := c.lru.SaveAndEvict(keys...); len(evictedKeys) > 0 { + _, _ = c.doRemove(ctx, evictedKeys...) + return + } + return +} + // clearByKey deletes the key-value pair with given `key`. // The parameter `force` specifies whether doing this deleting forcibly. -func (c *AdapterMemory) clearByKey(key interface{}, force ...bool) { +func (c *AdapterMemory) deleteExpiredKey(key interface{}) { // Doubly check before really deleting it from cache. - c.data.DeleteWithDoubleCheck(key, force...) - + c.data.Delete(key) // Deleting its expiration time from `expireTimes`. c.expireTimes.Delete(key) - - // Deleting it from LRU. - if c.cap > 0 { - c.lru.Remove(key) - } } diff --git a/os/gcache/gcache_adapter_memory_data.go b/os/gcache/gcache_adapter_memory_data.go index 941339d0f..ddd0c5fae 100644 --- a/os/gcache/gcache_adapter_memory_data.go +++ b/os/gcache/gcache_adapter_memory_data.go @@ -14,14 +14,20 @@ import ( "github.com/gogf/gf/v2/os/gtime" ) -type adapterMemoryData struct { - mu sync.RWMutex // dataMu ensures the concurrent safety of underlying data map. - data map[interface{}]adapterMemoryItem // data is the underlying cache data which is stored in a hash table. +type memoryData struct { + mu sync.RWMutex // dataMu ensures the concurrent safety of underlying data map. + data map[interface{}]memoryDataItem // data is the underlying cache data which is stored in a hash table. } -func newAdapterMemoryData() *adapterMemoryData { - return &adapterMemoryData{ - data: make(map[interface{}]adapterMemoryItem), +// memoryDataItem holds the internal cache item data. +type memoryDataItem struct { + v interface{} // Value. + e int64 // Expire timestamp in milliseconds. +} + +func newMemoryData() *memoryData { + return &memoryData{ + data: make(map[interface{}]memoryDataItem), } } @@ -30,11 +36,11 @@ func newAdapterMemoryData() *adapterMemoryData { // // It deletes the `key` if given `value` is nil. // It does nothing if `key` does not exist in the cache. -func (d *adapterMemoryData) Update(key interface{}, value interface{}) (oldValue interface{}, exist bool, err error) { +func (d *memoryData) Update(key interface{}, value interface{}) (oldValue interface{}, exist bool, err error) { d.mu.Lock() defer d.mu.Unlock() if item, ok := d.data[key]; ok { - d.data[key] = adapterMemoryItem{ + d.data[key] = memoryDataItem{ v: value, e: item.e, } @@ -47,11 +53,11 @@ func (d *adapterMemoryData) Update(key interface{}, value interface{}) (oldValue // // It returns -1 and does nothing if the `key` does not exist in the cache. // It deletes the `key` if `duration` < 0. -func (d *adapterMemoryData) UpdateExpire(key interface{}, expireTime int64) (oldDuration time.Duration, err error) { +func (d *memoryData) UpdateExpire(key interface{}, expireTime int64) (oldDuration time.Duration, err error) { d.mu.Lock() defer d.mu.Unlock() if item, ok := d.data[key]; ok { - d.data[key] = adapterMemoryItem{ + d.data[key] = memoryDataItem{ v: item.v, e: expireTime, } @@ -62,7 +68,7 @@ func (d *adapterMemoryData) UpdateExpire(key interface{}, expireTime int64) (old // Remove deletes the one or more keys from cache, and returns its value. // If multiple keys are given, it returns the value of the deleted last item. -func (d *adapterMemoryData) Remove(keys ...interface{}) (removedKeys []interface{}, value interface{}, err error) { +func (d *memoryData) Remove(keys ...interface{}) (removedKeys []interface{}, value interface{}, err error) { d.mu.Lock() defer d.mu.Unlock() removedKeys = make([]interface{}, 0) @@ -78,77 +84,82 @@ func (d *adapterMemoryData) Remove(keys ...interface{}) (removedKeys []interface } // Data returns a copy of all key-value pairs in the cache as map type. -func (d *adapterMemoryData) Data() (map[interface{}]interface{}, error) { +func (d *memoryData) Data() (map[interface{}]interface{}, error) { d.mu.RLock() - m := make(map[interface{}]interface{}, len(d.data)) + defer d.mu.RUnlock() + var ( + data = make(map[interface{}]interface{}, len(d.data)) + nowMilli = gtime.TimestampMilli() + ) for k, v := range d.data { - if !v.IsExpired() { - m[k] = v.v + if v.e > nowMilli { + data[k] = v.v } } - d.mu.RUnlock() - return m, nil + return data, nil } // Keys returns all keys in the cache as slice. -func (d *adapterMemoryData) Keys() ([]interface{}, error) { +func (d *memoryData) Keys() ([]interface{}, error) { d.mu.RLock() + defer d.mu.RUnlock() var ( - index = 0 - keys = make([]interface{}, len(d.data)) + keys = make([]interface{}, 0, len(d.data)) + nowMilli = gtime.TimestampMilli() ) for k, v := range d.data { - if !v.IsExpired() { - keys[index] = k - index++ + if v.e > nowMilli { + keys = append(keys, k) } } - d.mu.RUnlock() return keys, nil } // Values returns all values in the cache as slice. -func (d *adapterMemoryData) Values() ([]interface{}, error) { +func (d *memoryData) Values() ([]interface{}, error) { d.mu.RLock() + defer d.mu.RUnlock() var ( - index = 0 - values = make([]interface{}, len(d.data)) + values = make([]interface{}, 0, len(d.data)) + nowMilli = gtime.TimestampMilli() ) for _, v := range d.data { - if !v.IsExpired() { - values[index] = v.v - index++ + if v.e > nowMilli { + values = append(values, v.v) } } - d.mu.RUnlock() return values, nil } -// Size returns the size of the cache. -func (d *adapterMemoryData) Size() (size int, err error) { +// Size returns the size of the cache that not expired. +func (d *memoryData) Size() (size int, err error) { d.mu.RLock() - size = len(d.data) - d.mu.RUnlock() + defer d.mu.RUnlock() + var nowMilli = gtime.TimestampMilli() + for _, v := range d.data { + if v.e > nowMilli { + size++ + } + } return size, nil } // Clear clears all data of the cache. // Note that this function is sensitive and should be carefully used. -func (d *adapterMemoryData) Clear() error { +func (d *memoryData) Clear() { d.mu.Lock() defer d.mu.Unlock() - d.data = make(map[interface{}]adapterMemoryItem) - return nil + d.data = make(map[interface{}]memoryDataItem) } -func (d *adapterMemoryData) Get(key interface{}) (item adapterMemoryItem, ok bool) { +func (d *memoryData) Get(key interface{}) (item memoryDataItem, ok bool) { d.mu.RLock() item, ok = d.data[key] d.mu.RUnlock() return } -func (d *adapterMemoryData) Set(key interface{}, value adapterMemoryItem) { +func (d *memoryData) Set(key interface{}, value memoryDataItem) { d.mu.Lock() d.data[key] = value d.mu.Unlock() @@ -158,10 +169,10 @@ func (d *adapterMemoryData) Set(key interface{}, value adapterMemoryItem) { // // It does not expire if `duration` == 0. // It deletes the keys of `data` if `duration` < 0 or given `value` is nil. -func (d *adapterMemoryData) SetMap(data map[interface{}]interface{}, expireTime int64) error { +func (d *memoryData) SetMap(data map[interface{}]interface{}, expireTime int64) error { d.mu.Lock() for k, v := range data { - d.data[k] = adapterMemoryItem{ + d.data[k] = memoryDataItem{ v: v, e: expireTime, } @@ -170,7 +181,7 @@ func (d *adapterMemoryData) SetMap(data map[interface{}]interface{}, expireTime return nil } -func (d *adapterMemoryData) SetWithLock(ctx context.Context, key interface{}, value interface{}, expireTimestamp int64) (interface{}, error) { +func (d *memoryData) SetWithLock(ctx context.Context, key interface{}, value interface{}, expireTimestamp int64) (interface{}, error) { d.mu.Lock() defer d.mu.Unlock() var ( @@ -192,15 +203,12 @@ func (d *adapterMemoryData) SetWithLock(ctx context.Context, key interface{}, va return nil, nil } } - d.data[key] = adapterMemoryItem{v: value, e: expireTimestamp} + d.data[key] = memoryDataItem{v: value, e: expireTimestamp} return value, nil } -func (d *adapterMemoryData) DeleteWithDoubleCheck(key interface{}, force ...bool) { +func (d *memoryData) Delete(key interface{}) { d.mu.Lock() - // Doubly check before really deleting it from cache. - if item, ok := d.data[key]; (ok && item.IsExpired()) || (len(force) > 0 && force[0]) { - delete(d.data, key) - } - d.mu.Unlock() + defer d.mu.Unlock() + delete(d.data, key) } diff --git a/os/gcache/gcache_adapter_memory_expire_sets.go b/os/gcache/gcache_adapter_memory_expire_sets.go index b49678c7c..58ef3424e 100644 --- a/os/gcache/gcache_adapter_memory_expire_sets.go +++ b/os/gcache/gcache_adapter_memory_expire_sets.go @@ -12,25 +12,27 @@ import ( "github.com/gogf/gf/v2/container/gset" ) -type adapterMemoryExpireSets struct { - mu sync.RWMutex // expireSetMu ensures the concurrent safety of expireSets map. - expireSets map[int64]*gset.Set // expireSets is the expiring timestamp to its key set mapping, which is used for quick indexing and deleting. +type memoryExpireSets struct { + // expireSetMu ensures the concurrent safety of expireSets map. + mu sync.RWMutex + // expireSets is the expiring timestamp in seconds to its key set mapping, which is used for quick indexing and deleting. + expireSets map[int64]*gset.Set } -func newAdapterMemoryExpireSets() *adapterMemoryExpireSets { - return &adapterMemoryExpireSets{ +func newMemoryExpireSets() *memoryExpireSets { + return &memoryExpireSets{ expireSets: make(map[int64]*gset.Set), } } -func (d *adapterMemoryExpireSets) Get(key int64) (result *gset.Set) { +func (d *memoryExpireSets) Get(key int64) (result *gset.Set) { d.mu.RLock() result = d.expireSets[key] d.mu.RUnlock() return } -func (d *adapterMemoryExpireSets) GetOrNew(key int64) (result *gset.Set) { +func (d *memoryExpireSets) GetOrNew(key int64) (result *gset.Set) { if result = d.Get(key); result != nil { return } @@ -45,7 +47,7 @@ func (d *adapterMemoryExpireSets) GetOrNew(key int64) (result *gset.Set) { return } -func (d *adapterMemoryExpireSets) Delete(key int64) { +func (d *memoryExpireSets) Delete(key int64) { d.mu.Lock() delete(d.expireSets, key) d.mu.Unlock() diff --git a/os/gcache/gcache_adapter_memory_expire_times.go b/os/gcache/gcache_adapter_memory_expire_times.go index af3d4b419..182b75114 100644 --- a/os/gcache/gcache_adapter_memory_expire_times.go +++ b/os/gcache/gcache_adapter_memory_expire_times.go @@ -10,31 +10,31 @@ import ( "sync" ) -type adapterMemoryExpireTimes struct { +type memoryExpireTimes struct { mu sync.RWMutex // expireTimeMu ensures the concurrent safety of expireTimes map. expireTimes map[interface{}]int64 // expireTimes is the expiring key to its timestamp mapping, which is used for quick indexing and deleting. } -func newAdapterMemoryExpireTimes() *adapterMemoryExpireTimes { - return &adapterMemoryExpireTimes{ +func newMemoryExpireTimes() *memoryExpireTimes { + return &memoryExpireTimes{ expireTimes: make(map[interface{}]int64), } } -func (d *adapterMemoryExpireTimes) Get(key interface{}) (value int64) { +func (d *memoryExpireTimes) Get(key interface{}) (value int64) { d.mu.RLock() value = d.expireTimes[key] d.mu.RUnlock() return } -func (d *adapterMemoryExpireTimes) Set(key interface{}, value int64) { +func (d *memoryExpireTimes) Set(key interface{}, value int64) { d.mu.Lock() d.expireTimes[key] = value d.mu.Unlock() } -func (d *adapterMemoryExpireTimes) Delete(key interface{}) { +func (d *memoryExpireTimes) Delete(key interface{}) { d.mu.Lock() delete(d.expireTimes, key) d.mu.Unlock() diff --git a/os/gcache/gcache_adapter_memory_item.go b/os/gcache/gcache_adapter_memory_item.go index 5a7862cae..ede93f32c 100644 --- a/os/gcache/gcache_adapter_memory_item.go +++ b/os/gcache/gcache_adapter_memory_item.go @@ -11,9 +11,8 @@ import ( ) // IsExpired checks whether `item` is expired. -func (item *adapterMemoryItem) IsExpired() bool { +func (item *memoryDataItem) IsExpired() bool { // Note that it should use greater than or equal judgement here // imagining that the cache time is only 1 millisecond. - return item.e < gtime.TimestampMilli() } diff --git a/os/gcache/gcache_adapter_memory_lru.go b/os/gcache/gcache_adapter_memory_lru.go index 6583ec968..318bb2171 100644 --- a/os/gcache/gcache_adapter_memory_lru.go +++ b/os/gcache/gcache_adapter_memory_lru.go @@ -7,94 +7,93 @@ package gcache import ( - "context" - "github.com/gogf/gf/v2/container/glist" "github.com/gogf/gf/v2/container/gmap" - "github.com/gogf/gf/v2/container/gtype" - "github.com/gogf/gf/v2/os/gtimer" + "sync" ) -// LRU cache object. +// memoryLru holds LRU info. // It uses list.List from stdlib for its underlying doubly linked list. -type adapterMemoryLru struct { - cache *AdapterMemory // Parent cache object. - data *gmap.Map // Key mapping to the item of the list. - list *glist.List // Key list. - rawList *glist.List // History for key adding. - closed *gtype.Bool // Closed or not. +type memoryLru struct { + mu sync.RWMutex // Mutex to guarantee concurrent safety. + cap int // LRU cap. + data *gmap.Map // Key mapping to the item of the list. + list *glist.List // Key list. } -// newMemCacheLru creates and returns a new LRU object. -func newMemCacheLru(cache *AdapterMemory) *adapterMemoryLru { - lru := &adapterMemoryLru{ - cache: cache, - data: gmap.New(true), - list: glist.New(true), - rawList: glist.New(true), - closed: gtype.NewBool(), +// newMemoryLru creates and returns a new LRU manager. +func newMemoryLru(cap int) *memoryLru { + lru := &memoryLru{ + cap: cap, + data: gmap.New(false), + list: glist.New(false), } return lru } -// Close closes the LRU object. -func (lru *adapterMemoryLru) Close() { - lru.closed.Set(true) -} - // Remove deletes the `key` FROM `lru`. -func (lru *adapterMemoryLru) Remove(key interface{}) { - if v := lru.data.Get(key); v != nil { - lru.data.Remove(key) - lru.list.Remove(v.(*glist.Element)) - } -} - -// Size returns the size of `lru`. -func (lru *adapterMemoryLru) Size() int { - return lru.data.Size() -} - -// Push pushes `key` to the tail of `lru`. -func (lru *adapterMemoryLru) Push(key interface{}) { - lru.rawList.PushBack(key) -} - -// Pop deletes and returns the key from tail of `lru`. -func (lru *adapterMemoryLru) Pop() interface{} { - if v := lru.list.PopBack(); v != nil { - lru.data.Remove(v) - return v - } - return nil -} - -// SyncAndClear synchronizes the keys from `rawList` to `list` and `data` -// using Least Recently Used algorithm. -func (lru *adapterMemoryLru) SyncAndClear(ctx context.Context) { - if lru.closed.Val() { - gtimer.Exit() +func (l *memoryLru) Remove(keys ...interface{}) { + if l == nil { return } - // Data synchronization. - var alreadyExistItem interface{} - for { - if rawListItem := lru.rawList.PopFront(); rawListItem != nil { - // Deleting the key from list. - if alreadyExistItem = lru.data.Get(rawListItem); alreadyExistItem != nil { - lru.list.Remove(alreadyExistItem.(*glist.Element)) - } - // Pushing key to the head of the list - // and setting its list item to hash table for quick indexing. - lru.data.Set(rawListItem, lru.list.PushFront(rawListItem)) - } else { - break - } - } - // Data cleaning up. - for clearLength := lru.Size() - lru.cache.cap; clearLength > 0; clearLength-- { - if topKey := lru.Pop(); topKey != nil { - lru.cache.clearByKey(topKey, true) + l.mu.Lock() + defer l.mu.Unlock() + for _, key := range keys { + if v := l.data.Remove(key); v != nil { + l.list.Remove(v.(*glist.Element)) } } } + +// SaveAndEvict saves the keys into LRU, evicts and returns the spare keys. +func (l *memoryLru) SaveAndEvict(keys ...interface{}) (evictedKeys []interface{}) { + if l == nil { + return + } + l.mu.Lock() + defer l.mu.Unlock() + evictedKeys = make([]interface{}, 0) + for _, key := range keys { + if evictedKey := l.doSaveAndEvict(key); evictedKey != nil { + evictedKeys = append(evictedKeys, evictedKey) + } + } + return +} + +func (l *memoryLru) doSaveAndEvict(key interface{}) (evictedKey interface{}) { + var element *glist.Element + if v := l.data.Get(key); v != nil { + element = v.(*glist.Element) + if element.Prev() == nil { + // It this element is already on top of list, + // it ignores the element moving. + return + } + l.list.Remove(element) + } + + // pushes the active key to top of list. + element = l.list.PushFront(key) + l.data.Set(key, element) + // evict the spare key from list. + if l.data.Size() <= l.cap { + return + } + + if evictedKey = l.list.PopBack(); evictedKey != nil { + l.data.Remove(evictedKey) + } + return +} + +// Clear deletes all keys. +func (l *memoryLru) Clear() { + if l == nil { + return + } + l.mu.Lock() + defer l.mu.Unlock() + l.data.Clear() + l.list.Clear() +} diff --git a/os/gcache/gcache_adapter_redis.go b/os/gcache/gcache_adapter_redis.go index 2a49fc919..794556a45 100644 --- a/os/gcache/gcache_adapter_redis.go +++ b/os/gcache/gcache_adapter_redis.go @@ -21,7 +21,7 @@ type AdapterRedis struct { } // NewAdapterRedis creates and returns a new memory cache object. -func NewAdapterRedis(redis *gredis.Redis) Adapter { +func NewAdapterRedis(redis *gredis.Redis) *AdapterRedis { return &AdapterRedis{ redis: redis, } diff --git a/os/gcache/gcache_cache.go b/os/gcache/gcache_cache.go index bd3d2ac4b..7cae6c7c8 100644 --- a/os/gcache/gcache_cache.go +++ b/os/gcache/gcache_cache.go @@ -8,7 +8,6 @@ package gcache import ( "context" - "github.com/gogf/gf/v2/util/gconv" ) @@ -23,9 +22,14 @@ type localAdapter = Adapter // New creates and returns a new cache object using default memory adapter. // Note that the LRU feature is only available using memory adapter. func New(lruCap ...int) *Cache { - memAdapter := NewAdapterMemory(lruCap...) + var adapter Adapter + if len(lruCap) == 0 { + adapter = NewAdapterMemory() + } else { + adapter = NewAdapterMemoryLru(lruCap[0]) + } c := &Cache{ - localAdapter: memAdapter, + localAdapter: adapter, } return c } diff --git a/os/gcache/gcache_z_bench_test.go b/os/gcache/gcache_z_bench_test.go index ef41af49c..3ab6b9b4f 100644 --- a/os/gcache/gcache_z_bench_test.go +++ b/os/gcache/gcache_z_bench_test.go @@ -17,7 +17,7 @@ import ( var ( localCache = gcache.New() - localCacheLru = gcache.New(10000) + localCacheLru = gcache.NewWithAdapter(gcache.NewAdapterMemoryLru(10000)) ) func Benchmark_CacheSet(b *testing.B) { diff --git a/os/gcache/gcache_z_example_cache_test.go b/os/gcache/gcache_z_example_cache_test.go index 5628d34d3..64a5e012b 100644 --- a/os/gcache/gcache_z_example_cache_test.go +++ b/os/gcache/gcache_z_example_cache_test.go @@ -97,7 +97,7 @@ func ExampleCache_SetIfNotExist() { // true // false // [k1] - // [] + // [] } func ExampleCache_SetMap() { diff --git a/os/gcache/gcache_z_unit_test.go b/os/gcache/gcache_z_unit_test.go index 23ba4dc0b..4eba06475 100644 --- a/os/gcache/gcache_z_unit_test.go +++ b/os/gcache/gcache_z_unit_test.go @@ -168,30 +168,26 @@ func TestCache_LRU(t *testing.T) { t.AssertNil(cache.Set(ctx, i, i, 0)) } n, _ := cache.Size(ctx) - t.Assert(n, 10) - v, _ := cache.Get(ctx, 6) - t.Assert(v, 6) - time.Sleep(4 * time.Second) - g.Log().Debugf(ctx, `items after lru: %+v`, cache.MustData(ctx)) - n, _ = cache.Size(ctx) t.Assert(n, 2) - v, _ = cache.Get(ctx, 6) - t.Assert(v, 6) - v, _ = cache.Get(ctx, 1) - t.Assert(v, nil) - t.Assert(cache.Close(ctx), nil) + v, _ := cache.Get(ctx, 6) + t.AssertNil(v) + v, _ = cache.Get(ctx, 9) + t.Assert(v, 9) }) } func TestCache_LRU_expire(t *testing.T) { gtest.C(t, func(t *gtest.T) { cache := gcache.New(2) - t.Assert(cache.Set(ctx, 1, nil, 1000), nil) + t.Assert(cache.Set(ctx, 1, nil, 50*time.Millisecond), nil) + n, _ := cache.Size(ctx) t.Assert(n, 1) - v, _ := cache.Get(ctx, 1) - t.Assert(v, nil) + time.Sleep(time.Millisecond * 100) + + n, _ = cache.Size(ctx) + t.Assert(n, 0) }) } @@ -480,7 +476,10 @@ func TestCache_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { { cache := gcache.New() - cache.SetMap(ctx, g.MapAnyAny{1: 11, 2: 22}, 0) + cache.SetMap(ctx, g.MapAnyAny{ + 1: 11, + 2: 22, + }, 0) b, _ := cache.Contains(ctx, 1) t.Assert(b, true) v, _ := cache.Get(ctx, 1) @@ -520,6 +519,7 @@ func TestCache_Basic(t *testing.T) { t.Assert(data[3], nil) n, _ := gcache.Size(ctx) t.Assert(n, 2) + keys, _ := gcache.Keys(ctx) t.Assert(gset.NewFrom(g.Slice{1, 2}).Equal(gset.NewFrom(keys)), true) keyStrs, _ := gcache.KeyStrings(ctx) diff --git a/os/gcfg/gcfg_adapter_content.go b/os/gcfg/gcfg_adapter_content.go index 44daa7ef1..9a0b12a28 100644 --- a/os/gcfg/gcfg_adapter_content.go +++ b/os/gcfg/gcfg_adapter_content.go @@ -37,7 +37,7 @@ func NewAdapterContent(content ...string) (*AdapterContent, error) { // SetContent sets customized configuration content for specified `file`. // The `file` is unnecessary param, default is DefaultConfigFile. func (a *AdapterContent) SetContent(content string) error { - j, err := gjson.LoadContent(content, true) + j, err := gjson.LoadContent([]byte(content), true) if err != nil { return gerror.Wrap(err, `load configuration content failed`) } diff --git a/os/gcfg/gcfg_adapter_file.go b/os/gcfg/gcfg_adapter_file.go index f736d28c5..dc98a3787 100644 --- a/os/gcfg/gcfg_adapter_file.go +++ b/os/gcfg/gcfg_adapter_file.go @@ -262,9 +262,9 @@ func (a *AdapterFile) getJson(fileNameOrPath ...string) (configJson *gjson.Json, // Note that the underlying configuration json object operations are concurrent safe. dataType := gjson.ContentType(gfile.ExtName(filePath)) if gjson.IsValidDataType(dataType) && !isFromConfigContent { - configJson, err = gjson.LoadContentType(dataType, content, true) + configJson, err = gjson.LoadContentType(dataType, []byte(content), true) } else { - configJson, err = gjson.LoadContent(content, true) + configJson, err = gjson.LoadContent([]byte(content), true) } if err != nil { if filePath != "" { diff --git a/os/gcmd/gcmd_command.go b/os/gcmd/gcmd_command.go index 557a7531c..ce0582060 100644 --- a/os/gcmd/gcmd_command.go +++ b/os/gcmd/gcmd_command.go @@ -24,14 +24,18 @@ type Command struct { Arguments []Argument // Argument array, configuring how this command act. Func Function // Custom function. FuncWithValue FuncWithValue // Custom function with output parameters that can interact with command caller. - HelpFunc Function // Custom help function + HelpFunc Function // Custom help function. Examples string // Usage examples. Additional string // Additional info about this command, which will be appended to the end of help info. Strict bool // Strict parsing options, which means it returns error if invalid option given. CaseSensitive bool // CaseSensitive parsing options, which means it parses input options in case-sensitive way. Config string // Config node name, which also retrieves the values from config component along with command line. - parent *Command // Parent command for internal usage. - commands []*Command // Sub commands of this command. + internalCommandAttributes +} + +type internalCommandAttributes struct { + parent *Command // Parent command for internal usage. + commands []*Command // Sub commands of this command. } // Function is a custom command callback function that is bound to a certain argument. diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index 43ecc4f91..c7e49b547 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -267,10 +267,6 @@ func newCommandFromMethod( ) if value := ctx.Value(CtxKeyArgumentsIndex); value != nil { argIndex = value.(int) - // Use the left args to assign to input struct object. - if argIndex < len(arguments) { - arguments = arguments[argIndex:] - } } if data == nil { data = map[string]interface{}{} diff --git a/os/gcmd/gcmd_command_run.go b/os/gcmd/gcmd_command_run.go index 80e29842d..1f4c4bd06 100644 --- a/os/gcmd/gcmd_command_run.go +++ b/os/gcmd/gcmd_command_run.go @@ -85,15 +85,18 @@ func (c *Command) RunWithSpecificArgs(ctx context.Context, args []string) (value return nil, err } parsedArgs := parser.GetArgAll() - if len(parsedArgs) == 1 { - return c.doRun(ctx, args, parser) - } // Exclude the root binary name. parsedArgs = parsedArgs[1:] + // If no args or no sub command, it runs standalone. + if len(parsedArgs) == 0 || len(c.commands) == 0 { + return c.doRun(ctx, args, parser) + } + // Find the matched command and run it. - lastCmd, foundCmd, newCtx := c.searchCommand(ctx, parsedArgs, 0) + // It here `fromArgIndex` set to 1 to calculate the argument index in to `newCtx`. + lastCmd, foundCmd, newCtx := c.searchCommand(ctx, parsedArgs, 1) if foundCmd != nil { return foundCmd.doRun(newCtx, args, parser) } @@ -128,6 +131,7 @@ func (c *Command) doRun(ctx context.Context, args []string, parser *Parser) (val } return nil, c.defaultHelpFunc(ctx, parser) } + // OpenTelemetry for command. var ( span trace.Span diff --git a/os/gcmd/gcmd_parser.go b/os/gcmd/gcmd_parser.go index 2dcf9479e..f27945426 100644 --- a/os/gcmd/gcmd_parser.go +++ b/os/gcmd/gcmd_parser.go @@ -256,7 +256,7 @@ func (p *Parser) GetArgAll() []string { } // MarshalJSON implements the interface MarshalJSON for json.Marshal. -func (p Parser) MarshalJSON() ([]byte, error) { +func (p *Parser) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]interface{}{ "parsedArgs": p.parsedArgs, "parsedOptions": p.parsedOptions, diff --git a/os/gcmd/gcmd_z_unit_issue_test.go b/os/gcmd/gcmd_z_unit_issue_test.go index 19bb4a1c1..2db62bd65 100644 --- a/os/gcmd/gcmd_z_unit_issue_test.go +++ b/os/gcmd/gcmd_z_unit_issue_test.go @@ -232,3 +232,99 @@ func Test_Issue3417(t *testing.T) { ) }) } + +// https://github.com/gogf/gf/issues/3670 +type ( + Issue3670FirstCommand struct { + *gcmd.Command + } + + Issue3670First struct { + g.Meta `name:"first"` + } + + Issue3670Second struct { + g.Meta `name:"second"` + } + + Issue3670Third struct { + g.Meta `name:"third"` + Issue3670Last + } + + Issue3670Last struct { + g.Meta `name:"last"` + } + + Issue3670LastInput struct { + g.Meta `name:"last"` + Country string `name:"country" arg:"true"` + Singer string `name:"singer" arg:"true"` + } + + Issue3670LastOutput struct { + Content string + } +) + +func (receiver Issue3670Last) LastRecv(ctx context.Context, in Issue3670LastInput) (out *Issue3670LastOutput, err error) { + out = &Issue3670LastOutput{ + Content: gjson.MustEncodeString(in), + } + return +} + +func Test_Issue3670(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + ctx = gctx.New() + err error + ) + + third, err := gcmd.NewFromObject(Issue3670Third{}) + t.AssertNil(err) + + second, err := gcmd.NewFromObject(Issue3670Second{}) + t.AssertNil(err) + err = second.AddCommand(third) + t.AssertNil(err) + + first, err := gcmd.NewFromObject(Issue3670First{}) + t.AssertNil(err) + err = first.AddCommand(second) + t.AssertNil(err) + + command := &Issue3670FirstCommand{first} + + value, err := command.RunWithSpecificArgs( + ctx, + []string{"main", "second", "third", "last", "china", "邓丽君"}, + ) + t.AssertNil(err) + + t.Assert(value.(*Issue3670LastOutput).Content, `{"Country":"china","Singer":"邓丽君"}`) + }) +} + +func Test_Issue3701(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + outputArgs []string + inputArgs = []string{"abc", "def"} + ctx = gctx.New() + cmd = gcmd.Command{ + Name: "main", + Usage: "main", + Brief: "...", + Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { + outputArgs = parser.GetArgAll() + return nil + }, + } + ) + + _, err := cmd.RunWithSpecificArgs(ctx, inputArgs) + t.AssertNil(err) + t.Assert(outputArgs, inputArgs) + }) +} diff --git a/os/gfile/gfile.go b/os/gfile/gfile.go index 7222ed900..ee1c902f1 100644 --- a/os/gfile/gfile.go +++ b/os/gfile/gfile.go @@ -252,6 +252,10 @@ func Glob(pattern string, onlyNames ...bool) ([]string, error) { // If parameter `path` is directory, it deletes it recursively. // // It does nothing if given `path` does not exist or is empty. +// +// Deprecated: +// As the name Remove for files deleting is ambiguous, +// please use RemoveFile or RemoveAll for explicit usage instead. func Remove(path string) (err error) { // It does nothing if `path` is empty. if path == "" { @@ -263,6 +267,25 @@ func Remove(path string) (err error) { return } +// RemoveFile removes the named file or (empty) directory. +func RemoveFile(path string) (err error) { + if err = os.Remove(path); err != nil { + err = gerror.Wrapf(err, `os.Remove failed for path "%s"`, path) + } + return +} + +// RemoveAll removes path and any children it contains. +// It removes everything it can but returns the first error +// it encounters. If the path does not exist, RemoveAll +// returns nil (no error). +func RemoveAll(path string) (err error) { + if err = os.RemoveAll(path); err != nil { + err = gerror.Wrapf(err, `os.RemoveAll failed for path "%s"`, path) + } + return +} + // IsReadable checks whether given `path` is readable. func IsReadable(path string) bool { result := true @@ -270,7 +293,9 @@ func IsReadable(path string) bool { if err != nil { result = false } - file.Close() + if file != nil { + _ = file.Close() + } return result } @@ -294,7 +319,9 @@ func IsWritable(path string) bool { if err != nil { result = false } - _ = file.Close() + if file != nil { + _ = file.Close() + } } return result } @@ -406,15 +433,17 @@ func IsEmpty(path string) bool { if err != nil { return true } + if file == nil { + return true + } defer file.Close() names, err := file.Readdirnames(-1) if err != nil { return true } return len(names) == 0 - } else { - return stat.Size() == 0 } + return stat.Size() == 0 } // Ext returns the file name extension used by path. diff --git a/os/gfile/gfile_z_unit_test.go b/os/gfile/gfile_z_unit_test.go index 4760ce1ab..40696d871 100644 --- a/os/gfile/gfile_z_unit_test.go +++ b/os/gfile/gfile_z_unit_test.go @@ -16,6 +16,7 @@ import ( "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/guid" ) func Test_IsDir(t *testing.T) { @@ -213,7 +214,6 @@ func Test_OpenWithFlagPerm(t *testing.T) { } func Test_Exists(t *testing.T) { - gtest.C(t, func(t *gtest.T) { var ( flag bool @@ -685,3 +685,43 @@ func Test_MTimestamp(t *testing.T) { t.Assert(gfile.MTimestamp(gfile.Temp()) > 0, true) }) } + +func Test_RemoveFile_RemoveAll(t *testing.T) { + // safe deleting single file. + gtest.C(t, func(t *gtest.T) { + path := gfile.Temp(guid.S()) + err := gfile.PutContents(path, "1") + t.AssertNil(err) + t.Assert(gfile.Exists(path), true) + + err = gfile.RemoveFile(path) + t.AssertNil(err) + t.Assert(gfile.Exists(path), false) + }) + // error deleting dir which is not empty. + gtest.C(t, func(t *gtest.T) { + var ( + err error + dirPath = gfile.Temp(guid.S()) + filePath1 = gfile.Join(dirPath, guid.S()) + filePath2 = gfile.Join(dirPath, guid.S()) + ) + err = gfile.PutContents(filePath1, "1") + t.AssertNil(err) + t.Assert(gfile.Exists(filePath1), true) + + err = gfile.PutContents(filePath2, "2") + t.AssertNil(err) + t.Assert(gfile.Exists(filePath2), true) + + err = gfile.RemoveFile(dirPath) + t.AssertNE(err, nil) + t.Assert(gfile.Exists(filePath1), true) + t.Assert(gfile.Exists(filePath2), true) + + err = gfile.RemoveAll(dirPath) + t.AssertNil(err) + t.Assert(gfile.Exists(filePath1), false) + t.Assert(gfile.Exists(filePath2), false) + }) +} diff --git a/os/gfpool/gfpool_pool.go b/os/gfpool/gfpool_pool.go index c8d9942a6..55929b461 100644 --- a/os/gfpool/gfpool_pool.go +++ b/os/gfpool/gfpool_pool.go @@ -99,7 +99,7 @@ func (p *Pool) File() (*File, error) { } // It firstly checks using !p.init.Val() for performance purpose. if !p.init.Val() && p.init.Cas(false, true) { - _, _ = gfsnotify.Add(f.path, func(event *gfsnotify.Event) { + var watchCallback = func(event *gfsnotify.Event) { // If the file is removed or renamed, recreates the pool by increasing the pool id. if event.IsRemove() || event.IsRename() { // It drops the old pool. @@ -110,7 +110,8 @@ func (p *Pool) File() (*File, error) { // Whenever the pool id changes, the pool will be recreated. p.id.Add(1) } - }, false) + } + _, _ = gfsnotify.Add(f.path, watchCallback, gfsnotify.WatchOption{NoRecursive: true}) } return f, nil } diff --git a/os/gfsnotify/gfsnotify.go b/os/gfsnotify/gfsnotify.go index 75a76edf5..51f7c93ea 100644 --- a/os/gfsnotify/gfsnotify.go +++ b/os/gfsnotify/gfsnotify.go @@ -42,7 +42,7 @@ type Callback struct { Path string // Bound file path (absolute). name string // Registered name for AddOnce. elem *glist.Element // Element in the callbacks of watcher. - recursive bool // Is bound to path recursively or not. + recursive bool // Is bound to sub-path recursively or not. } // Event is the event produced by underlying fsnotify. @@ -53,6 +53,15 @@ type Event struct { Watcher *Watcher // Parent watcher. } +// WatchOption holds the option for watching. +type WatchOption struct { + // NoRecursive explicitly specifies no recursive watching. + // Recursive watching will also watch all its current and following created subfolders and sub-files. + // + // Note that the recursive watching is enabled in default. + NoRecursive bool +} + // Op is the bits union for file operations. type Op uint32 @@ -75,13 +84,15 @@ const ( var ( mu sync.Mutex // Mutex for concurrent safety of defaultWatcher. defaultWatcher *Watcher // Default watcher. - callbackIdMap = gmap.NewIntAnyMap(true) // Id to callback mapping. + callbackIdMap = gmap.NewIntAnyMap(true) // Global callback id to callback function mapping. callbackIdGenerator = gtype.NewInt() // Atomic id generator for callback. ) // New creates and returns a new watcher. // Note that the watcher number is limited by the file handle setting of the system. -// Eg: fs.inotify.max_user_instances system variable in linux systems. +// Example: fs.inotify.max_user_instances system variable in linux systems. +// +// In most case, you can use the default watcher for usage instead of creating one. func New() (*Watcher, error) { w := &Watcher{ cache: gcache.New(), @@ -102,26 +113,30 @@ func New() (*Watcher, error) { } // Add monitors `path` using default watcher with callback function `callbackFunc`. +// +// The parameter `path` can be either a file or a directory path. // The optional parameter `recursive` specifies whether monitoring the `path` recursively, which is true in default. -func Add(path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { +func Add(path string, callbackFunc func(event *Event), option ...WatchOption) (callback *Callback, err error) { w, err := getDefaultWatcher() if err != nil { return nil, err } - return w.Add(path, callbackFunc, recursive...) + return w.Add(path, callbackFunc, option...) } // AddOnce monitors `path` using default watcher with callback function `callbackFunc` only once using unique name `name`. -// If AddOnce is called multiple times with the same `name` parameter, `path` is only added to monitor once. It returns error -// if it's called twice with the same `name`. // +// If AddOnce is called multiple times with the same `name` parameter, `path` is only added to monitor once. +// It returns error if it's called twice with the same `name`. +// +// The parameter `path` can be either a file or a directory path. // The optional parameter `recursive` specifies whether monitoring the `path` recursively, which is true in default. -func AddOnce(name, path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { +func AddOnce(name, path string, callbackFunc func(event *Event), option ...WatchOption) (callback *Callback, err error) { w, err := getDefaultWatcher() if err != nil { return nil, err } - return w.AddOnce(name, path, callbackFunc, recursive...) + return w.AddOnce(name, path, callbackFunc, option...) } // Remove removes all monitoring callbacks of given `path` from watcher recursively. diff --git a/os/gfsnotify/gfsnotify_filefunc.go b/os/gfsnotify/gfsnotify_filefunc.go index c8f4c7b0c..754be56cf 100644 --- a/os/gfsnotify/gfsnotify_filefunc.go +++ b/os/gfsnotify/gfsnotify_filefunc.go @@ -106,14 +106,12 @@ func doFileScanDir(path string, pattern string, recursive ...bool) ([]string, er file, err = os.Open(path) ) if err != nil { - err = gerror.Wrapf(err, `os.Open failed for path "%s"`, path) - return nil, err + return nil, gerror.Wrapf(err, `os.Open failed for path "%s"`, path) } defer file.Close() names, err := file.Readdirnames(-1) if err != nil { - err = gerror.Wrapf(err, `read directory files failed for path "%s"`, path) - return nil, err + return nil, gerror.Wrapf(err, `read directory files failed for path "%s"`, path) } filePath := "" for _, name := range names { diff --git a/os/gfsnotify/gfsnotify_watcher.go b/os/gfsnotify/gfsnotify_watcher.go index d76d64483..915e588c2 100644 --- a/os/gfsnotify/gfsnotify_watcher.go +++ b/os/gfsnotify/gfsnotify_watcher.go @@ -16,10 +16,14 @@ import ( ) // Add monitors `path` with callback function `callbackFunc` to the watcher. +// +// The parameter `path` can be either a file or a directory path. // The optional parameter `recursive` specifies whether monitoring the `path` recursively, // which is true in default. -func (w *Watcher) Add(path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { - return w.AddOnce("", path, callbackFunc, recursive...) +func (w *Watcher) Add( + path string, callbackFunc func(event *Event), option ...WatchOption, +) (callback *Callback, err error) { + return w.AddOnce("", path, callbackFunc, option...) } // AddOnce monitors `path` with callback function `callbackFunc` only once using unique name @@ -28,26 +32,40 @@ func (w *Watcher) Add(path string, callbackFunc func(event *Event), recursive .. // // It returns error if it's called twice with the same `name`. // +// The parameter `path` can be either a file or a directory path. // The optional parameter `recursive` specifies whether monitoring the `path` recursively, // which is true in default. -func (w *Watcher) AddOnce(name, path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { +func (w *Watcher) AddOnce( + name, path string, callbackFunc func(event *Event), option ...WatchOption, +) (callback *Callback, err error) { + var watchOption = w.getWatchOption(option...) w.nameSet.AddIfNotExistFuncLock(name, func() bool { // Firstly add the path to watcher. - callback, err = w.addWithCallbackFunc(name, path, callbackFunc, recursive...) + // + // A path can only be watched once; watching it more than once is a no-op and will + // not return an error. + callback, err = w.addWithCallbackFunc( + name, path, callbackFunc, option..., + ) if err != nil { return false } + // If it's recursive adding, it then adds all sub-folders to the monitor. // NOTE: // 1. It only recursively adds **folders** to the monitor, NOT files, // because if the folders are monitored and their sub-files are also monitored. // 2. It bounds no callbacks to the folders, because it will search the callbacks // from its parent recursively if any event produced. - if fileIsDir(path) && (len(recursive) == 0 || recursive[0]) { + if fileIsDir(path) && !watchOption.NoRecursive { for _, subPath := range fileAllDirs(path) { if fileIsDir(subPath) { - if err = w.watcher.Add(subPath); err != nil { - err = gerror.Wrapf(err, `add watch failed for path "%s"`, subPath) + if watchAddErr := w.watcher.Add(subPath); watchAddErr != nil { + err = gerror.Wrapf( + err, + `add watch failed for path "%s", err: %s`, + subPath, watchAddErr.Error(), + ) } else { intlog.Printf(context.TODO(), "watcher adds monitor for: %s", subPath) } @@ -62,14 +80,24 @@ func (w *Watcher) AddOnce(name, path string, callbackFunc func(event *Event), re return } +func (w *Watcher) getWatchOption(option ...WatchOption) WatchOption { + if len(option) > 0 { + return option[0] + } + return WatchOption{} +} + // addWithCallbackFunc adds the path to underlying monitor, creates and returns a callback object. // Very note that if it calls multiple times with the same `path`, the latest one will overwrite the previous one. -func (w *Watcher) addWithCallbackFunc(name, path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { +func (w *Watcher) addWithCallbackFunc( + name, path string, callbackFunc func(event *Event), option ...WatchOption, +) (callback *Callback, err error) { + var watchOption = w.getWatchOption(option...) // Check and convert the given path to absolute path. - if t := fileRealPath(path); t == "" { + if realPath := fileRealPath(path); realPath == "" { return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `"%s" does not exist`, path) } else { - path = t + path = realPath } // Create callback object. callback = &Callback{ @@ -77,10 +105,7 @@ func (w *Watcher) addWithCallbackFunc(name, path string, callbackFunc func(event Func: callbackFunc, Path: path, name: name, - recursive: true, - } - if len(recursive) > 0 { - callback.recursive = recursive[0] + recursive: !watchOption.NoRecursive, } // Register the callback to watcher. w.callbacks.LockFunc(func(m map[string]interface{}) { @@ -113,74 +138,50 @@ func (w *Watcher) Close() { w.events.Close() } -// Remove removes monitor and all callbacks associated with the `path` recursively. +// Remove removes watching and all callbacks associated with the `path` recursively. +// Note that, it's recursive in default if given `path` is a directory. func (w *Watcher) Remove(path string) error { - // Firstly remove the callbacks of the path. - if value := w.callbacks.Remove(path); value != nil { - list := value.(*glist.List) - for { - if item := list.PopFront(); item != nil { - callbackIdMap.Remove(item.(*Callback).Id) - } else { - break - } + var ( + err error + subPaths []string + removedPaths = make([]string, 0) + ) + removedPaths = append(removedPaths, path) + if fileIsDir(path) { + subPaths, err = fileScanDir(path, "*", true) + if err != nil { + return err } + removedPaths = append(removedPaths, subPaths...) } - // Secondly remove monitor of all sub-files which have no callbacks. - if subPaths, err := fileScanDir(path, "*", true); err == nil && len(subPaths) > 0 { - for _, subPath := range subPaths { - if w.checkPathCanBeRemoved(subPath) { - if internalErr := w.watcher.Remove(subPath); internalErr != nil { - intlog.Errorf(context.TODO(), `%+v`, internalErr) + + for _, removedPath := range removedPaths { + // remove the callbacks of the path. + if value := w.callbacks.Remove(removedPath); value != nil { + list := value.(*glist.List) + for { + if item := list.PopFront(); item != nil { + callbackIdMap.Remove(item.(*Callback).Id) + } else { + break } } } - } - // Lastly remove the monitor of the path from underlying monitor. - err := w.watcher.Remove(path) - if err != nil { - err = gerror.Wrapf(err, `remove watch failed for path "%s"`, path) + // remove the monitor of the path from underlying monitor. + if watcherRemoveErr := w.watcher.Remove(removedPath); watcherRemoveErr != nil { + err = gerror.Wrapf( + err, + `remove watch failed for path "%s", err: %s`, + removedPath, watcherRemoveErr.Error(), + ) + } } return err } -// checkPathCanBeRemoved checks whether the given path have no callbacks bound. -func (w *Watcher) checkPathCanBeRemoved(path string) bool { - // Firstly check the callbacks in the watcher directly. - if v := w.callbacks.Get(path); v != nil { - return false - } - // Secondly check its parent whether has callbacks. - dirPath := fileDir(path) - if v := w.callbacks.Get(dirPath); v != nil { - for _, c := range v.(*glist.List).FrontAll() { - if c.(*Callback).recursive { - return false - } - } - return false - } - // Recursively check its parent. - parentDirPath := "" - for { - parentDirPath = fileDir(dirPath) - if parentDirPath == dirPath { - break - } - if v := w.callbacks.Get(parentDirPath); v != nil { - for _, c := range v.(*glist.List).FrontAll() { - if c.(*Callback).recursive { - return false - } - } - return false - } - dirPath = parentDirPath - } - return true -} - // RemoveCallback removes callback with given callback id from watcher. +// +// Note that, it auto removes the path watching if there's no callback bound on it. func (w *Watcher) RemoveCallback(callbackId int) { callback := (*Callback)(nil) if r := callbackIdMap.Get(callbackId); r != nil { diff --git a/os/gfsnotify/gfsnotify_watcher_loop.go b/os/gfsnotify/gfsnotify_watcher_loop.go index fd1d37f63..dca551fdf 100644 --- a/os/gfsnotify/gfsnotify_watcher_loop.go +++ b/os/gfsnotify/gfsnotify_watcher_loop.go @@ -8,7 +8,6 @@ package gfsnotify import ( "context" - "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" @@ -20,33 +19,36 @@ import ( func (w *Watcher) watchLoop() { for { select { - // Close event. + // close event. case <-w.closeChan: return - // Event listening. + // event listening. case ev, ok := <-w.watcher.Events: if !ok { return } - // Filter the repeated event in custom duration. + // filter the repeated event in custom duration. + var cacheFunc = func(ctx context.Context) (value interface{}, err error) { + w.events.Push(&Event{ + event: ev, + Path: ev.Name, + Op: Op(ev.Op), + Watcher: w, + }) + return struct{}{}, nil + } _, err := w.cache.SetIfNotExist( context.Background(), ev.String(), - func(ctx context.Context) (value interface{}, err error) { - w.events.Push(&Event{ - event: ev, - Path: ev.Name, - Op: Op(ev.Op), - Watcher: w, - }) - return struct{}{}, nil - }, repeatEventFilterDuration, + cacheFunc, + repeatEventFilterDuration, ) if err != nil { intlog.Errorf(context.TODO(), `%+v`, err) } + // error occurs in underlying watcher. case err := <-w.watcher.Errors: intlog.Errorf(context.TODO(), `%+v`, err) } @@ -55,26 +57,39 @@ func (w *Watcher) watchLoop() { // eventLoop is the core event handler. func (w *Watcher) eventLoop() { + var ( + err error + ctx = context.TODO() + ) for { if v := w.events.Pop(); v != nil { event := v.(*Event) - // If there's no any callback of this path, it removes it from monitor. - callbacks := w.getCallbacks(event.Path) + // If there's no any callback of this path, it removes it from monitor, + // as a path watching without callback is meaningless. + callbacks := w.getCallbacksForPath(event.Path) if len(callbacks) == 0 { _ = w.watcher.Remove(event.Path) continue } + switch { case event.IsRemove(): // It should check again the existence of the path. // It adds it back to the monitor if it still exists. if fileExists(event.Path) { - // It adds the path back to monitor. + // A watch will be automatically removed if the watched path is deleted or + // renamed. + // + // It here adds the path back to monitor. // We need no worry about the repeat adding. - if err := w.watcher.Add(event.Path); err != nil { - intlog.Errorf(context.TODO(), `%+v`, err) + if err = w.watcher.Add(event.Path); err != nil { + intlog.Errorf(ctx, `%+v`, err) } else { - intlog.Printf(context.TODO(), "fake remove event, watcher re-adds monitor for: %s", event.Path) + intlog.Printf( + ctx, + "fake remove event, watcher re-adds monitor for: %s", + event.Path, + ) } // Change the event to RENAME, which means it renames itself to its origin name. event.Op = RENAME @@ -85,60 +100,49 @@ func (w *Watcher) eventLoop() { // It adds it back to the monitor if it still exists. // Especially Some editors might do RENAME and then CHMOD when it's editing file. if fileExists(event.Path) { - // It might lost the monitoring for the path, so we add the path back to monitor. + // A watch will be automatically removed if the watched path is deleted or + // renamed. + // + // It might lose the monitoring for the path, so we add the path back to monitor. // We need no worry about the repeat adding. - if err := w.watcher.Add(event.Path); err != nil { - intlog.Errorf(context.TODO(), `%+v`, err) + if err = w.watcher.Add(event.Path); err != nil { + intlog.Errorf(ctx, `%+v`, err) } else { - intlog.Printf(context.TODO(), "fake rename event, watcher re-adds monitor for: %s", event.Path) + intlog.Printf( + ctx, + "fake rename event, watcher re-adds monitor for: %s", + event.Path, + ) } // Change the event to CHMOD. event.Op = CHMOD } case event.IsCreate(): - // ========================================= + // ================================================================================= // Note that it here just adds the path to monitor without any callback registering, // because its parent already has the callbacks. - // ========================================= - if fileIsDir(event.Path) { - // If it's a folder, it then does adding recursively to monitor. + // ================================================================================= + if w.checkRecursiveWatchingInCreatingEvent(event.Path) { + // It handles only folders, watching folders also watching its sub files. for _, subPath := range fileAllDirs(event.Path) { if fileIsDir(subPath) { - if err := w.watcher.Add(subPath); err != nil { - intlog.Errorf(context.TODO(), `%+v`, err) + if err = w.watcher.Add(subPath); err != nil { + intlog.Errorf(ctx, `%+v`, err) } else { - intlog.Printf(context.TODO(), "folder creation event, watcher adds monitor for: %s", subPath) + intlog.Printf( + ctx, + "folder creation event, watcher adds monitor for: %s", + subPath, + ) } } } - } else { - // If it's a file, it directly adds it to monitor. - if err := w.watcher.Add(event.Path); err != nil { - intlog.Errorf(context.TODO(), `%+v`, err) - } else { - intlog.Printf(context.TODO(), "file creation event, watcher adds monitor for: %s", event.Path) - } } } - // Calling the callbacks in order. + // Calling the callbacks in multiple goroutines. for _, callback := range callbacks { - go func(callback *Callback) { - defer func() { - if err := recover(); err != nil { - switch err { - case callbackExitEventPanicStr: - w.RemoveCallback(callback.Id) - default: - if e, ok := err.(error); ok { - panic(gerror.WrapCode(gcode.CodeInternalPanic, e)) - } - panic(err) - } - } - }() - callback.Func(event) - }(callback) + go w.doCallback(event, callback) } } else { break @@ -146,35 +150,85 @@ func (w *Watcher) eventLoop() { } } -// getCallbacks searches and returns all callbacks with given `path`. +// checkRecursiveWatchingInCreatingEvent checks and returns whether recursive adding given `path` to watcher +// in creating event. +func (w *Watcher) checkRecursiveWatchingInCreatingEvent(path string) bool { + if !fileIsDir(path) { + return false + } + var ( + parentDirPath string + dirPath = path + ) + for { + parentDirPath = fileDir(dirPath) + if parentDirPath == dirPath { + break + } + if callbackItem := w.callbacks.Get(parentDirPath); callbackItem != nil { + for _, node := range callbackItem.(*glist.List).FrontAll() { + callback := node.(*Callback) + if callback.recursive { + return true + } + } + } + dirPath = parentDirPath + } + return false +} + +func (w *Watcher) doCallback(event *Event, callback *Callback) { + defer func() { + if exception := recover(); exception != nil { + switch exception { + case callbackExitEventPanicStr: + w.RemoveCallback(callback.Id) + default: + if e, ok := exception.(error); ok { + panic(gerror.WrapCode(gcode.CodeInternalPanic, e)) + } + panic(exception) + } + } + }() + callback.Func(event) +} + +// getCallbacksForPath searches and returns all callbacks with given `path`. +// // It also searches its parents for callbacks if they're recursive. -func (w *Watcher) getCallbacks(path string) (callbacks []*Callback) { +func (w *Watcher) getCallbacksForPath(path string) (callbacks []*Callback) { // Firstly add the callbacks of itself. - if v := w.callbacks.Get(path); v != nil { - for _, v := range v.(*glist.List).FrontAll() { - callback := v.(*Callback) + if item := w.callbacks.Get(path); item != nil { + for _, node := range item.(*glist.List).FrontAll() { + callback := node.(*Callback) callbacks = append(callbacks, callback) } } + // ============================================================================================================ // Secondly searches its direct parent for callbacks. - // It is special handling here, which is the different between `recursive` and `not recursive` logic + // + // Note that it is SPECIAL handling here, which is the different between `recursive` and `not recursive` logic // for direct parent folder of `path` that events are from. + // ============================================================================================================ dirPath := fileDir(path) - if v := w.callbacks.Get(dirPath); v != nil { - for _, v := range v.(*glist.List).FrontAll() { - callback := v.(*Callback) + if item := w.callbacks.Get(dirPath); item != nil { + for _, node := range item.(*glist.List).FrontAll() { + callback := node.(*Callback) callbacks = append(callbacks, callback) } } + // Lastly searches all the parents of directory of `path` recursively for callbacks. for { parentDirPath := fileDir(dirPath) if parentDirPath == dirPath { break } - if v := w.callbacks.Get(parentDirPath); v != nil { - for _, v := range v.(*glist.List).FrontAll() { - callback := v.(*Callback) + if item := w.callbacks.Get(parentDirPath); item != nil { + for _, node := range item.(*glist.List).FrontAll() { + callback := node.(*Callback) if callback.recursive { callbacks = append(callbacks, callback) } diff --git a/os/gfsnotify/gfsnotify_z_unit_test.go b/os/gfsnotify/gfsnotify_z_unit_test.go index 6155768e1..1ca79a58f 100644 --- a/os/gfsnotify/gfsnotify_z_unit_test.go +++ b/os/gfsnotify/gfsnotify_z_unit_test.go @@ -193,6 +193,39 @@ func TestWatcher_Callback2(t *testing.T) { }) } +func TestWatcher_WatchFolderWithRecursively(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + err error + array = garray.New(true) + dirPath = gfile.Temp(gtime.TimestampNanoStr()) + ) + err = gfile.Mkdir(dirPath) + t.AssertNil(err) + defer gfile.Remove(dirPath) + + _, err = gfsnotify.Add(dirPath, func(event *gfsnotify.Event) { + //fmt.Println(event.String()) + array.Append(1) + }) + t.AssertNil(err) + time.Sleep(time.Millisecond * 100) + t.Assert(array.Len(), 0) + + subDirPath := gfile.Join(dirPath, gtime.TimestampNanoStr()) + err = gfile.Mkdir(subDirPath) + t.AssertNil(err) + time.Sleep(time.Millisecond * 100) + t.Assert(array.Len(), 1) + + f, err := gfile.Create(gfile.Join(subDirPath, gtime.TimestampNanoStr())) + t.AssertNil(err) + t.AssertNil(f.Close()) + time.Sleep(time.Millisecond * 100) + t.Assert(array.Len(), 2) + }) +} + func TestWatcher_WatchFolderWithoutRecursively(t *testing.T) { gtest.C(t, func(t *gtest.T) { var ( @@ -206,7 +239,7 @@ func TestWatcher_WatchFolderWithoutRecursively(t *testing.T) { _, err = gfsnotify.Add(dirPath, func(event *gfsnotify.Event) { // fmt.Println(event.String()) array.Append(1) - }, false) + }, gfsnotify.WatchOption{NoRecursive: true}) t.AssertNil(err) time.Sleep(time.Millisecond * 100) t.Assert(array.Len(), 0) diff --git a/os/glog/glog_logger.go b/os/glog/glog_logger.go index 9377fb8c5..cf3d03e29 100644 --- a/os/glog/glog_logger.go +++ b/os/glog/glog_logger.go @@ -355,11 +355,19 @@ func (l *Logger) getFpFromPool(ctx context.Context, path string) *gfpool.File { // printStd prints content `s` without stack. func (l *Logger) printStd(ctx context.Context, level int, values ...interface{}) { + // nil logger, print nothing + if l == nil { + return + } l.print(ctx, level, "", values...) } // printErr prints content `s` with stack check. func (l *Logger) printErr(ctx context.Context, level int, values ...interface{}) { + // nil logger, print nothing + if l == nil { + return + } var stack string if l.config.StStatus == 1 { stack = l.GetStack() diff --git a/os/glog/glog_logger_api.go b/os/glog/glog_logger_api.go index d485d6fc2..748fae74c 100644 --- a/os/glog/glog_logger_api.go +++ b/os/glog/glog_logger_api.go @@ -142,5 +142,9 @@ func (l *Logger) Criticalf(ctx context.Context, format string, v ...interface{}) // checkLevel checks whether the given `level` could be output. func (l *Logger) checkLevel(level int) bool { + // nil logger, print nothing + if l == nil { + return false + } return l.config.Level&level > 0 } diff --git a/os/glog/glog_logger_rotate.go b/os/glog/glog_logger_rotate.go index 4df261d1a..7e8403616 100644 --- a/os/glog/glog_logger_rotate.go +++ b/os/glog/glog_logger_rotate.go @@ -55,7 +55,7 @@ func (l *Logger) doRotateFile(ctx context.Context, filePath string) error { // No backups, it then just removes the current logging file. if l.config.RotateBackupLimit == 0 { - if err := gfile.Remove(filePath); err != nil { + if err := gfile.RemoveFile(filePath); err != nil { return err } intlog.Printf( @@ -216,7 +216,7 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { err := gcompress.GzipFile(path, path+".gz") if err == nil { intlog.Printf(ctx, `compressed done, remove original logging file: %s`, path) - if err = gfile.Remove(path); err != nil { + if err = gfile.RemoveFile(path); err != nil { intlog.Print(ctx, err) } } else { @@ -264,7 +264,7 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { for i := 0; i < diff; i++ { path, _ := backupFiles.PopLeft() intlog.Printf(ctx, `remove exceeded backup limit file: %s`, path) - if err := gfile.Remove(path.(string)); err != nil { + if err = gfile.RemoveFile(path.(string)); err != nil { intlog.Errorf(ctx, `%+v`, err) } } @@ -284,7 +284,7 @@ func (l *Logger) rotateChecksTimely(ctx context.Context) { `%v - %v = %v > %v, remove expired backup file: %s`, now, mtime, subDuration, l.config.RotateBackupExpire, path, ) - if err := gfile.Remove(path); err != nil { + if err = gfile.RemoveFile(path); err != nil { intlog.Errorf(ctx, `%+v`, err) } return true diff --git a/os/gproc/gproc_signal.go b/os/gproc/gproc_signal.go index e4845fb0c..30efc61f3 100644 --- a/os/gproc/gproc_signal.go +++ b/os/gproc/gproc_signal.go @@ -8,12 +8,13 @@ package gproc import ( "context" - "github.com/gogf/gf/v2/internal/intlog" - "github.com/gogf/gf/v2/util/gutil" "os" "os/signal" "sync" "syscall" + + "github.com/gogf/gf/v2/internal/intlog" + "github.com/gogf/gf/v2/util/gutil" ) // SigHandler defines a function type for signal handling. diff --git a/os/gsession/gsession_storage_file.go b/os/gsession/gsession_storage_file.go index fdf5b54c3..27c83dcd6 100644 --- a/os/gsession/gsession_storage_file.go +++ b/os/gsession/gsession_storage_file.go @@ -128,7 +128,7 @@ func (s *StorageFile) sessionFilePath(sessionId string) string { // RemoveAll deletes all key-value pairs from storage. func (s *StorageFile) RemoveAll(ctx context.Context, sessionId string) error { - return gfile.Remove(s.sessionFilePath(sessionId)) + return gfile.RemoveAll(s.sessionFilePath(sessionId)) } // GetSession returns the session data as *gmap.StrAnyMap for given session id from storage. @@ -262,7 +262,7 @@ func (s *StorageFile) checkAndClearSessionFile(ctx context.Context, path string) path, gtime.NewFromTimeStamp(fileTimestampMilli), s.ttl, ) }) - return gfile.Remove(path) + return gfile.RemoveFile(path) } return nil } diff --git a/os/gspath/gspath_cache.go b/os/gspath/gspath_cache.go index 1070b0b79..c442b005e 100644 --- a/os/gspath/gspath_cache.go +++ b/os/gspath/gspath_cache.go @@ -83,7 +83,7 @@ func (sp *SPath) addToCache(filePath, rootPath string) { // When the files under the directory are updated, the cache will be updated meanwhile. // Note that since the listener is added recursively, if you delete a directory, the files (including the directory) // under the directory will also generate delete events, which means it will generate N+1 events in total -// if a directory deleted and there're N files under it. +// if a directory deleted and there are N files under it. func (sp *SPath) addMonitorByPath(path string) { if sp.cache == nil { return @@ -102,7 +102,7 @@ func (sp *SPath) addMonitorByPath(path string) { case event.IsCreate(): sp.addToCache(event.Path, path) } - }, true) + }) } // removeMonitorByPath removes gfsnotify monitoring of `path` recursively. diff --git a/os/gtime/gtime_sql.go b/os/gtime/gtime_sql.go index e3c79a81b..4fdd4902b 100644 --- a/os/gtime/gtime_sql.go +++ b/os/gtime/gtime_sql.go @@ -24,5 +24,11 @@ func (t *Time) Value() (driver.Value, error) { if t.IsZero() { return nil, nil } + + if t.Year() == 0 { + // Only time. + return t.Format("15:04:05"), nil + } + return t.Time, nil } diff --git a/os/gtime/gtime_z_example_time_test.go b/os/gtime/gtime_z_example_time_test.go index 84a42dda7..439b8ff35 100644 --- a/os/gtime/gtime_z_example_time_test.go +++ b/os/gtime/gtime_z_example_time_test.go @@ -23,12 +23,14 @@ func ExampleNew_Basic() { t3 := gtime.New(curTime, "Y-m-d H:i:s") t4 := gtime.New(curTime) t5 := gtime.New(1533686888) + t6 := gtime.New("08:08:08") fmt.Println(t1) fmt.Println(t2) fmt.Println(t3) fmt.Println(t4) fmt.Println(t5) + fmt.Println(t6) // Output: // 2018-08-08 08:08:08 @@ -36,6 +38,7 @@ func ExampleNew_Basic() { // 2018-08-08 08:08:08 // 2018-08-08 08:08:08 // 2018-08-08 08:08:08 + // 08:08:08 } func ExampleNew_WithFormat() { @@ -68,12 +71,15 @@ func ExampleNewFromTime() { // NewFromStr creates and returns a Time object with given string. // Note that it returns nil if there's error occurs. func ExampleNewFromStr() { - t := gtime.NewFromStr("2018-08-08 08:08:08") + t1 := gtime.NewFromStr("2018-08-08 08:08:08") + t2 := gtime.NewFromStr("08:08:08") - fmt.Println(t) + fmt.Println(t1) + fmt.Println(t2) // Output: // 2018-08-08 08:08:08 + // 08:08:08 } // NewFromStrFormat creates and returns a Time object with given string and @@ -189,26 +195,38 @@ func ExampleTime_Second() { // String returns current time object as string. func ExampleTime_String() { - gt := gtime.New("2018-08-08 08:08:08") - t1 := gt.String() + gt1 := gtime.New("2018-08-08 08:08:08") + t1 := gt1.String() + gt2 := gtime.New("08:08:08") fmt.Println(t1) fmt.Println(reflect.TypeOf(t1)) + fmt.Println(gt2) // Output: // 2018-08-08 08:08:08 // string + // 08:08:08 } // IsZero reports whether t represents the zero time instant, // January 1, year 1, 00:00:00 UTC. func ExampleTime_IsZero() { - gt := gtime.New("2018-08-08 08:08:08") + gt1 := gtime.New("2018-08-08 08:08:08") + gt2 := gtime.New("00:00:00") + timer, _ := time.Parse("15:04:05", "00:00:00") + gt3 := gtime.NewFromTime(timer) - fmt.Println(gt.IsZero()) + fmt.Println(gt1.IsZero()) + fmt.Println(gt2.IsZero()) + fmt.Println(timer.IsZero()) // stdlib is also false + fmt.Println(gt3.IsZero()) // Output: // false + // false + // false + // false } // Add adds the duration to current time. diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000..b40cde24b --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,8 @@ +sonar.projectKey=gogf_gf +sonar.organization=gogf + +sonar.sources=. + +sonar.sourceEncoding=UTF-8 + +sonar.host.url=https://sonarcloud.io diff --git a/test/gtest/gtest_util.go b/test/gtest/gtest_util.go index 9d30df10c..c9ccb9f0b 100644 --- a/test/gtest/gtest_util.go +++ b/test/gtest/gtest_util.go @@ -315,35 +315,44 @@ func compareMap(value, expect interface{}) error { rvValue = reflect.ValueOf(value) rvExpect = reflect.ValueOf(expect) ) - if rvExpect.Kind() == reflect.Map { - if rvValue.Kind() == reflect.Map { - if rvExpect.Len() == rvValue.Len() { - // Turn two interface maps to the same type for comparison. - // Direct use of rvValue.MapIndex(key).Interface() will panic - // when the key types are inconsistent. - mValue := make(map[string]string) - mExpect := make(map[string]string) - ksValue := rvValue.MapKeys() - ksExpect := rvExpect.MapKeys() - for _, key := range ksValue { - mValue[gconv.String(key.Interface())] = gconv.String(rvValue.MapIndex(key).Interface()) - } - for _, key := range ksExpect { - mExpect[gconv.String(key.Interface())] = gconv.String(rvExpect.MapIndex(key).Interface()) - } - for k, v := range mExpect { - if v != mValue[k] { - return fmt.Errorf(`[ASSERT] EXPECT VALUE map["%v"]:%v == map["%v"]:%v`+ - "\nGIVEN : %v\nEXPECT: %v", k, mValue[k], k, v, mValue, mExpect) - } - } - } else { - return fmt.Errorf(`[ASSERT] EXPECT MAP LENGTH %d == %d`, rvValue.Len(), rvExpect.Len()) - } - } else { - return fmt.Errorf(`[ASSERT] EXPECT VALUE TO BE A MAP, BUT GIVEN "%s"`, rvValue.Kind()) + + if rvExpect.Kind() != reflect.Map { + return nil + } + + if rvValue.Kind() != reflect.Map { + return fmt.Errorf(`[ASSERT] EXPECT VALUE TO BE A MAP, BUT GIVEN "%s"`, rvValue.Kind()) + } + + if rvExpect.Len() != rvValue.Len() { + return fmt.Errorf(`[ASSERT] EXPECT MAP LENGTH %d == %d`, rvValue.Len(), rvExpect.Len()) + } + + // Turn two interface maps to the same type for comparison. + // Direct use of rvValue.MapIndex(key).Interface() will panic + // when the key types are inconsistent. + var ( + mValue = make(map[string]string) + mExpect = make(map[string]string) + ksValue = rvValue.MapKeys() + ksExpect = rvExpect.MapKeys() + ) + + for _, key := range ksValue { + mValue[gconv.String(key.Interface())] = gconv.String(rvValue.MapIndex(key).Interface()) + } + + for _, key := range ksExpect { + mExpect[gconv.String(key.Interface())] = gconv.String(rvExpect.MapIndex(key).Interface()) + } + + for k, v := range mExpect { + if v != mValue[k] { + return fmt.Errorf(`[ASSERT] EXPECT VALUE map["%v"]:%v == map["%v"]:%v`+ + "\nGIVEN : %v\nEXPECT: %v", k, mValue[k], k, v, mValue, mExpect) } } + return nil } @@ -364,11 +373,11 @@ func AssertNil(value interface{}) { // which will be joined with current system separator and returned with the path. func DataPath(names ...string) string { _, path, _ := gdebug.CallerWithFilter([]string{pathFilterKey}) - path = filepath.Dir(path) + string(filepath.Separator) + "testdata" + path = filepath.Join(filepath.Dir(path), "testdata") for _, name := range names { - path += string(filepath.Separator) + name + path = filepath.Join(path, name) } - return path + return filepath.FromSlash(path) } // DataContent retrieves and returns the file content for specified testdata path of current package diff --git a/test/gtest/gtest_z_unit_test.go b/test/gtest/gtest_z_unit_test.go index 06872a352..2c1197f22 100644 --- a/test/gtest/gtest_z_unit_test.go +++ b/test/gtest/gtest_z_unit_test.go @@ -399,7 +399,7 @@ func TestAssertError(t *testing.T) { func TestDataPath(t *testing.T) { gtest.C(t, func(t *gtest.T) { - t.Assert(filepath.ToSlash(gtest.DataPath("testdata.txt")), `./testdata/testdata.txt`) + t.Assert(filepath.ToSlash(gtest.DataPath("testdata.txt")), `testdata/testdata.txt`) }) } diff --git a/text/gstr/gstr_case.go b/text/gstr/gstr_case.go index 252db6195..88835dd0c 100644 --- a/text/gstr/gstr_case.go +++ b/text/gstr/gstr_case.go @@ -107,6 +107,7 @@ func CaseConvert(s string, caseType CaseType) string { // // Example: // CaseCamel("any_kind_of_string") -> AnyKindOfString +// CaseCamel("anyKindOfString") -> AnyKindOfString func CaseCamel(s string) string { return toCamelInitCase(s, true) } @@ -115,6 +116,7 @@ func CaseCamel(s string) string { // // Example: // CaseCamelLower("any_kind_of_string") -> anyKindOfString +// CaseCamelLower("AnyKindOfString") -> anyKindOfString func CaseCamelLower(s string) string { if s == "" { return s diff --git a/text/gstr/gstr_z_unit_case_test.go b/text/gstr/gstr_z_unit_case_test.go index ebf78b59e..bdc033c0d 100644 --- a/text/gstr/gstr_z_unit_case_test.go +++ b/text/gstr/gstr_z_unit_case_test.go @@ -18,6 +18,7 @@ func Test_CaseCamel(t *testing.T) { {"test_case", "TestCase"}, {"test", "Test"}, {"TestCase", "TestCase"}, + {"testCase", "TestCase"}, {" test case ", "TestCase"}, {"userLogin_log.bak", "UserLoginLogBak"}, {"", ""}, diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index f6a006ef5..9a39aee70 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -6,7 +6,7 @@ // Package gconv implements powerful and convenient converting functionality for any types of variables. // -// This package should keep much less dependencies with other packages. +// This package should keep much fewer dependencies with other packages. package gconv import ( @@ -23,7 +23,8 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/os/gtime" - "github.com/gogf/gf/v2/util/gtag" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" + "github.com/gogf/gf/v2/util/gconv/internal/structcache" ) var ( @@ -35,13 +36,27 @@ var ( "off": {}, "false": {}, } - - // StructTagPriority defines the default priority tags for Map*/Struct* functions. - // Note that, the `gconv/param` tags are used by old version of package. - // It is strongly recommended using short tag `c/p` instead in the future. - StructTagPriority = gtag.StructTagPriority ) +// IUnmarshalValue is the interface for custom defined types customizing value assignment. +// Note that only pointer can implement interface IUnmarshalValue. +type IUnmarshalValue = localinterface.IUnmarshalValue + +func init() { + // register common converters for internal usage. + structcache.RegisterCommonConverter(structcache.CommonConverter{ + Int64: Int64, + Uint64: Uint64, + String: String, + Float32: Float32, + Float64: Float64, + Time: Time, + GTime: GTime, + Bytes: Bytes, + Bool: Bool, + }) +} + // Byte converts `any` to byte. func Byte(any interface{}) byte { if v, ok := any.(byte); ok { @@ -63,7 +78,7 @@ func Bytes(any interface{}) []byte { return value default: - if f, ok := value.(iBytes); ok { + if f, ok := value.(localinterface.IBytes); ok { return f.Bytes() } originValueAndKind := reflection.OriginValueAndKind(any) @@ -170,16 +185,12 @@ func String(any interface{}) string { } return value.String() default: - // Empty checks. - if value == nil { - return "" - } - if f, ok := value.(iString); ok { + if f, ok := value.(localinterface.IString); ok { // If the variable implements the String() interface, // then use that interface to perform the conversion return f.String() } - if f, ok := value.(iError); ok { + if f, ok := value.(localinterface.IError); ok { // If the variable implements the Error() interface, // then use that interface to perform the conversion return f.Error() @@ -190,11 +201,11 @@ func String(any interface{}) string { kind = rv.Kind() ) switch kind { - case reflect.Chan, + case + reflect.Chan, reflect.Map, reflect.Slice, reflect.Func, - reflect.Ptr, reflect.Interface, reflect.UnsafePointer: if rv.IsNil() { @@ -202,9 +213,21 @@ func String(any interface{}) string { } case reflect.String: return rv.String() - } - if kind == reflect.Ptr { + case reflect.Ptr: + if rv.IsNil() { + return "" + } return String(rv.Elem().Interface()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(rv.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return strconv.FormatUint(rv.Uint(), 10) + case reflect.Uintptr: + return strconv.FormatUint(rv.Uint(), 10) + case reflect.Float32, reflect.Float64: + return strconv.FormatFloat(rv.Float(), 'f', -1, 64) + case reflect.Bool: + return strconv.FormatBool(rv.Bool()) } // Finally, we use json.Marshal to convert. if jsonContent, err := json.Marshal(value); err != nil { @@ -235,16 +258,29 @@ func Bool(any interface{}) bool { } return true default: - if f, ok := value.(iBool); ok { + if f, ok := value.(localinterface.IBool); ok { return f.Bool() } rv := reflect.ValueOf(any) switch rv.Kind() { case reflect.Ptr: - return !rv.IsNil() - case reflect.Map: - fallthrough - case reflect.Array: + if rv.IsNil() { + return false + } + if rv.Type().Elem().Kind() == reflect.Bool { + return rv.Elem().Bool() + } + return Bool(rv.Elem().Interface()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return rv.Int() != 0 + case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return rv.Uint() != 0 + case reflect.Float32, reflect.Float64: + return rv.Float() != 0 + case reflect.Bool: + return rv.Bool() + // TODO:(Map,Array,Slice,Struct) It might panic here for these types. + case reflect.Map, reflect.Array: fallthrough case reflect.Slice: return rv.Len() != 0 diff --git a/util/gconv/gconv_convert.go b/util/gconv/gconv_convert.go index 2ff5b1a94..49bb32b1f 100644 --- a/util/gconv/gconv_convert.go +++ b/util/gconv/gconv_convert.go @@ -266,10 +266,10 @@ func doConvert(in doConvertInput) (convertedValue interface{}) { case "map[string]string": return MapStrStr(in.FromValue) - case "map[string]interface{}": + case "map[string]interface {}": return Map(in.FromValue) - case "[]map[string]interface{}": + case "[]map[string]interface {}": return Maps(in.FromValue) case "RawMessage", "json.RawMessage": diff --git a/util/gconv/gconv_converter.go b/util/gconv/gconv_converter.go index 0f5615677..eb0e226d1 100644 --- a/util/gconv/gconv_converter.go +++ b/util/gconv/gconv_converter.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/util/gconv/internal/structcache" ) type ( @@ -82,6 +83,7 @@ func RegisterConverter(fn interface{}) (err error) { return } registeredOutTypeMap[outType] = reflect.ValueOf(fn) + structcache.RegisterCustomConvertType(outType) return } diff --git a/util/gconv/gconv_float.go b/util/gconv/gconv_float.go index 41cfb1cc7..ceda78df4 100644 --- a/util/gconv/gconv_float.go +++ b/util/gconv/gconv_float.go @@ -7,9 +7,11 @@ package gconv import ( + "reflect" "strconv" "github.com/gogf/gf/v2/encoding/gbinary" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // Float32 converts `any` to float32. @@ -23,13 +25,40 @@ func Float32(any interface{}) float32 { case float64: return float32(value) case []byte: + // TODO: It might panic here for these types. return gbinary.DecodeToFloat32(value) default: - if f, ok := value.(iFloat32); ok { - return f.Float32() + rv := reflect.ValueOf(any) + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float32(rv.Int()) + case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return float32(rv.Uint()) + case reflect.Float32, reflect.Float64: + return float32(rv.Float()) + case reflect.Bool: + if rv.Bool() { + return 1 + } + return 0 + case reflect.String: + f, _ := strconv.ParseFloat(rv.String(), 32) + return float32(f) + case reflect.Ptr: + if rv.IsNil() { + return 0 + } + if f, ok := value.(localinterface.IFloat32); ok { + return f.Float32() + } + return Float32(rv.Elem().Interface()) + default: + if f, ok := value.(localinterface.IFloat32); ok { + return f.Float32() + } + v, _ := strconv.ParseFloat(String(any), 32) + return float32(v) } - v, _ := strconv.ParseFloat(String(any), 64) - return float32(v) } } @@ -44,12 +73,44 @@ func Float64(any interface{}) float64 { case float64: return value case []byte: + // TODO: It might panic here for these types. return gbinary.DecodeToFloat64(value) default: - if f, ok := value.(iFloat64); ok { - return f.Float64() + rv := reflect.ValueOf(any) + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(rv.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return float64(rv.Uint()) + case reflect.Uintptr: + return float64(rv.Uint()) + case reflect.Float32, reflect.Float64: + // Please Note: + // When the type is float32 or a custom type defined based on float32, + // switching to float64 may result in a few extra decimal places. + return rv.Float() + case reflect.Bool: + if rv.Bool() { + return 1 + } + return 0 + case reflect.String: + f, _ := strconv.ParseFloat(rv.String(), 64) + return f + case reflect.Ptr: + if rv.IsNil() { + return 0 + } + if f, ok := value.(localinterface.IFloat64); ok { + return f.Float64() + } + return Float64(rv.Elem().Interface()) + default: + if f, ok := value.(localinterface.IFloat64); ok { + return f.Float64() + } + v, _ := strconv.ParseFloat(String(any), 64) + return v } - v, _ := strconv.ParseFloat(String(any), 64) - return v } } diff --git a/util/gconv/gconv_int.go b/util/gconv/gconv_int.go index 48e26fc2c..8b389f754 100644 --- a/util/gconv/gconv_int.go +++ b/util/gconv/gconv_int.go @@ -8,9 +8,11 @@ package gconv import ( "math" + "reflect" "strconv" "github.com/gogf/gf/v2/encoding/gbinary" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // Int converts `any` to int. @@ -62,44 +64,37 @@ func Int64(any interface{}) int64 { if any == nil { return 0 } - switch value := any.(type) { - case int: - return int64(value) - case int8: - return int64(value) - case int16: - return int64(value) - case int32: - return int64(value) - case int64: - return value - case uint: - return int64(value) - case uint8: - return int64(value) - case uint16: - return int64(value) - case uint32: - return int64(value) - case uint64: - return int64(value) - case float32: - return int64(value) - case float64: - return int64(value) - case bool: - if value { + rv := reflect.ValueOf(any) + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return int64(rv.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return int64(rv.Uint()) + case reflect.Uintptr: + return int64(rv.Uint()) + case reflect.Float32, reflect.Float64: + return int64(rv.Float()) + case reflect.Bool: + if rv.Bool() { return 1 } return 0 - case []byte: - return gbinary.DecodeToInt64(value) - default: - if f, ok := value.(iInt64); ok { + case reflect.Ptr: + if rv.IsNil() { + return 0 + } + if f, ok := any.(localinterface.IInt64); ok { return f.Int64() } + return Int64(rv.Elem().Interface()) + case reflect.Slice: + // TODO: It might panic here for these types. + if rv.Type().Elem().Kind() == reflect.Uint8 { + return gbinary.DecodeToInt64(rv.Bytes()) + } + case reflect.String: var ( - s = String(value) + s = rv.String() isMinus = false ) if len(s) > 0 { @@ -110,7 +105,7 @@ func Int64(any interface{}) int64 { s = s[1:] } } - // Hexadecimal + // Hexadecimal. if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { if v, e := strconv.ParseInt(s[2:], 16, 64); e == nil { if isMinus { @@ -119,18 +114,26 @@ func Int64(any interface{}) int64 { return v } } - // Decimal + // Decimal. if v, e := strconv.ParseInt(s, 10, 64); e == nil { if isMinus { return -v } return v } - // Float64 - if valueInt64 := Float64(value); math.IsNaN(valueInt64) { + // Float64. + if valueInt64 := Float64(s); math.IsNaN(valueInt64) { return 0 } else { + if isMinus { + return -int64(valueInt64) + } return int64(valueInt64) } + default: + if f, ok := any.(localinterface.IInt64); ok { + return f.Int64() + } } + return 0 } diff --git a/util/gconv/gconv_interface.go b/util/gconv/gconv_interface.go deleted file mode 100644 index 8ba7361bc..000000000 --- a/util/gconv/gconv_interface.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package gconv - -import "github.com/gogf/gf/v2/os/gtime" - -// iVal is used for type assert api for String(). -type iVal interface { - Val() interface{} -} - -// iString is used for type assert api for String(). -type iString interface { - String() string -} - -// iBool is used for type assert api for Bool(). -type iBool interface { - Bool() bool -} - -// iInt64 is used for type assert api for Int64(). -type iInt64 interface { - Int64() int64 -} - -// iUint64 is used for type assert api for Uint64(). -type iUint64 interface { - Uint64() uint64 -} - -// iFloat32 is used for type assert api for Float32(). -type iFloat32 interface { - Float32() float32 -} - -// iFloat64 is used for type assert api for Float64(). -type iFloat64 interface { - Float64() float64 -} - -// iError is used for type assert api for Error(). -type iError interface { - Error() string -} - -// iBytes is used for type assert api for Bytes(). -type iBytes interface { - Bytes() []byte -} - -// iInterface is used for type assert api for Interface(). -type iInterface interface { - Interface() interface{} -} - -// iInterfaces is used for type assert api for Interfaces(). -type iInterfaces interface { - Interfaces() []interface{} -} - -// iFloats is used for type assert api for Floats(). -type iFloats interface { - Floats() []float64 -} - -// iInts is used for type assert api for Ints(). -type iInts interface { - Ints() []int -} - -// iStrings is used for type assert api for Strings(). -type iStrings interface { - Strings() []string -} - -// iUints is used for type assert api for Uints(). -type iUints interface { - Uints() []uint -} - -// iMapStrAny is the interface support for converting struct parameter to map. -type iMapStrAny interface { - MapStrAny() map[string]interface{} -} - -// iUnmarshalValue is the interface for custom defined types customizing value assignment. -// Note that only pointer can implement interface iUnmarshalValue. -type iUnmarshalValue interface { - UnmarshalValue(interface{}) error -} - -// iUnmarshalText is the interface for custom defined types customizing value assignment. -// Note that only pointer can implement interface iUnmarshalText. -type iUnmarshalText interface { - UnmarshalText(text []byte) error -} - -// iUnmarshalText is the interface for custom defined types customizing value assignment. -// Note that only pointer can implement interface iUnmarshalJSON. -type iUnmarshalJSON interface { - UnmarshalJSON(b []byte) error -} - -// iSet is the interface for custom value assignment. -type iSet interface { - Set(value interface{}) (old interface{}) -} - -// iGTime is the interface for gtime.Time converting. -type iGTime interface { - GTime(format ...string) *gtime.Time -} diff --git a/util/gconv/gconv_map.go b/util/gconv/gconv_map.go index 243a8aa15..459c438c8 100644 --- a/util/gconv/gconv_map.go +++ b/util/gconv/gconv_map.go @@ -13,6 +13,7 @@ import ( "github.com/gogf/gf/v2/internal/empty" "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" "github.com/gogf/gf/v2/util/gtag" ) @@ -40,8 +41,8 @@ type MapOption struct { // Map converts any variable `value` to map[string]interface{}. If the parameter `value` is not a // map/struct/*struct type, then the conversion will fail and returns nil. // -// If `value` is a struct/*struct object, the second parameter `tags` specifies the most priority -// tags that will be detected, otherwise it detects the tags in order of: +// If `value` is a struct/*struct object, the second parameter `priorityTagAndFieldName` specifies the most priority +// priorityTagAndFieldName that will be detected, otherwise it detects the priorityTagAndFieldName in order of: // gconv, json, field name. func Map(value interface{}, option ...MapOption) map[string]interface{} { return doMapConvert(value, recursiveTypeAuto, false, option...) @@ -67,10 +68,9 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool return nil } // It redirects to its underlying value if it has implemented interface iVal. - if v, ok := value.(iVal); ok { + if v, ok := value.(localinterface.IVal); ok { value = v.Val() } - var ( usedOption = getUsedMapOption(option...) newTags = gtag.StructTagPriority @@ -334,7 +334,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in case reflect.Struct: var dataMap = make(map[string]interface{}) // Map converting interface check. - if v, ok := in.Value.(iMapStrAny); ok { + if v, ok := in.Value.(localinterface.IMapStrAny); ok { // Value copy, in case of concurrent safety. for mapK, mapV := range v.MapStrAny() { if in.RecursiveOption { diff --git a/util/gconv/gconv_scan.go b/util/gconv/gconv_scan.go index 6d22407d6..8b58788ac 100644 --- a/util/gconv/gconv_scan.go +++ b/util/gconv/gconv_scan.go @@ -12,6 +12,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // Scan automatically checks the type of `pointer` and converts `params` to `pointer`. @@ -197,7 +198,7 @@ func doConvertWithJsonCheck(srcValue interface{}, dstPointer interface{}) (ok bo default: // The `params` might be struct that implements interface function Interface, eg: gvar.Var. - if v, ok := srcValue.(iInterface); ok { + if v, ok := srcValue.(localinterface.IInterface); ok { return doConvertWithJsonCheck(v.Interface(), dstPointer) } } diff --git a/util/gconv/gconv_slice_any.go b/util/gconv/gconv_slice_any.go index 8308fdf67..00ecee0c2 100644 --- a/util/gconv/gconv_slice_any.go +++ b/util/gconv/gconv_slice_any.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // SliceAny is alias of Interfaces. @@ -104,7 +105,7 @@ func Interfaces(any interface{}) []interface{} { if array != nil { return array } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return v.Interfaces() } // JSON format string value converting. diff --git a/util/gconv/gconv_slice_float.go b/util/gconv/gconv_slice_float.go index 3d7b49949..bca5af6b0 100644 --- a/util/gconv/gconv_slice_float.go +++ b/util/gconv/gconv_slice_float.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // SliceFloat is alias of Floats. @@ -126,10 +127,10 @@ func Float32s(any interface{}) []float32 { if array != nil { return array } - if v, ok := any.(iFloats); ok { + if v, ok := any.(localinterface.IFloats); ok { return Float32s(v.Floats()) } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Float32s(v.Interfaces()) } // JSON format string value converting. @@ -250,10 +251,10 @@ func Float64s(any interface{}) []float64 { if array != nil { return array } - if v, ok := any.(iFloats); ok { + if v, ok := any.(localinterface.IFloats); ok { return v.Floats() } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Floats(v.Interfaces()) } // JSON format string value converting. diff --git a/util/gconv/gconv_slice_int.go b/util/gconv/gconv_slice_int.go index f28e7fd18..929acfa14 100644 --- a/util/gconv/gconv_slice_int.go +++ b/util/gconv/gconv_slice_int.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // SliceInt is alias of Ints. @@ -126,10 +127,10 @@ func Ints(any interface{}) []int { if array != nil { return array } - if v, ok := any.(iInts); ok { + if v, ok := any.(localinterface.IInts); ok { return v.Ints() } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Ints(v.Interfaces()) } // JSON format string value converting. @@ -255,10 +256,10 @@ func Int32s(any interface{}) []int32 { if array != nil { return array } - if v, ok := any.(iInts); ok { + if v, ok := any.(localinterface.IInts); ok { return Int32s(v.Ints()) } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Int32s(v.Interfaces()) } // JSON format string value converting. @@ -384,10 +385,10 @@ func Int64s(any interface{}) []int64 { if array != nil { return array } - if v, ok := any.(iInts); ok { + if v, ok := any.(localinterface.IInts); ok { return Int64s(v.Ints()) } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Int64s(v.Interfaces()) } // JSON format string value converting. diff --git a/util/gconv/gconv_slice_str.go b/util/gconv/gconv_slice_str.go index 8c97c0157..405e72ca5 100644 --- a/util/gconv/gconv_slice_str.go +++ b/util/gconv/gconv_slice_str.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // SliceStr is alias of Strings. @@ -127,10 +128,10 @@ func Strings(any interface{}) []string { if array != nil { return array } - if v, ok := any.(iStrings); ok { + if v, ok := any.(localinterface.IStrings); ok { return v.Strings() } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Strings(v.Interfaces()) } // JSON format string value converting. diff --git a/util/gconv/gconv_slice_uint.go b/util/gconv/gconv_slice_uint.go index a1ffa7617..8ab15dbf7 100644 --- a/util/gconv/gconv_slice_uint.go +++ b/util/gconv/gconv_slice_uint.go @@ -13,6 +13,7 @@ import ( "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // SliceUint is alias of Uints. @@ -136,10 +137,10 @@ func Uints(any interface{}) []uint { } // Default handler. - if v, ok := any.(iUints); ok { + if v, ok := any.(localinterface.IUints); ok { return v.Uints() } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Uints(v.Interfaces()) } // JSON format string value converting. @@ -270,10 +271,10 @@ func Uint32s(any interface{}) []uint32 { } // Default handler. - if v, ok := any.(iUints); ok { + if v, ok := any.(localinterface.IUints); ok { return Uint32s(v.Uints()) } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Uint32s(v.Interfaces()) } // JSON format string value converting. @@ -404,10 +405,10 @@ func Uint64s(any interface{}) []uint64 { return array } // Default handler. - if v, ok := any.(iUints); ok { + if v, ok := any.(localinterface.IUints); ok { return Uint64s(v.Uints()) } - if v, ok := any.(iInterfaces); ok { + if v, ok := any.(localinterface.IInterfaces); ok { return Uint64s(v.Interfaces()) } // JSON format string value converting. diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index 62883b7e6..57fadd7c9 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -15,7 +15,8 @@ import ( "github.com/gogf/gf/v2/internal/empty" "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/utils" - "github.com/gogf/gf/v2/util/gtag" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" + "github.com/gogf/gf/v2/util/gconv/internal/structcache" ) // Struct maps the params key-value pairs to the corresponding struct object's attributes. @@ -36,8 +37,8 @@ func Struct(params interface{}, pointer interface{}, paramKeyToAttrMap ...map[st } // StructTag acts as Struct but also with support for priority tag feature, which retrieves the -// specified tags for `params` key-value items to struct attribute names mapping. -// The parameter `priorityTag` supports multiple tags that can be joined with char ','. +// specified priorityTagAndFieldName for `params` key-value items to struct attribute names mapping. +// The parameter `priorityTag` supports multiple priorityTagAndFieldName that can be joined with char ','. func StructTag(params interface{}, pointer interface{}, priorityTag string) (err error) { return doStruct(params, pointer, nil, priorityTag) } @@ -79,7 +80,7 @@ func doStruct( paramsInterface interface{} // DO NOT use `params` directly as it might be type `reflect.Value` pointerReflectValue reflect.Value pointerReflectKind reflect.Kind - pointerElemReflectValue reflect.Value // The pointed element. + pointerElemReflectValue reflect.Value // The reflection value to struct element. ) if v, ok := params.(reflect.Value); ok { paramsReflectValue = v @@ -139,7 +140,7 @@ func doStruct( } }() } - // if v, ok := pointerElemReflectValue.Interface().(iUnmarshalValue); ok { + // if v, ok := pointerElemReflectValue.Interface().(localinterface.IUnmarshalValue); ok { // return v.UnmarshalValue(params) // } // Note that it's `pointerElemReflectValue` here not `pointerReflectValue`. @@ -149,175 +150,170 @@ func doStruct( // Retrieve its element, may be struct at last. pointerElemReflectValue = pointerElemReflectValue.Elem() } - - // paramsMap is the map[string]interface{} type variable for params. - // DO NOT use MapDeep here. - paramsMap := doMapConvert(paramsInterface, recursiveTypeAuto, true) - if paramsMap == nil { - return gerror.NewCodef( - gcode.CodeInvalidParameter, - `convert params from "%#v" to "map[string]interface{}" failed`, - params, - ) + paramsMap, ok := paramsInterface.(map[string]interface{}) + if !ok { + // paramsMap is the map[string]interface{} type variable for params. + // DO NOT use MapDeep here. + paramsMap = doMapConvert(paramsInterface, recursiveTypeAuto, true) + if paramsMap == nil { + return gerror.NewCodef( + gcode.CodeInvalidParameter, + `convert params from "%#v" to "map[string]interface{}" failed`, + params, + ) + } } - // Nothing to be done as the parameters are empty. if len(paramsMap) == 0 { return nil } - - // Holds the info for subsequent converting. - type toBeConvertedFieldInfo struct { - Value any // Found value by tag name or field name from input. - FieldIndex int // The associated reflection field index. - FieldOrTagName string // Field name or tag name for field tag by priority tags. - } - - var ( - priorityTagArray []string - elemFieldName string - elemFieldType reflect.StructField - elemFieldValue reflect.Value - elemType = pointerElemReflectValue.Type() - toBeConvertedFieldNameToInfoMap = map[string]toBeConvertedFieldInfo{} // key=elemFieldName + // Get struct info from cache or parse struct and cache the struct info. + cachedStructInfo := structcache.GetCachedStructInfo( + pointerElemReflectValue.Type(), priorityTag, ) - - if priorityTag != "" { - priorityTagArray = append(utils.SplitAndTrim(priorityTag, ","), gtag.StructTagPriority...) - } else { - priorityTagArray = gtag.StructTagPriority - } - - for i := 0; i < pointerElemReflectValue.NumField(); i++ { - elemFieldType = elemType.Field(i) - elemFieldName = elemFieldType.Name - // Only do converting to public attributes. - if !utils.IsLetterUpper(elemFieldName[0]) { - continue - } - - var fieldTagName = getTagNameFromField(elemFieldType, priorityTagArray) - // Maybe it's struct/*struct embedded. - if elemFieldType.Anonymous { - // type Name struct { - // LastName string `json:"lastName"` - // FirstName string `json:"firstName"` - // } - // - // type User struct { - // Name `json:"name"` - // // ... - // } - // - // It is only recorded if the name has a fieldTag - if fieldTagName != "" { - toBeConvertedFieldNameToInfoMap[elemFieldName] = toBeConvertedFieldInfo{ - FieldIndex: elemFieldType.Index[0], - FieldOrTagName: fieldTagName, - } - } - - elemFieldValue = pointerElemReflectValue.Field(i) - // Ignore the interface attribute if it's nil. - if elemFieldValue.Kind() == reflect.Interface { - elemFieldValue = elemFieldValue.Elem() - if !elemFieldValue.IsValid() { - continue - } - } - if err = doStruct(paramsMap, elemFieldValue, paramKeyToAttrMap, priorityTag); err != nil { - return err - } - } else { - // Use the native elemFieldName name as the fieldTag - if fieldTagName == "" { - fieldTagName = elemFieldName - } - toBeConvertedFieldNameToInfoMap[elemFieldName] = toBeConvertedFieldInfo{ - FieldIndex: elemFieldType.Index[0], - FieldOrTagName: fieldTagName, - } - } - } - // Nothing to be converted. - if len(toBeConvertedFieldNameToInfoMap) == 0 { + if cachedStructInfo == nil { return nil } - - // Search the parameter value for the field. - var paramsValue any - for fieldName, fieldInfo := range toBeConvertedFieldNameToInfoMap { - if paramsValue, ok = paramsMap[fieldInfo.FieldOrTagName]; ok { - fieldInfo.Value = paramsValue - toBeConvertedFieldNameToInfoMap[fieldName] = fieldInfo - } + // For the structure types of 0 tagOrFiledNameToFieldInfoMap, + // they also need to be cached to prevent invalid logic + if cachedStructInfo.HasNoFields() { + return nil } + var ( + // Indicates that those values have been used and cannot be reused. + usedParamsKeyOrTagNameMap = structcache.GetUsedParamsKeyOrTagNameMapFromPool() + cachedFieldInfo *structcache.CachedFieldInfo + paramsValue interface{} + ) + defer structcache.PutUsedParamsKeyOrTagNameMapToPool(usedParamsKeyOrTagNameMap) // Firstly, search according to custom mapping rules. // If a possible direct assignment is found, reduce the number of subsequent map searches. - var fieldInfo toBeConvertedFieldInfo for paramKey, fieldName := range paramKeyToAttrMap { - // Prevent setting of non-existent fields - fieldInfo, ok = toBeConvertedFieldNameToInfoMap[fieldName] - if ok { - // Prevent non-existent values from being set. - if paramsValue, ok = paramsMap[paramKey]; ok { - fieldInfo.Value = paramsValue - toBeConvertedFieldNameToInfoMap[fieldName] = fieldInfo - } - } - } - - var ( - paramKey string - paramValue any - fieldName string - // Indicates that those values have been used and cannot be reused. - usedParamsKeyOrTagNameMap = map[string]struct{}{} - ) - for fieldName, fieldInfo = range toBeConvertedFieldNameToInfoMap { - // If it is not empty, the tag or elemFieldName name matches - if fieldInfo.Value != nil { - if err = bindVarToStructAttrWithFieldIndex( - pointerElemReflectValue, fieldName, fieldInfo.FieldIndex, fieldInfo.Value, paramKeyToAttrMap, - ); err != nil { - return err - } - usedParamsKeyOrTagNameMap[fieldInfo.FieldOrTagName] = struct{}{} + paramsValue, ok = paramsMap[paramKey] + if !ok { continue } - - // If value is nil, a fuzzy match is used for search the key and value for converting. - paramKey, paramValue = fuzzyMatchingFieldName(fieldName, paramsMap, usedParamsKeyOrTagNameMap) - if paramValue != nil { - if err = bindVarToStructAttrWithFieldIndex( - pointerElemReflectValue, fieldName, fieldInfo.FieldIndex, paramValue, paramKeyToAttrMap, + cachedFieldInfo = cachedStructInfo.GetFieldInfo(fieldName) + if cachedFieldInfo != nil { + fieldValue := cachedFieldInfo.GetFieldReflectValueFrom(pointerElemReflectValue) + if err = bindVarToStructField( + fieldValue, + paramsValue, + cachedFieldInfo, + paramKeyToAttrMap, ); err != nil { return err } + if len(cachedFieldInfo.OtherSameNameField) > 0 { + if err = setOtherSameNameField( + cachedFieldInfo, paramsValue, pointerReflectValue, paramKeyToAttrMap, + ); err != nil { + return err + } + } usedParamsKeyOrTagNameMap[paramKey] = struct{}{} } } + // Already done converting for given `paramsMap`. + if len(usedParamsKeyOrTagNameMap) == len(paramsMap) { + return nil + } + return bindStructWithLoopFieldInfos( + paramsMap, pointerElemReflectValue, paramKeyToAttrMap, usedParamsKeyOrTagNameMap, cachedStructInfo, + ) +} + +func setOtherSameNameField( + cachedFieldInfo *structcache.CachedFieldInfo, + srcValue any, + structValue reflect.Value, + paramKeyToAttrMap map[string]string, +) (err error) { + // loop the same field name of all sub attributes. + for _, otherFieldInfo := range cachedFieldInfo.OtherSameNameField { + fieldValue := cachedFieldInfo.GetOtherFieldReflectValueFrom(structValue, otherFieldInfo.FieldIndexes) + if err = bindVarToStructField(fieldValue, srcValue, otherFieldInfo, paramKeyToAttrMap); err != nil { + return err + } + } return nil } -func getTagNameFromField(field reflect.StructField, priorityTags []string) string { - for _, tag := range priorityTags { - value, ok := field.Tag.Lookup(tag) +func bindStructWithLoopFieldInfos( + paramsMap map[string]any, + structValue reflect.Value, + paramKeyToAttrMap map[string]string, + usedParamsKeyOrTagNameMap map[string]struct{}, + cachedStructInfo *structcache.CachedStructInfo, +) (err error) { + var ( + cachedFieldInfo *structcache.CachedFieldInfo + fuzzLastKey string + fieldValue reflect.Value + paramKey string + paramValue any + matched bool + ok bool + ) + for _, cachedFieldInfo = range cachedStructInfo.FieldConvertInfos { + for _, fieldTag := range cachedFieldInfo.PriorityTagAndFieldName { + if paramValue, ok = paramsMap[fieldTag]; !ok { + continue + } + fieldValue = cachedFieldInfo.GetFieldReflectValueFrom(structValue) + if err = bindVarToStructField( + fieldValue, paramValue, cachedFieldInfo, paramKeyToAttrMap, + ); err != nil { + return err + } + // handle same field name in nested struct. + if len(cachedFieldInfo.OtherSameNameField) > 0 { + if err = setOtherSameNameField( + cachedFieldInfo, paramValue, structValue, paramKeyToAttrMap, + ); err != nil { + return err + } + } + usedParamsKeyOrTagNameMap[fieldTag] = struct{}{} + matched = true + break + } + if matched { + matched = false + continue + } + + fuzzLastKey = cachedFieldInfo.LastFuzzyKey.Load().(string) + if paramValue, ok = paramsMap[fuzzLastKey]; !ok { + paramKey, paramValue = fuzzyMatchingFieldName( + cachedFieldInfo.RemoveSymbolsFieldName, paramsMap, usedParamsKeyOrTagNameMap, + ) + ok = paramKey != "" + cachedFieldInfo.LastFuzzyKey.Store(paramKey) + } if ok { - // If there's something else in the tag string, - // it uses the first part which is split using char ','. - // Example: - // orm:"id, priority" - // orm:"name, with:uid=id" - array := strings.Split(value, ",") - // json:",omitempty" - trimmedTagName := strings.TrimSpace(array[0]) - return trimmedTagName + fieldValue = cachedFieldInfo.GetFieldReflectValueFrom(structValue) + if paramValue != nil { + if err = bindVarToStructField( + fieldValue, paramValue, cachedFieldInfo, paramKeyToAttrMap, + ); err != nil { + return err + } + // handle same field name in nested struct. + if len(cachedFieldInfo.OtherSameNameField) > 0 { + if err = setOtherSameNameField( + cachedFieldInfo, paramValue, structValue, paramKeyToAttrMap, + ); err != nil { + return err + } + } + } + usedParamsKeyOrTagNameMap[paramKey] = struct{}{} } } - return "" + return nil } // fuzzy matching rule: @@ -327,7 +323,6 @@ func fuzzyMatchingFieldName( paramsMap map[string]any, usedParamsKeyMap map[string]struct{}, ) (string, any) { - fieldName = utils.RemoveSymbols(fieldName) for paramKey, paramValue := range paramsMap { if _, ok := usedParamsKeyMap[paramKey]; ok { continue @@ -340,78 +335,61 @@ func fuzzyMatchingFieldName( return "", nil } -// bindVarToStructAttrWithFieldIndex sets value to struct object attribute by name. -func bindVarToStructAttrWithFieldIndex( - structReflectValue reflect.Value, attrName string, - fieldIndex int, value interface{}, paramKeyToAttrMap map[string]string, +// bindVarToStructField sets value to struct object attribute by name. +func bindVarToStructField( + fieldValue reflect.Value, + srcValue interface{}, + cachedFieldInfo *structcache.CachedFieldInfo, + paramKeyToAttrMap map[string]string, ) (err error) { - structFieldValue := structReflectValue.Field(fieldIndex) - if !structFieldValue.IsValid() { + if !fieldValue.IsValid() { return nil } // CanSet checks whether attribute is public accessible. - if !structFieldValue.CanSet() { + if !fieldValue.CanSet() { return nil } defer func() { if exception := recover(); exception != nil { - if err = bindVarToReflectValue(structFieldValue, value, paramKeyToAttrMap); err != nil { - err = gerror.Wrapf(err, `error binding value to attribute "%s"`, attrName) + if err = bindVarToReflectValue(fieldValue, srcValue, paramKeyToAttrMap); err != nil { + err = gerror.Wrapf(err, `error binding srcValue to attribute "%s"`, cachedFieldInfo.FieldName()) } } }() // Directly converting. - if empty.IsNil(value) { - structFieldValue.Set(reflect.Zero(structFieldValue.Type())) - } else { - // Try to call custom converter. - // Issue: https://github.com/gogf/gf/issues/3099 - var ( - customConverterInput reflect.Value - ok bool - ) - if customConverterInput, ok = value.(reflect.Value); !ok { - customConverterInput = reflect.ValueOf(value) - } - - if ok, err = callCustomConverter(customConverterInput, structFieldValue); ok || err != nil { - return - } - - // Special handling for certain types: - // - Overwrite the default type converting logic of stdlib for time.Time/*time.Time. - var structFieldTypeName = structFieldValue.Type().String() - switch structFieldTypeName { - case "time.Time", "*time.Time": - doConvertWithReflectValueSet(structFieldValue, doConvertInput{ - FromValue: value, - ToTypeName: structFieldTypeName, - ReferValue: structFieldValue, - }) - return - // Hold the time zone consistent in recursive - // Issue: https://github.com/gogf/gf/issues/2980 - case "*gtime.Time", "gtime.Time": - doConvertWithReflectValueSet(structFieldValue, doConvertInput{ - FromValue: value, - ToTypeName: structFieldTypeName, - ReferValue: structFieldValue, - }) - return - } - - // Common interface check. - if ok, err = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok { - return err - } - - // Default converting. - doConvertWithReflectValueSet(structFieldValue, doConvertInput{ - FromValue: value, - ToTypeName: structFieldTypeName, - ReferValue: structFieldValue, - }) + if empty.IsNil(srcValue) { + fieldValue.Set(reflect.Zero(fieldValue.Type())) + return nil } + // Try to call custom converter. + // Issue: https://github.com/gogf/gf/issues/3099 + var ( + customConverterInput reflect.Value + ok bool + ) + if cachedFieldInfo.IsCustomConvert { + if customConverterInput, ok = srcValue.(reflect.Value); !ok { + customConverterInput = reflect.ValueOf(srcValue) + } + if ok, err = callCustomConverter(customConverterInput, fieldValue); ok || err != nil { + return + } + } + if cachedFieldInfo.IsCommonInterface { + if ok, err = bindVarToReflectValueWithInterfaceCheck(fieldValue, srcValue); ok || err != nil { + return + } + } + // Common types use fast assignment logic + if cachedFieldInfo.ConvertFunc != nil { + cachedFieldInfo.ConvertFunc(srcValue, fieldValue) + return nil + } + doConvertWithReflectValueSet(fieldValue, doConvertInput{ + FromValue: srcValue, + ToTypeName: cachedFieldInfo.StructField.Type.String(), + ReferValue: fieldValue, + }) return nil } @@ -432,17 +410,17 @@ func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value i pointer = reflectValue.Interface() } // UnmarshalValue. - if v, ok := pointer.(iUnmarshalValue); ok { + if v, ok := pointer.(localinterface.IUnmarshalValue); ok { return ok, v.UnmarshalValue(value) } // UnmarshalText. - if v, ok := pointer.(iUnmarshalText); ok { + if v, ok := pointer.(localinterface.IUnmarshalText); ok { var valueBytes []byte if b, ok := value.([]byte); ok { valueBytes = b } else if s, ok := value.(string); ok { valueBytes = []byte(s) - } else if f, ok := value.(iString); ok { + } else if f, ok := value.(localinterface.IString); ok { valueBytes = []byte(f.String()) } if len(valueBytes) > 0 { @@ -450,13 +428,13 @@ func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value i } } // UnmarshalJSON. - if v, ok := pointer.(iUnmarshalJSON); ok { + if v, ok := pointer.(localinterface.IUnmarshalJSON); ok { var valueBytes []byte if b, ok := value.([]byte); ok { valueBytes = b } else if s, ok := value.(string); ok { valueBytes = []byte(s) - } else if f, ok := value.(iString); ok { + } else if f, ok := value.(localinterface.IString); ok { valueBytes = []byte(f.String()) } @@ -472,7 +450,7 @@ func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value i return ok, v.UnmarshalJSON(valueBytes) } } - if v, ok := pointer.(iSet); ok { + if v, ok := pointer.(localinterface.ISet); ok { v.Set(value) return ok, nil } @@ -497,7 +475,7 @@ func bindVarToReflectValue( switch kind { case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Interface: if !structFieldValue.IsNil() { - if v, ok := structFieldValue.Interface().(iSet); ok { + if v, ok := structFieldValue.Interface().(localinterface.ISet); ok { v.Set(value) return nil } diff --git a/util/gconv/gconv_structs.go b/util/gconv/gconv_structs.go index b6722477a..867fcdd2b 100644 --- a/util/gconv/gconv_structs.go +++ b/util/gconv/gconv_structs.go @@ -25,8 +25,8 @@ func SliceStruct(params interface{}, pointer interface{}, mapping ...map[string] } // StructsTag acts as Structs but also with support for priority tag feature, which retrieves the -// specified tags for `params` key-value items to struct attribute names mapping. -// The parameter `priorityTag` supports multiple tags that can be joined with char ','. +// specified priorityTagAndFieldName for `params` key-value items to struct attribute names mapping. +// The parameter `priorityTag` supports multiple priorityTagAndFieldName that can be joined with char ','. func StructsTag(params interface{}, pointer interface{}, priorityTag string) (err error) { return doStructs(params, pointer, nil, priorityTag) } diff --git a/util/gconv/gconv_time.go b/util/gconv/gconv_time.go index 20823ceb4..d42a06395 100644 --- a/util/gconv/gconv_time.go +++ b/util/gconv/gconv_time.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // Time converts `any` to time.Time. @@ -52,7 +53,7 @@ func GTime(any interface{}, format ...string) *gtime.Time { if any == nil { return nil } - if v, ok := any.(iGTime); ok { + if v, ok := any.(localinterface.IGTime); ok { return v.GTime(format...) } // It's already this type. diff --git a/util/gconv/gconv_uint.go b/util/gconv/gconv_uint.go index 028a14dec..ac1938763 100644 --- a/util/gconv/gconv_uint.go +++ b/util/gconv/gconv_uint.go @@ -8,9 +8,11 @@ package gconv import ( "math" + "reflect" "strconv" "github.com/gogf/gf/v2/encoding/gbinary" + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" ) // Uint converts `any` to uint. @@ -62,43 +64,38 @@ func Uint64(any interface{}) uint64 { if any == nil { return 0 } - switch value := any.(type) { - case int: - return uint64(value) - case int8: - return uint64(value) - case int16: - return uint64(value) - case int32: - return uint64(value) - case int64: - return uint64(value) - case uint: - return uint64(value) - case uint8: - return uint64(value) - case uint16: - return uint64(value) - case uint32: - return uint64(value) - case uint64: - return value - case float32: - return uint64(value) - case float64: - return uint64(value) - case bool: - if value { + rv := reflect.ValueOf(any) + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return uint64(rv.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return uint64(rv.Uint()) + case reflect.Uintptr: + return uint64(rv.Uint()) + case reflect.Float32, reflect.Float64: + return uint64(rv.Float()) + case reflect.Bool: + if rv.Bool() { return 1 } return 0 - case []byte: - return gbinary.DecodeToUint64(value) - default: - if f, ok := value.(iUint64); ok { + case reflect.Ptr: + if rv.IsNil() { + return 0 + } + if f, ok := any.(localinterface.IUint64); ok { return f.Uint64() } - s := String(value) + return Uint64(rv.Elem().Interface()) + case reflect.Slice: + // TODO:These types should be panic + if rv.Type().Elem().Kind() == reflect.Uint8 { + return gbinary.DecodeToUint64(rv.Bytes()) + } + case reflect.String: + var ( + s = rv.String() + ) // Hexadecimal if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { if v, e := strconv.ParseUint(s[2:], 16, 64); e == nil { @@ -110,10 +107,15 @@ func Uint64(any interface{}) uint64 { return v } // Float64 - if valueFloat64 := Float64(value); math.IsNaN(valueFloat64) { + if valueFloat64 := Float64(any); math.IsNaN(valueFloat64) { return 0 } else { return uint64(valueFloat64) } + default: + if f, ok := any.(localinterface.IUint64); ok { + return f.Uint64() + } } + return 0 } diff --git a/util/gconv/gconv_z_unit_bool_test.go b/util/gconv/gconv_z_unit_bool_test.go index 51c6f0929..912a2dc2b 100644 --- a/util/gconv/gconv_z_unit_bool_test.go +++ b/util/gconv/gconv_z_unit_bool_test.go @@ -13,6 +13,11 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +var ( + boolTestTrueValue = true + boolTestFalseValue = false +) + var boolTests = []struct { value interface{} expect bool @@ -46,6 +51,17 @@ var boolTests = []struct { {struct{}{}, true}, {&struct{}{}, true}, {nil, false}, + {(*bool)(nil), false}, + + {&boolTestTrueValue, true}, + {&boolTestFalseValue, false}, + + {myBool(true), true}, + {myBool(false), false}, + {(*myBool)(&boolTestTrueValue), true}, + {(*myBool)(&boolTestFalseValue), false}, + + {(*myBool)(nil), false}, } func TestBool(t *testing.T) { diff --git a/util/gconv/gconv_z_unit_custom_base_type_test.go b/util/gconv/gconv_z_unit_custom_base_type_test.go new file mode 100644 index 000000000..e46d09239 --- /dev/null +++ b/util/gconv/gconv_z_unit_custom_base_type_test.go @@ -0,0 +1,28 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gconv_test + +type ( + myInt int + myInt8 int8 + myInt16 int16 + myInt32 int32 + myInt64 int64 + + myUint uint + myUint8 uint8 + myUint16 uint16 + myUint32 uint32 + myUint64 uint64 + + myFloat32 float32 + myFloat64 float64 + + myBool bool + + myString string +) diff --git a/util/gconv/gconv_z_unit_float_test.go b/util/gconv/gconv_z_unit_float_test.go index 5097d1798..df888a3d0 100644 --- a/util/gconv/gconv_z_unit_float_test.go +++ b/util/gconv/gconv_z_unit_float_test.go @@ -16,12 +16,20 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +var ( + // Please Note: + // When the type is float32 or a custom type defined based on float32, + // switching to float64 may result in a few extra decimal places. + float32TestValue = float32(123) + float64TestValue = float64(123.456) +) + var floatTests = []struct { value interface{} expect32 float32 expect64 float64 }{ - {true, 0, 0}, + {true, 1, 1}, {false, 0, 0}, {int(0), 0, 0}, @@ -70,9 +78,23 @@ var floatTests = []struct { {struct{}{}, 0, 0}, {nil, 0, 0}, + {(*float32)(nil), 0, 0}, + {(*float64)(nil), 0, 0}, {gvar.New(123), 123, 123}, {gvar.New(123.456), 123.456, 123.456}, + + {&float32TestValue, 123, 123}, + {&float64TestValue, 123.456, 123.456}, + + {myFloat32(123), 123, 123}, + {myFloat64(123.456), 123.456, 123.456}, + + {(*myFloat32)(&float32TestValue), 123, 123}, + {(*myFloat64)(&float64TestValue), 123.456, 123.456}, + + {(*myFloat32)(nil), 0, 0}, + {(*myFloat64)(nil), 0, 0}, } func TestFloat32(t *testing.T) { diff --git a/util/gconv/gconv_z_unit_int_test.go b/util/gconv/gconv_z_unit_int_test.go index 72e2adefb..9129896f3 100644 --- a/util/gconv/gconv_z_unit_int_test.go +++ b/util/gconv/gconv_z_unit_int_test.go @@ -15,6 +15,14 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +var ( + intTestValue = 123 + int8TestValue = int8(123) + int16TestValue = int16(123) + int32TestValue = int32(123) + int64TestValue = int64(123) +) + var intTests = []struct { value interface{} expect int @@ -61,6 +69,7 @@ var intTests = []struct { {"0XA", 10, 10, 10, 10, 10}, {"-0XA", -10, -10, -10, -10, -10}, {"123.456", 123, 123, 123, 123, 123}, + {"-123.456", -123, -123, -123, -123, -123}, {"true", 0, 0, 0, 0, 0}, {"false", 0, 0, 0, 0, 0}, {"on", 0, 0, 0, 0, 0}, @@ -79,8 +88,38 @@ var intTests = []struct { {struct{}{}, 0, 0, 0, 0, 0}, {nil, 0, 0, 0, 0, 0}, + {(*int)(nil), 0, 0, 0, 0, 0}, + {(*int8)(nil), 0, 0, 0, 0, 0}, + {(*int16)(nil), 0, 0, 0, 0, 0}, + {(*int32)(nil), 0, 0, 0, 0, 0}, + {(*int64)(nil), 0, 0, 0, 0, 0}, + {gvar.New(123), 123, 123, 123, 123, 123}, {gvar.New(123.456), 123, 123, 123, 123, 123}, + + {&intTestValue, 123, 123, 123, 123, 123}, + {&int8TestValue, 123, 123, 123, 123, 123}, + {&int16TestValue, 123, 123, 123, 123, 123}, + {&int32TestValue, 123, 123, 123, 123, 123}, + {&int64TestValue, 123, 123, 123, 123, 123}, + + {(myInt)(intTestValue), 123, 123, 123, 123, 123}, + {(myInt8)(int8TestValue), 123, 123, 123, 123, 123}, + {(myInt16)(int16TestValue), 123, 123, 123, 123, 123}, + {(myInt32)(int32TestValue), 123, 123, 123, 123, 123}, + {(myInt64)(int64TestValue), 123, 123, 123, 123, 123}, + + {(*myInt)(&intTestValue), 123, 123, 123, 123, 123}, + {(*myInt8)(&int8TestValue), 123, 123, 123, 123, 123}, + {(*myInt16)(&int16TestValue), 123, 123, 123, 123, 123}, + {(*myInt32)(&int32TestValue), 123, 123, 123, 123, 123}, + {(*myInt64)(&int64TestValue), 123, 123, 123, 123, 123}, + + {(*myInt)(nil), 0, 0, 0, 0, 0}, + {(*myInt8)(nil), 0, 0, 0, 0, 0}, + {(*myInt16)(nil), 0, 0, 0, 0, 0}, + {(*myInt32)(nil), 0, 0, 0, 0, 0}, + {(*myInt64)(nil), 0, 0, 0, 0, 0}, } func TestInt(t *testing.T) { diff --git a/util/gconv/gconv_z_unit_issue_test.go b/util/gconv/gconv_z_unit_issue_test.go index e5f5e7a44..7e80fe30a 100644 --- a/util/gconv/gconv_z_unit_issue_test.go +++ b/util/gconv/gconv_z_unit_issue_test.go @@ -7,11 +7,13 @@ package gconv_test import ( + "fmt" "math/big" "testing" "time" "github.com/gogf/gf/v2/container/gtype" + "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/internal/json" @@ -21,7 +23,7 @@ import ( ) // https://github.com/gogf/gf/issues/1227 -func TestIssue1227(t *testing.T) { +func Test_Issue1227(t *testing.T) { gtest.C(t, func(t *gtest.T) { type StructFromIssue1227 struct { Name string `json:"n1"` @@ -129,7 +131,7 @@ func (f *issue1607Float64) UnmarshalValue(value interface{}) error { return nil } -func TestIssue1607(t *testing.T) { +func Test_Issue1607(t *testing.T) { gtest.C(t, func(t *gtest.T) { type Demo struct { B issue1607Float64 @@ -147,7 +149,7 @@ func TestIssue1607(t *testing.T) { } // https://github.com/gogf/gf/issues/1946 -func TestIssue1946(t *testing.T) { +func Test_Issue1946(t *testing.T) { gtest.C(t, func(t *gtest.T) { type B struct { init *gtype.Bool @@ -221,7 +223,7 @@ func TestIssue1946(t *testing.T) { } // https://github.com/gogf/gf/issues/2381 -func TestIssue2381(t *testing.T) { +func Test_Issue2381(t *testing.T) { gtest.C(t, func(t *gtest.T) { type Inherit struct { Id int64 `json:"id" description:"Id"` @@ -258,7 +260,7 @@ func TestIssue2381(t *testing.T) { } // https://github.com/gogf/gf/issues/2391 -func TestIssue2391(t *testing.T) { +func Test_Issue2391(t *testing.T) { gtest.C(t, func(t *gtest.T) { type Inherit struct { Ids []int @@ -298,7 +300,7 @@ func TestIssue2391(t *testing.T) { } // https://github.com/gogf/gf/issues/2395 -func TestIssue2395(t *testing.T) { +func Test_Issue2395(t *testing.T) { gtest.C(t, func(t *gtest.T) { type Test struct { Num int @@ -310,7 +312,7 @@ func TestIssue2395(t *testing.T) { } // https://github.com/gogf/gf/issues/2371 -func TestIssue2371(t *testing.T) { +func Test_Issue2371(t *testing.T) { gtest.C(t, func(t *gtest.T) { var ( s = struct { @@ -326,7 +328,7 @@ func TestIssue2371(t *testing.T) { } // https://github.com/gogf/gf/issues/2901 -func TestIssue2901(t *testing.T) { +func Test_Issue2901(t *testing.T) { type GameApp2 struct { ForceUpdateTime *time.Time } @@ -341,7 +343,7 @@ func TestIssue2901(t *testing.T) { } // https://github.com/gogf/gf/issues/3006 -func TestIssue3006(t *testing.T) { +func Test_Issue3006(t *testing.T) { type tFF struct { Val1 json.RawMessage `json:"val1"` Val2 []json.RawMessage `json:"val2"` @@ -366,3 +368,440 @@ func TestIssue3006(t *testing.T) { t.Assert(ff.Val3["val3"], []byte(`{"hello":"world"}`)) }) } + +// https://github.com/gogf/gf/issues/3731 +func Test_Issue3731(t *testing.T) { + type Data struct { + Doc map[string]interface{} `json:"doc"` + } + + gtest.C(t, func(t *gtest.T) { + dataMap := map[string]any{ + "doc": map[string]any{ + "craft": nil, + }, + } + + var args Data + err := gconv.Struct(dataMap, &args) + t.AssertNil(err) + t.AssertEQ("", fmt.Sprintf("%T", args.Doc["craft"])) + }) +} + +// https://github.com/gogf/gf/issues/3764 +func Test_Issue3764(t *testing.T) { + type T struct { + True bool `json:"true"` + False bool `json:"false"` + TruePtr *bool `json:"true_ptr"` + FalsePtr *bool `json:"false_ptr"` + } + gtest.C(t, func(t *gtest.T) { + trueValue := true + falseValue := false + m := g.Map{ + "true": trueValue, + "false": falseValue, + "true_ptr": &trueValue, + "false_ptr": &falseValue, + } + tt := &T{} + err := gconv.Struct(m, &tt) + t.AssertNil(err) + t.AssertEQ(tt.True, true) + t.AssertEQ(tt.False, false) + t.AssertEQ(*tt.TruePtr, trueValue) + t.AssertEQ(*tt.FalsePtr, falseValue) + }) +} + +// https://github.com/gogf/gf/issues/3789 +func Test_Issue3789(t *testing.T) { + type ItemSecondThird struct { + SecondID uint64 `json:"secondId,string"` + ThirdID uint64 `json:"thirdId,string"` + } + type ItemFirst struct { + ID uint64 `json:"id,string"` + ItemSecondThird + } + type ItemInput struct { + ItemFirst + } + type HelloReq struct { + g.Meta `path:"/hello" method:"GET"` + ItemInput + } + gtest.C(t, func(t *gtest.T) { + m := map[string]interface{}{ + "id": 1, + "secondId": 2, + "thirdId": 3, + } + var dest HelloReq + err := gconv.Scan(m, &dest) + t.AssertNil(err) + t.Assert(dest.ID, uint64(1)) + t.Assert(dest.SecondID, uint64(2)) + t.Assert(dest.ThirdID, uint64(3)) + }) +} + +// https://github.com/gogf/gf/issues/3797 +func Test_Issue3797(t *testing.T) { + type Option struct { + F1 int + F2 string + } + type Rule struct { + ID int64 `json:"id"` + Rule []*Option `json:"rule"` + } + type Res1 struct { + g.Meta + Rule + } + gtest.C(t, func(t *gtest.T) { + var r = &Rule{ + ID: 100, + } + var res = &Res1{} + for i := 0; i < 10000; i++ { + err := gconv.Scan(r, res) + t.AssertNil(err) + t.Assert(res.ID, 100) + t.AssertEQ(res.Rule.Rule, nil) + } + }) +} + +// https://github.com/gogf/gf/issues/3800 +func Test_Issue3800(t *testing.T) { + // might be random assignment in converting, + // it here so runs multiple times to reproduce the issue. + for i := 0; i < 1000; i++ { + doTestIssue3800(t) + } +} + +func doTestIssue3800(t *testing.T) { + type NullID string + + type StructA struct { + Superior string `json:"superior"` + UpdatedTick int `json:"updated_tick"` + } + type StructB struct { + Superior *NullID `json:"superior"` + UpdatedTick *int `json:"updated_tick"` + } + + type StructC struct { + Superior string `json:"superior"` + UpdatedTick int `json:"updated_tick"` + } + type StructD struct { + StructC + Superior *NullID `json:"superior"` + UpdatedTick *int `json:"updated_tick"` + } + + type StructE struct { + Superior string `json:"superior"` + UpdatedTick int `json:"updated_tick"` + } + type StructF struct { + Superior *NullID `json:"superior"` + UpdatedTick *int `json:"updated_tick"` + StructE + } + + type StructG struct { + Superior string `json:"superior"` + UpdatedTick int `json:"updated_tick"` + } + type StructH struct { + Superior *string `json:"superior"` + UpdatedTick *int `json:"updated_tick"` + StructG + } + + type StructI struct { + Master struct { + Superior *NullID `json:"superior"` + UpdatedTick int `json:"updated_tick"` + } `json:"master"` + } + type StructJ struct { + StructA + Superior *NullID `json:"superior"` + UpdatedTick *int `json:"updated_tick"` + } + + type StructK struct { + Master struct { + Superior *NullID `json:"superior"` + UpdatedTick int `json:"updated_tick"` + } `json:"master"` + } + type StructL struct { + Superior *NullID `json:"superior"` + UpdatedTick *int `json:"updated_tick"` + StructA + } + + // case 0 + // NullID should not be initialized. + gtest.C(t, func(t *gtest.T) { + structA := g.Map{ + "UpdatedTick": 10, + } + structB := StructB{} + err := gconv.Scan(structA, &structB) + t.AssertNil(err) + t.AssertNil(structB.Superior) + t.Assert(*structB.UpdatedTick, structA["UpdatedTick"]) + }) + + // case 1 + gtest.C(t, func(t *gtest.T) { + structA := StructA{ + Superior: "superior100", + UpdatedTick: 20, + } + structB := StructB{} + err := gconv.Scan(structA, &structB) + t.AssertNil(err) + t.Assert(*structB.Superior, structA.Superior) + }) + + // case 2 + gtest.C(t, func(t *gtest.T) { + structA1 := StructA{ + Superior: "100", + UpdatedTick: 20, + } + structB1 := StructB{} + err := gconv.Scan(structA1, &structB1) + t.AssertNil(err) + t.Assert(*structB1.Superior, structA1.Superior) + t.Assert(*structB1.UpdatedTick, structA1.UpdatedTick) + }) + + // case 3 + gtest.C(t, func(t *gtest.T) { + structC := StructC{ + Superior: "superior100", + UpdatedTick: 20, + } + structD := StructD{} + err := gconv.Scan(structC, &structD) + t.AssertNil(err) + t.Assert(structD.StructC.Superior, structC.Superior) + t.Assert(*structD.Superior, structC.Superior) + t.Assert(*structD.UpdatedTick, structC.UpdatedTick) + }) + + // case 4 + gtest.C(t, func(t *gtest.T) { + structC1 := StructC{ + Superior: "100", + UpdatedTick: 20, + } + structD1 := StructD{} + err := gconv.Scan(structC1, &structD1) + t.AssertNil(err) + t.Assert(structD1.StructC.Superior, structC1.Superior) + t.Assert(structD1.StructC.UpdatedTick, structC1.UpdatedTick) + t.Assert(*structD1.Superior, structC1.Superior) + t.Assert(*structD1.UpdatedTick, structC1.UpdatedTick) + }) + + // case 5 + gtest.C(t, func(t *gtest.T) { + structE := StructE{ + Superior: "superior100", + UpdatedTick: 20, + } + structF := StructF{} + err := gconv.Scan(structE, &structF) + t.AssertNil(err) + t.Assert(structF.StructE.Superior, structE.Superior) + t.Assert(structF.StructE.UpdatedTick, structE.UpdatedTick) + t.Assert(*structF.Superior, structE.Superior) + t.Assert(*structF.UpdatedTick, structE.UpdatedTick) + }) + + // case 6 + gtest.C(t, func(t *gtest.T) { + structE1 := StructE{ + Superior: "100", + UpdatedTick: 20, + } + structF1 := StructF{} + err := gconv.Scan(structE1, &structF1) + t.AssertNil(err) + t.Assert(*structF1.Superior, structE1.Superior) + t.Assert(*structF1.UpdatedTick, structE1.UpdatedTick) + t.Assert(structF1.StructE.Superior, structE1.Superior) + t.Assert(structF1.StructE.UpdatedTick, structE1.UpdatedTick) + }) + + // case 7 + gtest.C(t, func(t *gtest.T) { + structG := StructG{ + Superior: "superior100", + UpdatedTick: 20, + } + structH := StructH{} + err := gconv.Scan(structG, &structH) + t.AssertNil(err) + t.Assert(*structH.Superior, structG.Superior) + t.Assert(*structH.UpdatedTick, structG.UpdatedTick) + t.Assert(structH.StructG.Superior, structG.Superior) + t.Assert(structH.StructG.UpdatedTick, structG.UpdatedTick) + }) + + // case 8 + gtest.C(t, func(t *gtest.T) { + structG1 := StructG{ + Superior: "100", + UpdatedTick: 20, + } + structH1 := StructH{} + err := gconv.Scan(structG1, &structH1) + t.AssertNil(err) + t.Assert(*structH1.Superior, structG1.Superior) + t.Assert(*structH1.UpdatedTick, structG1.UpdatedTick) + t.Assert(structH1.StructG.Superior, structG1.Superior) + t.Assert(structH1.StructG.UpdatedTick, structG1.UpdatedTick) + }) + + // case 9 + gtest.C(t, func(t *gtest.T) { + structI := StructI{} + xxx := NullID("superior100") + structI.Master.Superior = &xxx + structI.Master.UpdatedTick = 30 + structJ := StructJ{} + err := gconv.Scan(structI.Master, &structJ) + t.AssertNil(err) + t.Assert(*structJ.Superior, structI.Master.Superior) + t.Assert(*structJ.UpdatedTick, structI.Master.UpdatedTick) + t.Assert(structJ.StructA.Superior, structI.Master.Superior) + t.Assert(structJ.StructA.UpdatedTick, structI.Master.UpdatedTick) + }) + + // case 10 + gtest.C(t, func(t *gtest.T) { + structK := StructK{} + yyy := NullID("superior100") + structK.Master.Superior = &yyy + structK.Master.UpdatedTick = 40 + structL := StructL{} + err := gconv.Scan(structK.Master, &structL) + t.AssertNil(err) + t.Assert(*structL.Superior, structK.Master.Superior) + t.Assert(*structL.UpdatedTick, structK.Master.UpdatedTick) + t.Assert(structL.StructA.Superior, structK.Master.Superior) + t.Assert(structL.StructA.UpdatedTick, structK.Master.UpdatedTick) + }) +} + +// https://github.com/gogf/gf/issues/3821 +func Test_Issue3821(t *testing.T) { + // Scan + gtest.C(t, func(t *gtest.T) { + var record = map[string]interface{}{ + `user_id`: 1, + `user_name`: "teemo", + } + + type DoubleInnerUser struct { + UserId int64 `orm:"user_id"` + } + + type InnerUser struct { + UserId int32 `orm:"user_id"` + UserIdBool bool `orm:"user_id"` + Username *string `orm:"user_name"` + Username2 *string `orm:"user_name"` + Username3 string `orm:"username"` + *DoubleInnerUser + } + + type User struct { + InnerUser + UserId int `orm:"user_id"` + UserIdBool gtype.Bool `orm:"user_id"` + Username string `orm:"user_name"` + Username2 string `orm:"user_name"` + Username3 *string `orm:"user_name"` + Username4 string `orm:"username"` // empty string + } + var user = &User{} + err := gconv.StructTag(record, user, "orm") + + t.AssertNil(err) + t.AssertEQ(user.UserId, 1) + t.AssertEQ(user.UserIdBool.Val(), true) + t.AssertEQ(user.Username, "teemo") + t.AssertEQ(user.Username2, "teemo") + t.AssertEQ(*user.Username3, "teemo") + t.AssertEQ(user.Username4, "") + t.AssertEQ(user.InnerUser.UserId, int32(1)) + t.AssertEQ(user.InnerUser.UserIdBool, true) + t.AssertEQ(*user.InnerUser.Username, "teemo") + t.AssertEQ(*user.InnerUser.Username2, "teemo") + t.AssertEQ(user.InnerUser.Username3, "") + t.AssertEQ(user.DoubleInnerUser.UserId, int64(1)) + }) +} + +// https://github.com/gogf/gf/issues/3868 +func Test_Issue3868(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + type Config struct { + Enable bool + Spec string + PoolSize int + } + data := gjson.New(`[{"enable":false,"spec":"a"},{"enable":true,"poolSize":1}]`) + for i := 0; i < 1000; i++ { + var configs []*Config + err := gconv.Structs(data, &configs) + t.AssertNil(err) + t.Assert(len(configs), 2) + t.Assert(configs[0], &Config{ + Enable: false, + Spec: "a", + }) + t.Assert(configs[1], &Config{ + Enable: true, + PoolSize: 1, + }) + } + }) +} + +// https://github.com/gogf/gf/issues/3903 +func Test_Issue3903(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + type TestA struct { + UserId int `json:"UserId" orm:"user_id" ` + } + type TestB struct { + TestA + UserId int `json:"NewUserId" description:""` + } + var input = map[string]interface{}{ + "user_id": gvar.New(100, true), + } + var a TestB + err := gconv.StructTag(input, &a, "orm") + t.AssertNil(err) + t.Assert(a.TestA.UserId, 100) + t.Assert(a.UserId, 100) + }) +} diff --git a/util/gconv/gconv_z_unit_string_test.go b/util/gconv/gconv_z_unit_string_test.go index 5e704ee57..2d9eaf248 100644 --- a/util/gconv/gconv_z_unit_string_test.go +++ b/util/gconv/gconv_z_unit_string_test.go @@ -65,6 +65,7 @@ var stringTests = []struct { {struct{}{}, "{}"}, {nil, ""}, + {(*string)(nil), ""}, {gvar.New(123), "123"}, {gvar.New(123.456), "123.456"}, diff --git a/util/gconv/gconv_z_unit_struct_test.go b/util/gconv/gconv_z_unit_struct_test.go index a5fdcf3d0..1dcb190c2 100644 --- a/util/gconv/gconv_z_unit_struct_test.go +++ b/util/gconv/gconv_z_unit_struct_test.go @@ -7,6 +7,7 @@ package gconv_test import ( + "strconv" "testing" "time" @@ -182,6 +183,39 @@ func TestStruct(t *testing.T) { }) } +func TestStructDuplicateField(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + m := map[string]any{ + "ID": 100, + } + type Nested1 struct { + ID string + } + type Nested2 struct { + ID uint + } + type Nested3 struct { + ID int + } + type Dest struct { + ID int + Nested1 + Nested2 + Nested3 + } + var ( + err error + dest = new(Dest) + ) + err = gconv.Struct(m, dest) + t.AssertNil(err) + t.Assert(dest.ID, m["ID"]) + t.Assert(dest.Nested1.ID, strconv.Itoa(m["ID"].(int))) + t.Assert(dest.Nested2.ID, m["ID"]) + t.Assert(dest.Nested3.ID, m["ID"]) + }) +} + func TestStructErr(t *testing.T) { gtest.C(t, func(t *gtest.T) { type Score struct { diff --git a/util/gconv/gconv_z_unit_test.go b/util/gconv/gconv_z_unit_test.go new file mode 100644 index 000000000..ca83b3fea --- /dev/null +++ b/util/gconv/gconv_z_unit_test.go @@ -0,0 +1,28 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gconv_test + +import ( + "testing" + + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/gconv" +) + +type impUnmarshalValue struct{} + +func (*impUnmarshalValue) UnmarshalValue(interface{}) error { + return nil +} + +func TestIUnmarshalValue(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var v any = &impUnmarshalValue{} + _, ok := (v).(gconv.IUnmarshalValue) + t.AssertEQ(ok, true) + }) +} diff --git a/util/gconv/gconv_z_unit_time_test.go b/util/gconv/gconv_z_unit_time_test.go index 67178978b..2a758fe1d 100644 --- a/util/gconv/gconv_z_unit_time_test.go +++ b/util/gconv/gconv_z_unit_time_test.go @@ -35,6 +35,8 @@ func TestDuration(t *testing.T) { t.AssertEQ(gconv.Duration(timeTimeTests), time.Duration(0)) t.AssertEQ(gconv.Duration("1m"), time.Minute) t.AssertEQ(gconv.Duration(time.Hour), time.Hour) + t.AssertEQ(gconv.Duration("-1"), time.Duration(-1)) + t.AssertEQ(gconv.Duration("+1"), time.Duration(1)) }) } diff --git a/util/gconv/gconv_z_unit_uint_test.go b/util/gconv/gconv_z_unit_uint_test.go index 37051c42b..2908a79b9 100644 --- a/util/gconv/gconv_z_unit_uint_test.go +++ b/util/gconv/gconv_z_unit_uint_test.go @@ -15,6 +15,14 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +var ( + uintTestValue = uint(123) + uint8TestValue = uint8(123) + uint16TestValue = uint16(123) + uint32TestValue = uint32(123) + uint64TestValue = uint64(123) +) + var uintTests = []struct { value interface{} expect uint @@ -76,8 +84,38 @@ var uintTests = []struct { {struct{}{}, 0, 0, 0, 0, 0}, {nil, 0, 0, 0, 0, 0}, + {(*uint)(nil), 0, 0, 0, 0, 0}, + {(*uint8)(nil), 0, 0, 0, 0, 0}, + {(*uint16)(nil), 0, 0, 0, 0, 0}, + {(*uint32)(nil), 0, 0, 0, 0, 0}, + {(*uint64)(nil), 0, 0, 0, 0, 0}, + {gvar.New(123), 123, 123, 123, 123, 123}, {gvar.New(123.456), 123, 123, 123, 123, 123}, + + {&uintTestValue, 123, 123, 123, 123, 123}, + {&uint8TestValue, 123, 123, 123, 123, 123}, + {&uint16TestValue, 123, 123, 123, 123, 123}, + {&uint32TestValue, 123, 123, 123, 123, 123}, + {&uint64TestValue, 123, 123, 123, 123, 123}, + + {(myUint)(uintTestValue), 123, 123, 123, 123, 123}, + {(myUint8)(uint8TestValue), 123, 123, 123, 123, 123}, + {(myUint16)(uint16TestValue), 123, 123, 123, 123, 123}, + {(myUint32)(uint32TestValue), 123, 123, 123, 123, 123}, + {(myUint64)(uint64TestValue), 123, 123, 123, 123, 123}, + + {(*myUint)(&uintTestValue), 123, 123, 123, 123, 123}, + {(*myUint8)(&uint8TestValue), 123, 123, 123, 123, 123}, + {(*myUint16)(&uint16TestValue), 123, 123, 123, 123, 123}, + {(*myUint32)(&uint32TestValue), 123, 123, 123, 123, 123}, + {(*myUint64)(&uint64TestValue), 123, 123, 123, 123, 123}, + + {(*myUint)(nil), 0, 0, 0, 0, 0}, + {(*myUint8)(nil), 0, 0, 0, 0, 0}, + {(*myUint16)(nil), 0, 0, 0, 0, 0}, + {(*myUint32)(nil), 0, 0, 0, 0, 0}, + {(*myUint64)(nil), 0, 0, 0, 0, 0}, } func TestUint(t *testing.T) { diff --git a/util/gconv/internal/localinterface/localinterface.go b/util/gconv/internal/localinterface/localinterface.go new file mode 100644 index 000000000..63ef7d078 --- /dev/null +++ b/util/gconv/internal/localinterface/localinterface.go @@ -0,0 +1,118 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package localinterface defines some interfaces for converting usage. +package localinterface + +import "github.com/gogf/gf/v2/os/gtime" + +// IVal is used for type assert api for String(). +type IVal interface { + Val() interface{} +} + +// IString is used for type assert api for String(). +type IString interface { + String() string +} + +// IBool is used for type assert api for Bool(). +type IBool interface { + Bool() bool +} + +// IInt64 is used for type assert api for Int64(). +type IInt64 interface { + Int64() int64 +} + +// IUint64 is used for type assert api for Uint64(). +type IUint64 interface { + Uint64() uint64 +} + +// IFloat32 is used for type assert api for Float32(). +type IFloat32 interface { + Float32() float32 +} + +// IFloat64 is used for type assert api for Float64(). +type IFloat64 interface { + Float64() float64 +} + +// IError is used for type assert api for Error(). +type IError interface { + Error() string +} + +// IBytes is used for type assert api for Bytes(). +type IBytes interface { + Bytes() []byte +} + +// IInterface is used for type assert api for Interface(). +type IInterface interface { + Interface() interface{} +} + +// IInterfaces is used for type assert api for Interfaces(). +type IInterfaces interface { + Interfaces() []interface{} +} + +// IFloats is used for type assert api for Floats(). +type IFloats interface { + Floats() []float64 +} + +// IInts is used for type assert api for Ints(). +type IInts interface { + Ints() []int +} + +// IStrings is used for type assert api for Strings(). +type IStrings interface { + Strings() []string +} + +// IUints is used for type assert api for Uints(). +type IUints interface { + Uints() []uint +} + +// IMapStrAny is the interface support for converting struct parameter to map. +type IMapStrAny interface { + MapStrAny() map[string]interface{} +} + +// IUnmarshalText is the interface for custom defined types customizing value assignment. +// Note that only pointer can implement interface IUnmarshalText. +type IUnmarshalText interface { + UnmarshalText(text []byte) error +} + +// IUnmarshalJSON is the interface for custom defined types customizing value assignment. +// Note that only pointer can implement interface IUnmarshalJSON. +type IUnmarshalJSON interface { + UnmarshalJSON(b []byte) error +} + +// IUnmarshalValue is the interface for custom defined types customizing value assignment. +// Note that only pointer can implement interface IUnmarshalValue. +type IUnmarshalValue interface { + UnmarshalValue(interface{}) error +} + +// ISet is the interface for custom value assignment. +type ISet interface { + Set(value interface{}) (old interface{}) +} + +// IGTime is the interface for gtime.Time converting. +type IGTime interface { + GTime(format ...string) *gtime.Time +} diff --git a/util/gconv/internal/structcache/structcache.go b/util/gconv/internal/structcache/structcache.go new file mode 100644 index 000000000..cdb97388d --- /dev/null +++ b/util/gconv/internal/structcache/structcache.go @@ -0,0 +1,64 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// Package structcache provides struct and field info cache feature to enhance performance for struct converting. +package structcache + +import ( + "reflect" + + "github.com/gogf/gf/v2/util/gconv/internal/localinterface" +) + +var ( + // customConvertTypeMap is used to store whether field types are registered to custom conversions + // For example: + // func (src *TypeA) (dst *TypeB,err error) + // This map will store `TypeB` for quick judgment during assignment. + customConvertTypeMap = map[reflect.Type]struct{}{} +) + +// RegisterCustomConvertType registers custom +func RegisterCustomConvertType(fieldType reflect.Type) { + if fieldType.Kind() == reflect.Ptr { + fieldType = fieldType.Elem() + } + customConvertTypeMap[fieldType] = struct{}{} +} + +var ( + implUnmarshalText = reflect.TypeOf((*localinterface.IUnmarshalText)(nil)).Elem() + implUnmarshalJson = reflect.TypeOf((*localinterface.IUnmarshalJSON)(nil)).Elem() + implUnmarshalValue = reflect.TypeOf((*localinterface.IUnmarshalValue)(nil)).Elem() +) + +func checkTypeIsCommonInterface(field reflect.StructField) bool { + isCommonInterface := false + switch field.Type.String() { + case "time.Time", "*time.Time": + // default convert. + + case "gtime.Time", "*gtime.Time": + // default convert. + + default: + // Implemented three types of interfaces that must be pointer types, otherwise it is meaningless + if field.Type.Kind() != reflect.Ptr { + field.Type = reflect.PointerTo(field.Type) + } + switch { + case field.Type.Implements(implUnmarshalText): + isCommonInterface = true + + case field.Type.Implements(implUnmarshalJson): + isCommonInterface = true + + case field.Type.Implements(implUnmarshalValue): + isCommonInterface = true + } + } + return isCommonInterface +} diff --git a/util/gconv/internal/structcache/structcache_cached.go b/util/gconv/internal/structcache/structcache_cached.go new file mode 100644 index 000000000..1c7d4cf32 --- /dev/null +++ b/util/gconv/internal/structcache/structcache_cached.go @@ -0,0 +1,149 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package structcache + +import ( + "reflect" + "sync" + "time" + + "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gtag" +) + +// CommonConverter holds some converting functions of common types for internal usage. +type CommonConverter struct { + Int64 func(any interface{}) int64 + Uint64 func(any interface{}) uint64 + String func(any interface{}) string + Float32 func(any interface{}) float32 + Float64 func(any interface{}) float64 + Time func(any interface{}, format ...string) time.Time + GTime func(any interface{}, format ...string) *gtime.Time + Bytes func(any interface{}) []byte + Bool func(any interface{}) bool +} + +var ( + // map[reflect.Type]*CachedStructInfo + cachedStructsInfoMap = sync.Map{} + + // localCommonConverter holds some converting functions of common types for internal usage. + localCommonConverter CommonConverter +) + +// RegisterCommonConverter registers the CommonConverter for local usage. +func RegisterCommonConverter(commonConverter CommonConverter) { + localCommonConverter = commonConverter +} + +// GetCachedStructInfo retrieves or parses and returns a cached info for certain struct type. +// The given `structType` should be type of struct. +func GetCachedStructInfo(structType reflect.Type, priorityTag string) *CachedStructInfo { + if structType.Kind() != reflect.Struct { + return nil + } + // check if it has been cached. + cachedStructInfo, ok := getCachedConvertStructInfo(structType) + if ok { + // directly returns the cached struct info if already exists. + return cachedStructInfo + } + + // else create one. + + // it parses and generates a cache info for given struct type. + cachedStructInfo = &CachedStructInfo{ + tagOrFiledNameToFieldInfoMap: make(map[string]*CachedFieldInfo), + } + var ( + priorityTagArray []string + parentIndex = make([]int, 0) + ) + if priorityTag != "" { + priorityTagArray = append(utils.SplitAndTrim(priorityTag, ","), gtag.StructTagPriority...) + } else { + priorityTagArray = gtag.StructTagPriority + } + parseStructToCachedStructInfo(structType, parentIndex, cachedStructInfo, priorityTagArray) + storeCachedStructInfo(structType, cachedStructInfo) + return cachedStructInfo +} + +func storeCachedStructInfo(structType reflect.Type, cachedStructInfo *CachedStructInfo) { + // Temporarily enabled as an experimental feature + cachedStructsInfoMap.Store(structType, cachedStructInfo) +} + +func getCachedConvertStructInfo(structType reflect.Type) (*CachedStructInfo, bool) { + // Temporarily enabled as an experimental feature + v, ok := cachedStructsInfoMap.Load(structType) + if ok { + return v.(*CachedStructInfo), ok + } + return nil, false +} + +// parseStructToCachedStructInfo parses given struct reflection type and stores its fields info into given CachedStructInfo. +// It stores nothing into CachedStructInfo if given struct reflection type has no fields. +func parseStructToCachedStructInfo( + structType reflect.Type, + fieldIndexes []int, + cachedStructInfo *CachedStructInfo, + priorityTagArray []string, +) { + var ( + fieldName string + structField reflect.StructField + fieldType reflect.Type + ) + // TODO: + // Check if the structure has already been cached in the cache. + // If it has been cached, some information can be reused, + // but the [FieldIndex] needs to be reset. + // We will not implement it temporarily because it is somewhat complex + for i := 0; i < structType.NumField(); i++ { + structField = structType.Field(i) + fieldType = structField.Type + fieldName = structField.Name + // Only do converting to public attributes. + if !utils.IsLetterUpper(fieldName[0]) { + continue + } + + copyFieldIndexes := make([]int, len(fieldIndexes)) + copy(copyFieldIndexes, fieldIndexes) + + // normal basic attributes. + if structField.Anonymous { + // handle struct attributes, it might be struct/*struct embedded.. + if fieldType.Kind() == reflect.Ptr { + fieldType = fieldType.Elem() + } + if fieldType.Kind() != reflect.Struct { + continue + } + // Skip the embedded structure of the 0 field, + if fieldType.NumField() == 0 { + continue + } + if structField.Tag != "" { + // Do not add anonymous structures without tags + cachedStructInfo.AddField(structField, append(copyFieldIndexes, i), priorityTagArray) + } + parseStructToCachedStructInfo(fieldType, append(copyFieldIndexes, i), cachedStructInfo, priorityTagArray) + continue + } + // Do not directly use append(fieldIndexes, i) + // When the structure is nested deeply, it may lead to bugs, + // which are caused by the slice expansion mechanism + // So it is necessary to allocate a separate index for each field + // See details https://github.com/gogf/gf/issues/3789 + cachedStructInfo.AddField(structField, append(copyFieldIndexes, i), priorityTagArray) + } +} diff --git a/util/gconv/internal/structcache/structcache_cached_field_info.go b/util/gconv/internal/structcache/structcache_cached_field_info.go new file mode 100644 index 000000000..1009295e2 --- /dev/null +++ b/util/gconv/internal/structcache/structcache_cached_field_info.go @@ -0,0 +1,146 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package structcache + +import ( + "reflect" + "sync/atomic" +) + +// CachedFieldInfo holds the cached info for struct field. +type CachedFieldInfo struct { + // WARN: + // The [CachedFieldInfoBase] structure cannot be merged with the following [IsField] field into one structure. + // The [IsField] field should be used separately in the [bindStructWithLoopParamsMap] method + *CachedFieldInfoBase + + // This field is mainly used in the [bindStructWithLoopParamsMap] method. + // This field is needed when both `fieldName` and `tag` of a field exist in the map. + // For example: + // field string `json:"name"` + // map = { + // "field" : "f1", + // "name" : "n1", + // } + // The `name` should be used here. + // In the bindStructWithLoopParamsMap method, due to the disorder of `map`, `field` may be traversed first. + // This field is more about priority, that is, the priority of `name` is higher than that of `field`, + // even if it has been set before. + IsField bool +} + +// CachedFieldInfoBase holds the cached info for struct field. +type CachedFieldInfoBase struct { + // FieldIndexes holds the global index number from struct info. + // The field may belong to an embedded structure, so it is defined here as []int. + FieldIndexes []int + + // PriorityTagAndFieldName holds the tag value(conv, param, p, c, json) and the field name. + // PriorityTagAndFieldName contains the field name, which is the last item of slice. + PriorityTagAndFieldName []string + + // IsCommonInterface marks this field implements common interfaces as: + // - iUnmarshalValue + // - iUnmarshalText + // - iUnmarshalJSON + // Purpose: reduce the interface asserting cost in runtime. + IsCommonInterface bool + + // IsCustomConvert marks there custom converting function for this field type. + IsCustomConvert bool + + // StructField is the type info of this field. + StructField reflect.StructField + + // OtherSameNameField stores fields with the same name and type or different types of nested structures. + // + // For example: + // type ID struct{ + // ID1 string + // ID2 int + // } + // type Card struct{ + // ID + // ID1 uint64 + // ID2 int64 + // } + // + // We will cache each ID1 and ID2 separately, + // even if their types are different and their indexes are different + OtherSameNameField []*CachedFieldInfo + + // ConvertFunc is the converting function for this field. + ConvertFunc func(from any, to reflect.Value) + + // The last fuzzy matching key for this field. + // The fuzzy matching occurs only if there are no direct tag and field name matching in the params map. + // TODO If different paramsMaps contain paramKeys in different formats and all hit the same fieldName, + // the cached value may be continuously updated. + // LastFuzzyKey string. + LastFuzzyKey atomic.Value + + // removeSymbolsFieldName is used for quick fuzzy match for parameter key. + // removeSymbolsFieldName = utils.RemoveSymbols(fieldName) + RemoveSymbolsFieldName string +} + +// FieldName returns the field name of current field info. +func (cfi *CachedFieldInfo) FieldName() string { + return cfi.PriorityTagAndFieldName[len(cfi.PriorityTagAndFieldName)-1] +} + +// GetFieldReflectValueFrom retrieves and returns the `reflect.Value` of given struct field, +// which is used for directly value assignment. +// +// Note that, the input parameter `structValue` might be initialized internally. +func (cfi *CachedFieldInfo) GetFieldReflectValueFrom(structValue reflect.Value) reflect.Value { + if len(cfi.FieldIndexes) == 1 { + // no nested struct. + return structValue.Field(cfi.FieldIndexes[0]) + } + return cfi.fieldReflectValue(structValue, cfi.FieldIndexes) +} + +// GetOtherFieldReflectValueFrom retrieves and returns the `reflect.Value` of given struct field with nested index +// by `fieldLevel`, which is used for directly value assignment. +// +// Note that, the input parameter `structValue` might be initialized internally. +func (cfi *CachedFieldInfo) GetOtherFieldReflectValueFrom(structValue reflect.Value, fieldIndex []int) reflect.Value { + if len(fieldIndex) == 1 { + // no nested struct. + return structValue.Field(fieldIndex[0]) + } + return cfi.fieldReflectValue(structValue, fieldIndex) +} + +func (cfi *CachedFieldInfo) fieldReflectValue(v reflect.Value, fieldIndexes []int) reflect.Value { + for i, x := range fieldIndexes { + if i > 0 { + // it means nested struct. + switch v.Kind() { + case reflect.Pointer: + if v.IsNil() { + // Initialization. + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + + case reflect.Interface: + // Compatible with previous code + // Interface => struct + v = v.Elem() + if v.Kind() == reflect.Ptr { + // maybe *struct or other types + v = v.Elem() + } + default: + } + } + v = v.Field(x) + } + return v +} diff --git a/util/gconv/internal/structcache/structcache_cached_struct_info.go b/util/gconv/internal/structcache/structcache_cached_struct_info.go new file mode 100644 index 000000000..245107376 --- /dev/null +++ b/util/gconv/internal/structcache/structcache_cached_struct_info.go @@ -0,0 +1,208 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package structcache + +import ( + "reflect" + "strings" + "time" + + "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/os/gtime" +) + +// CachedStructInfo holds the cached info for certain struct. +type CachedStructInfo struct { + // This map field is mainly used in the bindStructWithLoopParamsMap method + // key = field's name + // Will save all field names and PriorityTagAndFieldName + // for example: + // field string `json:"name"` + // + // It will be stored twice, which keys are `name` and `field`. + tagOrFiledNameToFieldInfoMap map[string]*CachedFieldInfo + + // All sub attributes field info slice. + FieldConvertInfos []*CachedFieldInfo +} + +func (csi *CachedStructInfo) HasNoFields() bool { + return len(csi.tagOrFiledNameToFieldInfoMap) == 0 +} + +func (csi *CachedStructInfo) GetFieldInfo(fieldName string) *CachedFieldInfo { + return csi.tagOrFiledNameToFieldInfoMap[fieldName] +} + +func (csi *CachedStructInfo) AddField(field reflect.StructField, fieldIndexes []int, priorityTags []string) { + tagOrFieldNameArray := csi.genPriorityTagAndFieldName(field, priorityTags) + for _, tagOrFieldName := range tagOrFieldNameArray { + cachedFieldInfo, found := csi.tagOrFiledNameToFieldInfoMap[tagOrFieldName] + newFieldInfo := csi.makeOrCopyCachedInfo( + field, fieldIndexes, priorityTags, cachedFieldInfo, tagOrFieldName, + ) + if newFieldInfo.IsField { + csi.FieldConvertInfos = append(csi.FieldConvertInfos, newFieldInfo) + } + // if the field info by `tagOrFieldName` already cached, + // it so adds this new field info to other same name field. + if found { + cachedFieldInfo.OtherSameNameField = append(cachedFieldInfo.OtherSameNameField, newFieldInfo) + } else { + csi.tagOrFiledNameToFieldInfoMap[tagOrFieldName] = newFieldInfo + } + } +} + +func (csi *CachedStructInfo) makeOrCopyCachedInfo( + field reflect.StructField, fieldIndexes []int, priorityTags []string, + cachedFieldInfo *CachedFieldInfo, + currTagOrFieldName string, +) (newFieldInfo *CachedFieldInfo) { + if cachedFieldInfo == nil { + // If the field is not cached, it creates a new one. + newFieldInfo = csi.makeCachedFieldInfo(field, fieldIndexes, priorityTags) + newFieldInfo.IsField = currTagOrFieldName == field.Name + return + } + if cachedFieldInfo.StructField.Type != field.Type { + // If the types are different, some information needs to be reset. + newFieldInfo = csi.makeCachedFieldInfo(field, fieldIndexes, priorityTags) + } else { + // If the field types are the same. + newFieldInfo = csi.copyCachedInfoWithFieldIndexes(cachedFieldInfo, fieldIndexes) + } + newFieldInfo.IsField = currTagOrFieldName == field.Name + return +} + +// copyCachedInfoWithFieldIndexes copies and returns a new CachedFieldInfo based on given CachedFieldInfo, but different +// FieldIndexes. Mainly used for copying fields with the same name and type. +func (csi *CachedStructInfo) copyCachedInfoWithFieldIndexes(cfi *CachedFieldInfo, fieldIndexes []int) *CachedFieldInfo { + base := CachedFieldInfoBase{} + base = *cfi.CachedFieldInfoBase + base.FieldIndexes = fieldIndexes + return &CachedFieldInfo{ + CachedFieldInfoBase: &base, + } +} + +func (csi *CachedStructInfo) makeCachedFieldInfo( + field reflect.StructField, fieldIndexes []int, priorityTags []string, +) *CachedFieldInfo { + base := &CachedFieldInfoBase{ + IsCommonInterface: checkTypeIsCommonInterface(field), + StructField: field, + FieldIndexes: fieldIndexes, + ConvertFunc: csi.genFieldConvertFunc(field.Type.String()), + IsCustomConvert: csi.checkTypeHasCustomConvert(field.Type), + PriorityTagAndFieldName: csi.genPriorityTagAndFieldName(field, priorityTags), + RemoveSymbolsFieldName: utils.RemoveSymbols(field.Name), + } + base.LastFuzzyKey.Store(field.Name) + return &CachedFieldInfo{ + CachedFieldInfoBase: base, + } +} + +func (csi *CachedStructInfo) genFieldConvertFunc(fieldType string) (convertFunc func(from any, to reflect.Value)) { + if fieldType[0] == '*' { + convertFunc = csi.genFieldConvertFunc(fieldType[1:]) + if convertFunc == nil { + return nil + } + return csi.genPtrConvertFunc(convertFunc) + } + switch fieldType { + case "int", "int8", "int16", "int32", "int64": + convertFunc = func(from any, to reflect.Value) { + to.SetInt(localCommonConverter.Int64(from)) + } + case "uint", "uint8", "uint16", "uint32", "uint64": + convertFunc = func(from any, to reflect.Value) { + to.SetUint(localCommonConverter.Uint64(from)) + } + case "string": + convertFunc = func(from any, to reflect.Value) { + to.SetString(localCommonConverter.String(from)) + } + case "float32": + convertFunc = func(from any, to reflect.Value) { + to.SetFloat(float64(localCommonConverter.Float32(from))) + } + case "float64": + convertFunc = func(from any, to reflect.Value) { + to.SetFloat(localCommonConverter.Float64(from)) + } + case "Time", "time.Time": + convertFunc = func(from any, to reflect.Value) { + *to.Addr().Interface().(*time.Time) = localCommonConverter.Time(from) + } + case "GTime", "gtime.Time": + convertFunc = func(from any, to reflect.Value) { + v := localCommonConverter.GTime(from) + if v == nil { + v = gtime.New() + } + *to.Addr().Interface().(*gtime.Time) = *v + } + case "bool": + convertFunc = func(from any, to reflect.Value) { + to.SetBool(localCommonConverter.Bool(from)) + } + case "[]byte": + convertFunc = func(from any, to reflect.Value) { + to.SetBytes(localCommonConverter.Bytes(from)) + } + default: + return nil + } + return convertFunc +} + +func (csi *CachedStructInfo) genPriorityTagAndFieldName( + field reflect.StructField, priorityTags []string, +) (priorityTagAndFieldName []string) { + for _, tag := range priorityTags { + value, ok := field.Tag.Lookup(tag) + if ok { + // If there's something else in the tag string, + // it uses the first part which is split using char ','. + // Example: + // orm:"id, priority" + // orm:"name, with:uid=id" + tagValueItems := strings.Split(value, ",") + // json:",omitempty" + trimmedTagName := strings.TrimSpace(tagValueItems[0]) + if trimmedTagName != "" { + priorityTagAndFieldName = append(priorityTagAndFieldName, trimmedTagName) + break + } + } + } + priorityTagAndFieldName = append(priorityTagAndFieldName, field.Name) + return +} + +func (csi *CachedStructInfo) checkTypeHasCustomConvert(fieldType reflect.Type) bool { + if fieldType.Kind() == reflect.Ptr { + fieldType = fieldType.Elem() + } + _, ok := customConvertTypeMap[fieldType] + return ok +} + +func (csi *CachedStructInfo) genPtrConvertFunc( + convertFunc func(from any, to reflect.Value), +) func(from any, to reflect.Value) { + return func(from any, to reflect.Value) { + if to.IsNil() { + to.Set(reflect.New(to.Type().Elem())) + } + convertFunc(from, to.Elem()) + } +} diff --git a/util/gconv/internal/structcache/structcache_pool.go b/util/gconv/internal/structcache/structcache_pool.go new file mode 100644 index 000000000..30d4bca9e --- /dev/null +++ b/util/gconv/internal/structcache/structcache_pool.go @@ -0,0 +1,33 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package structcache + +import ( + "sync" +) + +var ( + poolUsedParamsKeyOrTagNameMap = &sync.Pool{ + New: func() any { + return make(map[string]struct{}) + }, + } +) + +// GetUsedParamsKeyOrTagNameMapFromPool retrieves and returns a map for storing params key or tag name. +func GetUsedParamsKeyOrTagNameMapFromPool() map[string]struct{} { + return poolUsedParamsKeyOrTagNameMap.Get().(map[string]struct{}) +} + +// PutUsedParamsKeyOrTagNameMapToPool puts a map for storing params key or tag name into pool for re-usage. +func PutUsedParamsKeyOrTagNameMapToPool(m map[string]struct{}) { + // need to be cleared before putting back into pool. + for k := range m { + delete(m, k) + } + poolUsedParamsKeyOrTagNameMap.Put(m) +} diff --git a/util/gpage/gpage.go b/util/gpage/gpage.go index 1570ff1e2..afdb3e650 100644 --- a/util/gpage/gpage.go +++ b/util/gpage/gpage.go @@ -9,6 +9,7 @@ package gpage import ( "fmt" + "html" "math" "github.com/gogf/gf/v2/text/gstr" @@ -215,12 +216,12 @@ func (p *Page) GetLink(page int, text, title string) string { if len(p.AjaxActionName) > 0 { return fmt.Sprintf( `%s`, - p.LinkStyle, p.AjaxActionName, p.GetUrl(page), title, text, + p.LinkStyle, p.AjaxActionName, p.GetUrl(page), html.EscapeString(title), text, ) } else { return fmt.Sprintf( `%s`, - p.LinkStyle, p.GetUrl(page), title, text, + p.LinkStyle, p.GetUrl(page), html.EscapeString(title), text, ) } } diff --git a/util/grand/grand_buffer.go b/util/grand/grand_buffer.go index 4527c25a2..4f527babc 100644 --- a/util/grand/grand_buffer.go +++ b/util/grand/grand_buffer.go @@ -28,7 +28,7 @@ func init() { go asyncProducingRandomBufferBytesLoop() } -// asyncProducingRandomBufferBytes is a named goroutine, which uses an asynchronous goroutine +// asyncProducingRandomBufferBytesLoop is a named goroutine, which uses an asynchronous goroutine // to produce the random bytes, and a buffer chan to store the random bytes. // So it has high performance to generate random numbers. func asyncProducingRandomBufferBytesLoop() { diff --git a/util/gtag/gtag.go b/util/gtag/gtag.go index edcd96247..d4d675523 100644 --- a/util/gtag/gtag.go +++ b/util/gtag/gtag.go @@ -11,41 +11,45 @@ package gtag const ( - Default = "default" // Default value tag of struct field for receiving parameters from HTTP request. - DefaultShort = "d" // Short name of Default. - Param = "param" // Parameter name for converting certain parameter to specified struct field. - ParamShort = "p" // Short name of Param. - Valid = "valid" // Validation rule tag for struct of field. - ValidShort = "v" // Short name of Valid. - NoValidation = "nv" // No validation for specified struct/field. - ORM = "orm" // ORM tag for ORM feature, which performs different features according scenarios. - Arg = "arg" // Arg tag for struct, usually for command argument option. - Brief = "brief" // Brief tag for struct, usually be considered as summary. - Root = "root" // Root tag for struct, usually for nested commands management. - Additional = "additional" // Additional tag for struct, usually for additional description of command. - AdditionalShort = "ad" // Short name of Additional. - Path = `path` // Route path for HTTP request. - Method = `method` // Route method for HTTP request. - Domain = `domain` // Route domain for HTTP request. - Mime = `mime` // MIME type for HTTP request/response. - Consumes = `consumes` // MIME type for HTTP request. - Summary = `summary` // Summary for struct, usually for OpenAPI in request struct. - SummaryShort = `sm` // Short name of Summary. - SummaryShort2 = `sum` // Short name of Summary. - Description = `description` // Description for struct, usually for OpenAPI in request struct. - DescriptionShort = `dc` // Short name of Description. - DescriptionShort2 = `des` // Short name of Description. - Example = `example` // Example for struct, usually for OpenAPI in request struct. - ExampleShort = `eg` // Short name of Example. - Examples = `examples` // Examples for struct, usually for OpenAPI in request struct. - ExamplesShort = `egs` // Short name of Examples. - ExternalDocs = `externalDocs` // External docs for struct, always for OpenAPI in request struct. - ExternalDocsShort = `ed` // Short name of ExternalDocs. - GConv = "gconv" // GConv defines the converting target name for specified struct field. - GConvShort = "c" // GConv defines the converting target name for specified struct field. - Json = "json" // Json tag is supported by stdlib. - Security = "security" // Security defines scheme for authentication. Detail to see https://swagger.io/docs/specification/authentication/ - In = "in" // Swagger distinguishes between the following parameter types based on the parameter location. Detail to see https://swagger.io/docs/specification/describing-parameters/ + Default = "default" // Default value tag of struct field for receiving parameters from HTTP request. + DefaultShort = "d" // Short name of Default. + Param = "param" // Parameter name for converting certain parameter to specified struct field. + ParamShort = "p" // Short name of Param. + Valid = "valid" // Validation rule tag for struct of field. + ValidShort = "v" // Short name of Valid. + NoValidation = "nv" // No validation for specified struct/field. + ORM = "orm" // ORM tag for ORM feature, which performs different features according scenarios. + Arg = "arg" // Arg tag for struct, usually for command argument option. + Brief = "brief" // Brief tag for struct, usually be considered as summary. + Root = "root" // Root tag for struct, usually for nested commands management. + Additional = "additional" // Additional tag for struct, usually for additional description of command. + AdditionalShort = "ad" // Short name of Additional. + Path = `path` // Route path for HTTP request. + Method = `method` // Route method for HTTP request. + Domain = `domain` // Route domain for HTTP request. + Mime = `mime` // MIME type for HTTP request/response. + Consumes = `consumes` // MIME type for HTTP request. + Summary = `summary` // Summary for struct, usually for OpenAPI in request struct. + SummaryShort = `sm` // Short name of Summary. + SummaryShort2 = `sum` // Short name of Summary. + Description = `description` // Description for struct, usually for OpenAPI in request struct. + DescriptionShort = `dc` // Short name of Description. + DescriptionShort2 = `des` // Short name of Description. + Example = `example` // Example for struct, usually for OpenAPI in request struct. + ExampleShort = `eg` // Short name of Example. + Examples = `examples` // Examples for struct, usually for OpenAPI in request struct. + ExamplesShort = `egs` // Short name of Examples. + ExternalDocs = `externalDocs` // External docs for struct, always for OpenAPI in request struct. + ExternalDocsShort = `ed` // Short name of ExternalDocs. + GConv = "gconv" // GConv defines the converting target name for specified struct field. + GConvShort = "c" // GConv defines the converting target name for specified struct field. + Json = "json" // Json tag is supported by stdlib. + Security = "security" // Security defines scheme for authentication. Detail to see https://swagger.io/docs/specification/authentication/ + In = "in" // Swagger distinguishes between the following parameter types based on the parameter location. Detail to see https://swagger.io/docs/specification/describing-parameters/ + Required = "required" // OpenAPIv3 required attribute name for request body. + Status = "status" // Response status code, usually for OpenAPI in response struct. + ResponseExample = "responseExample" // Response example resource path, usually for OpenAPI in response struct. + ResponseExampleShort = "resEg" // Short name of ResponseExample. ) // StructTagPriority defines the default priority tags for Map*/Struct* functions. diff --git a/util/gutil/gutil.go b/util/gutil/gutil.go index b77d6c2fd..2c5a555d1 100644 --- a/util/gutil/gutil.go +++ b/util/gutil/gutil.go @@ -18,9 +18,9 @@ const ( ) // Keys retrieves and returns the keys from given map or struct. -func Keys(mapOrStruct interface{}) (keysOrAttrs []string) { +func Keys(mapOrStruct any) (keysOrAttrs []string) { keysOrAttrs = make([]string, 0) - if m, ok := mapOrStruct.(map[string]interface{}); ok { + if m, ok := mapOrStruct.(map[string]any); ok { for k := range m { keysOrAttrs = append(keysOrAttrs, k) } @@ -63,6 +63,7 @@ func Keys(mapOrStruct interface{}) (keysOrAttrs []string) { keysOrAttrs = append(keysOrAttrs, fieldType.Name) } } + default: } return } @@ -108,6 +109,7 @@ func Values(mapOrStruct interface{}) (values []interface{}) { values = append(values, reflectValue.Field(i).Interface()) } } + default: } return } diff --git a/util/gutil/gutil_default.go b/util/gutil/gutil_default.go index 881b03744..593986ebc 100644 --- a/util/gutil/gutil_default.go +++ b/util/gutil/gutil_default.go @@ -20,7 +20,7 @@ func GetOrDefaultStr(def string, param ...string) string { // It returns `param[0]` if it is available, or else it returns `def`. func GetOrDefaultAny(def interface{}, param ...interface{}) interface{} { value := def - if len(param) > 0 && param[0] != "" { + if len(param) > 0 && param[0] != nil { value = param[0] } return value diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index d30f79b6f..69282cf99 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -465,6 +465,7 @@ func doDumpDefault(in doDumpInternalInput) { func addSlashesForString(s string) string { return gstr.ReplaceByMap(s, map[string]string{ `"`: `\"`, + `'`: `\'`, "\r": `\r`, "\t": `\t`, "\n": `\n`, diff --git a/util/gutil/gutil_z_unit_test.go b/util/gutil/gutil_z_unit_test.go index 20971aff8..2583ba307 100755 --- a/util/gutil/gutil_z_unit_test.go +++ b/util/gutil/gutil_z_unit_test.go @@ -204,5 +204,7 @@ func Test_GetOrDefaultAny(t *testing.T) { t.Assert(gutil.GetOrDefaultAny("a", "b"), "b") t.Assert(gutil.GetOrDefaultAny("a", "b", "c"), "b") t.Assert(gutil.GetOrDefaultAny("a"), "a") + t.Assert(gutil.GetOrDefaultAny("a", nil), "a") + t.Assert(gutil.GetOrDefaultAny("a", ""), "") }) } diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index 129dafbc3..e2ba2121e 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -263,6 +263,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Array: // Nothing to do. continue + default: } } v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ @@ -272,6 +273,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error ErrorMaps: errorMaps, ResultSequenceRules: &resultSequenceRules, }) + default: } } if v.bail && len(errorMaps) > 0 { @@ -284,6 +286,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error // The following logic is the same as some of CheckMap but with sequence support. for _, checkRuleItem := range checkRules { + // it ignores Meta object. if !checkRuleItem.IsMeta { value = getPossibleValueFromMap( inputParamMap, checkRuleItem.Name, fieldToAliasNameMap[checkRuleItem.Name], @@ -293,13 +296,16 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error if value != nil { switch checkRuleItem.FieldKind { case reflect.Struct, reflect.Map: + // empty struct or map. if gconv.String(value) == emptyJsonObjectStr { - value = "" + value = nil } case reflect.Slice, reflect.Array: + // empty slice. if gconv.String(value) == emptyJsonArrayStr { - value = "" + value = []any{} } + default: } } // It checks each rule and its value in loop. @@ -322,6 +328,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error required := false // rule => error for ruleKey := range errorItem { + // it checks whether current rule is kind of required rule. if required = v.checkRuleRequired(ruleKey); required { break } diff --git a/util/gvalid/gvalid_z_unit_feature_rule_test.go b/util/gvalid/gvalid_z_unit_feature_rule_test.go index c4c10d615..7d16bae83 100755 --- a/util/gvalid/gvalid_z_unit_feature_rule_test.go +++ b/util/gvalid/gvalid_z_unit_feature_rule_test.go @@ -1577,6 +1577,10 @@ func Test_Enums(t *testing.T) { Id int Enums EnumsTest `v:"enums"` } + type PointerParams struct { + Id int + Enums *EnumsTest `v:"enums"` + } type SliceParams struct { Id int Enums []EnumsTest `v:"foreach|enums"` @@ -1601,6 +1605,13 @@ func Test_Enums(t *testing.T) { }).Run(ctx) t.Assert(err, "The Enums value `c` should be in enums of: [\"a\",\"b\"]") + var b EnumsTest = "b" + err = g.Validator().Data(&PointerParams{ + Id: 1, + Enums: &b, + }).Run(ctx) + t.AssertNil(err) + err = g.Validator().Data(&SliceParams{ Id: 1, Enums: []EnumsTest{EnumsTestA, EnumsTestB}, diff --git a/util/gvalid/gvalid_z_unit_issue_test.go b/util/gvalid/gvalid_z_unit_issue_test.go index d7520d99d..38aea0739 100644 --- a/util/gvalid/gvalid_z_unit_issue_test.go +++ b/util/gvalid/gvalid_z_unit_issue_test.go @@ -8,8 +8,15 @@ package gvalid_test import ( "context" + "fmt" "testing" + "time" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/guid" "github.com/gogf/gf/v2/util/gvalid" ) @@ -34,3 +41,76 @@ func Test_Issue2503(t *testing.T) { t.Fatal(err) } } + +type Issue3636SliceV struct{} + +func init() { + rule := Issue3636SliceV{} + gvalid.RegisterRule(rule.Name(), rule.Run) +} + +func (r Issue3636SliceV) Name() string { + return "slice-v" +} + +func (r Issue3636SliceV) Message() string { + return "not a slice" +} + +func (r Issue3636SliceV) Run(_ context.Context, in gvalid.RuleFuncInput) error { + for _, v := range in.Value.Slice() { + if v == "" { + return gerror.New("empty value") + } + } + if !in.Value.IsSlice() { + return gerror.New("not a slice") + } + return nil +} + +type Issue3636HelloReq struct { + g.Meta `path:"/hello" method:"POST"` + + Name string `json:"name" v:"required" dc:"Your name"` + S []string `json:"s" v:"slice-v" dc:"S"` +} +type Issue3636HelloRes struct { + Name string `json:"name" v:"required" dc:"Your name"` + S []string `json:"s" v:"slice-v" dc:"S"` +} + +type Issue3636Hello struct{} + +func (Issue3636Hello) Say(ctx context.Context, req *Issue3636HelloReq) (res *Issue3636HelloRes, err error) { + res = &Issue3636HelloRes{ + Name: req.Name, + S: req.S, + } + return +} + +// https://github.com/gogf/gf/issues/3636 +func Test_Issue3636(t *testing.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3636Hello), + ) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + t.Assert( + c.PostContent(ctx, "/hello", `{"name": "t", "s" : []}`), + `{"code":0,"message":"","data":{"name":"t","s":[]}}`, + ) + }) +} diff --git a/util/gvalid/internal/builtin/builtin_enums.go b/util/gvalid/internal/builtin/builtin_enums.go index 071ec4d11..1c370f511 100644 --- a/util/gvalid/internal/builtin/builtin_enums.go +++ b/util/gvalid/internal/builtin/builtin_enums.go @@ -47,8 +47,9 @@ func (r RuleEnums) Run(in RunInput) error { var ( pkgPath = in.ValueType.PkgPath() typeName = in.ValueType.Name() + typeKind = in.ValueType.Kind() ) - if in.ValueType.Kind() == reflect.Slice { + if typeKind == reflect.Slice || typeKind == reflect.Ptr { pkgPath = in.ValueType.Elem().PkgPath() typeName = in.ValueType.Elem().Name() } diff --git a/version.go b/version.go index e68383e37..d6ce791b0 100644 --- a/version.go +++ b/version.go @@ -2,5 +2,5 @@ package gf const ( // VERSION is the current GoFrame version. - VERSION = "v2.7.2" + VERSION = "v2.8.1" )