mirror of
https://github.com/golang/go.git
synced 2024-09-21 18:38:37 +00:00
Merge remote-tracking branch 'origin/master' into feature/sync-atomic-and-or-loong64
This commit is contained in:
commit
9755db5406
45
.github/ISSUE_TEMPLATE/00-bug.md
vendored
45
.github/ISSUE_TEMPLATE/00-bug.md
vendored
@ -1,45 +0,0 @@
|
||||
---
|
||||
name: Bugs
|
||||
about: The go command, standard library, or anything else
|
||||
title: "affected/package: "
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### What version of Go are you using (`go version`)?
|
||||
|
||||
<pre>
|
||||
$ go version
|
||||
|
||||
</pre>
|
||||
|
||||
### Does this issue reproduce with the latest release?
|
||||
|
||||
|
||||
|
||||
### What operating system and processor architecture are you using (`go env`)?
|
||||
|
||||
<details><summary><code>go env</code> Output</summary><br><pre>
|
||||
$ go env
|
||||
|
||||
</pre></details>
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on go.dev/play is best.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
94
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
Normal file
94
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Bugs
|
||||
description: The go command, standard library, or anything else
|
||||
title: "import/path: issue title"
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
|
||||
|
||||
- type: input
|
||||
id: go-version
|
||||
attributes:
|
||||
label: Go version
|
||||
description: |
|
||||
What version of Go are you using (`go version`)?
|
||||
|
||||
Note: we only [support](https://go.dev/doc/devel/release#policy) the two most recent major releases.
|
||||
placeholder: ex. go version go1.20.7 darwin/arm64
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: go-env
|
||||
attributes:
|
||||
label: "Output of `go env` in your module/workspace:"
|
||||
placeholder: |
|
||||
GO111MODULE=""
|
||||
GOARCH="arm64"
|
||||
GOBIN="/Users/gopher/go/bin"
|
||||
GOCACHE="/Users/gopher/go/cache"
|
||||
GOENV="/Users/gopher/Library/Application Support/go/env"
|
||||
GOEXE=""
|
||||
GOEXPERIMENT=""
|
||||
GOFLAGS=""
|
||||
GOHOSTARCH="arm64"
|
||||
GOHOSTOS="darwin"
|
||||
GOINSECURE=""
|
||||
GOMODCACHE="/Users/gopher/go/pkg/mod"
|
||||
GONOPROXY=""
|
||||
GONOSUMDB=""
|
||||
GOOS="darwin"
|
||||
GOPATH="/Users/gopher/go"
|
||||
GOPRIVATE=""
|
||||
GOPROXY="https://proxy.golang.org,direct"
|
||||
GOROOT="/usr/local/go"
|
||||
GOSUMDB="sum.golang.org"
|
||||
GOTMPDIR=""
|
||||
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64"
|
||||
GOVCS=""
|
||||
GOVERSION="go1.20.7"
|
||||
GCCGO="gccgo"
|
||||
AR="ar"
|
||||
CC="clang"
|
||||
CXX="clang++"
|
||||
CGO_ENABLED="1"
|
||||
GOMOD="/dev/null"
|
||||
GOWORK=""
|
||||
CGO_CFLAGS="-O2 -g"
|
||||
CGO_CPPFLAGS=""
|
||||
CGO_CXXFLAGS="-O2 -g"
|
||||
CGO_FFLAGS="-O2 -g"
|
||||
CGO_LDFLAGS="-O2 -g"
|
||||
PKG_CONFIG="pkg-config"
|
||||
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/44/nbbyll_10jd0z8rj_qxm43740000gn/T/go-build2331607515=/tmp/go-build -gno-record-gcc-switches -fno-common"
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
description: Command invocations and their associated output, functions with their arguments and return results, full stacktraces for panics (upload a file if it is very long), etc. Prefer copying text output over using screenshots.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
description: Why is the current output incorrect, and any additional context we may need to understand the issue.
|
||||
validations:
|
||||
required: true
|
49
.github/ISSUE_TEMPLATE/01-pkgsite.md
vendored
49
.github/ISSUE_TEMPLATE/01-pkgsite.md
vendored
@ -1,49 +0,0 @@
|
||||
---
|
||||
name: Pkg.go.dev bugs or feature requests
|
||||
about: Issues or feature requests for the documentation site
|
||||
title: "x/pkgsite: "
|
||||
labels: pkgsite
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### What is the URL of the page with the issue?
|
||||
|
||||
|
||||
|
||||
### What is your user agent?
|
||||
|
||||
<!--
|
||||
You can find your user agent here:
|
||||
https://www.google.com/search?q=what+is+my+user+agent
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### Screenshot
|
||||
|
||||
<!--
|
||||
Please paste a screenshot of the page.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
|
||||
Starting with a Private/Incognito tab/window may help rule out problematic browser extensions.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
47
.github/ISSUE_TEMPLATE/01-pkgsite.yml
vendored
Normal file
47
.github/ISSUE_TEMPLATE/01-pkgsite.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
name: Pkg.go.dev bugs or feature requests
|
||||
description: Issues or feature requests for the documentation site
|
||||
title: "x/pkgsite: issue title"
|
||||
labels: ["pkgsite"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks!"
|
||||
- type: input
|
||||
id: url
|
||||
attributes:
|
||||
label: "What is the URL of the page with the issue?"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: user-agent
|
||||
attributes:
|
||||
label: "What is your user agent?"
|
||||
description: "You can find your user agent here: https://www.google.com/search?q=what+is+my+user+agent"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: "Screenshot"
|
||||
description: "Please paste a screenshot of the page."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. Starting with a Private/Incognito tab/window may help rule out problematic browser extensions."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
validations:
|
||||
required: true
|
39
.github/ISSUE_TEMPLATE/02-pkgsite-removal.md
vendored
39
.github/ISSUE_TEMPLATE/02-pkgsite-removal.md
vendored
@ -1,39 +0,0 @@
|
||||
---
|
||||
name: Pkg.go.dev package removal request
|
||||
about: Request a package be removed from the documentation site (pkg.go.dev)
|
||||
title: "x/pkgsite: package removal request for [type path here]"
|
||||
labels: pkgsite/package-removal
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### What is the path of the package that you would like to have removed?
|
||||
|
||||
<!---
|
||||
We can remove packages with a shared path prefix.
|
||||
For example, a request for "github.com/author" would remove all pkg.go.dev pages with that package path prefix.
|
||||
--->
|
||||
|
||||
|
||||
|
||||
### Are you the owner of this package?
|
||||
|
||||
<!---
|
||||
Only the package owners can request to have their packages removed from pkg.go.dev.
|
||||
--->
|
||||
|
||||
|
||||
|
||||
### What is the reason that you could not retract this package instead?
|
||||
|
||||
<!---
|
||||
If you would like to have your module removed from pkg.go.dev, we recommend that you retract them, so that they can be removed from the go command and proxy.golang.org as well.
|
||||
|
||||
Retracting a module version involves adding a retract directive to your go.mod file and publishing a new version. For example: https://github.com/jba/retract-demo/blob/main/go.mod#L5-L8
|
||||
|
||||
See https://pkg.go.dev/about#removing-a-package for additional tips on retractions.
|
||||
--->
|
||||
|
||||
|
42
.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml
vendored
Normal file
42
.github/ISSUE_TEMPLATE/02-pkgsite-removal.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
name: Pkg.go.dev package removal request
|
||||
description: Request a package be removed from the documentation site (pkg.go.dev)
|
||||
title: "x/pkgsite: package removal request for [type path here]"
|
||||
labels: ["pkgsite/package-removal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks!"
|
||||
- type: input
|
||||
id: package-path
|
||||
attributes:
|
||||
label: "What is the path of the package that you would like to have removed?"
|
||||
description: |
|
||||
We can remove packages with a shared path prefix.
|
||||
For example, a request for 'github.com/author' would remove all pkg.go.dev pages with that package path prefix.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: package-owner
|
||||
attributes:
|
||||
label: "Are you the owner of this package?"
|
||||
description: |
|
||||
Only the package owners can request to have their packages removed from pkg.go.dev.
|
||||
If the package path doesn't include your github username, please provide some other form of proof of ownership.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: retraction-reason
|
||||
attributes:
|
||||
label: "What is the reason that you could not retract this package instead?"
|
||||
description: |
|
||||
Requesting we remove a module here only hides the generated documentation on pkg.go.dev.
|
||||
It does not affect the behaviour of proxy.golang.org or the go command.
|
||||
Instead we recommend using the retract directive which will be processed by all 3 of the above.
|
||||
|
||||
If you have deleted your repo, please recreate it and publish a retraction.
|
||||
|
||||
Retracting a module version involves adding a retract directive to your go.mod file and publishing a new version.
|
||||
For example: https://github.com/jba/retract-demo/blob/main/go.mod#L5-L8.
|
||||
See https://pkg.go.dev/about#removing-a-package for additional tips on retractions.
|
||||
validations:
|
||||
required: true
|
63
.github/ISSUE_TEMPLATE/03-gopls.md
vendored
63
.github/ISSUE_TEMPLATE/03-gopls.md
vendored
@ -1,63 +0,0 @@
|
||||
---
|
||||
name: Gopls bugs or feature requests
|
||||
about: Issues or feature requests for the Go language server (gopls)
|
||||
title: "x/tools/gopls: "
|
||||
labels:
|
||||
- gopls
|
||||
- Tools
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
-->
|
||||
|
||||
### gopls version
|
||||
|
||||
<!--
|
||||
Output of `gopls -v version` on the command line
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### go env
|
||||
|
||||
<!--
|
||||
Output of `go env` on the command line in your workspace directory
|
||||
-->
|
||||
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on go.dev/play is better.
|
||||
A failing unit test is the best.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
||||
|
||||
### Editor and settings
|
||||
|
||||
<!--
|
||||
Your editor and any settings you have configured (for example, your VSCode settings.json file)
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### Logs
|
||||
|
||||
<!--
|
||||
If possible please include gopls logs. Instructions for capturing them can be found here:
|
||||
https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md#capture-logs
|
||||
-->
|
||||
|
||||
|
56
.github/ISSUE_TEMPLATE/03-gopls.yml
vendored
Normal file
56
.github/ISSUE_TEMPLATE/03-gopls.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
name: Gopls bugs or feature requests
|
||||
description: Issues or feature requests for the Go language server (gopls)
|
||||
title: "x/tools/gopls: issue title"
|
||||
labels: ["gopls", "Tools"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks!"
|
||||
- type: input
|
||||
id: gopls-version
|
||||
attributes:
|
||||
label: "gopls version"
|
||||
description: "Output of `gopls -v version` on the command line"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: go-env
|
||||
attributes:
|
||||
label: "go env"
|
||||
description: "Output of `go env` on the command line in your workspace directory"
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is better. A failing unit test is the best."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: editor-and-settings
|
||||
attributes:
|
||||
label: "Editor and settings"
|
||||
description: "Your editor and any settings you have configured (for example, your VSCode settings.json file)"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: "Logs"
|
||||
description: "If possible please include gopls logs. Instructions for capturing them can be found here: https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md#capture-logs"
|
||||
validations:
|
||||
required: false
|
51
.github/ISSUE_TEMPLATE/04-vuln.md
vendored
51
.github/ISSUE_TEMPLATE/04-vuln.md
vendored
@ -1,51 +0,0 @@
|
||||
---
|
||||
name: Go vulnerability management - bugs and feature requests
|
||||
about: Issues or feature requests about Go vulnerability management
|
||||
title: "x/vuln: "
|
||||
labels: "vulncheck or vulndb"
|
||||
---
|
||||
|
||||
<!--
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
|
||||
To add a new vulnerability to the Go vulnerability database
|
||||
(https://vuln.go.dev), see https://go.dev/s/vulndb-report-new.
|
||||
|
||||
To report an issue about a report, see https://go.dev/s/vulndb-report-feedback.
|
||||
-->
|
||||
|
||||
### What version of Go are you using (`go version`)?
|
||||
|
||||
<pre>
|
||||
$ go version
|
||||
|
||||
</pre>
|
||||
|
||||
### Does this issue reproduce at the latest version of golang.org/x/vuln?
|
||||
|
||||
|
||||
|
||||
### What operating system and processor architecture are you using (`go env`)?
|
||||
|
||||
<details><summary><code>go env</code> Output</summary><br><pre>
|
||||
$ go env
|
||||
|
||||
</pre></details>
|
||||
|
||||
### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on go.dev/play is best.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
|
52
.github/ISSUE_TEMPLATE/04-vuln.yml
vendored
Normal file
52
.github/ISSUE_TEMPLATE/04-vuln.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
name: Go vulnerability management - bugs and feature requests
|
||||
description: Issues or feature requests about Go vulnerability management
|
||||
title: "x/vuln: issue title"
|
||||
labels: ["vulncheck or vulndb"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please answer these questions before submitting your issue. Thanks! To add a new vulnerability to the Go vulnerability database (https://vuln.go.dev), see https://go.dev/s/vulndb-report-new. To report an issue about a report, see https://go.dev/s/vulndb-report-feedback."
|
||||
- type: textarea
|
||||
id: govulncheck-version
|
||||
attributes:
|
||||
label: govulncheck version
|
||||
description: What version of govulncheck are you using (`govulncheck -version`)?
|
||||
placeholder: |
|
||||
Go: devel go1.22-0262ea1ff9 Thu Oct 26 18:46:50 2023 +0000
|
||||
Scanner: govulncheck@v1.0.2-0.20231108200754-fcf7dff7b242
|
||||
DB: https://vuln.go.dev
|
||||
DB updated: 2023-11-21 15:39:17 +0000 UTC
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce-latest-version
|
||||
attributes:
|
||||
label: "Does this issue reproduce at the latest version of golang.org/x/vuln?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: go-env
|
||||
attributes:
|
||||
label: "Output of `go env` in your module/workspace:"
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-did-you-do
|
||||
attributes:
|
||||
label: "What did you do?"
|
||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: "What did you see happen?"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: "What did you expect to see?"
|
||||
validations:
|
||||
required: true
|
13
.github/ISSUE_TEMPLATE/10-proposal.md
vendored
13
.github/ISSUE_TEMPLATE/10-proposal.md
vendored
@ -1,13 +0,0 @@
|
||||
---
|
||||
name: Proposals
|
||||
about: New external API or other notable changes
|
||||
title: "proposal: affected/package: "
|
||||
labels: Proposal
|
||||
---
|
||||
|
||||
<!--
|
||||
Our proposal process is documented here:
|
||||
https://go.dev/s/proposal-process
|
||||
-->
|
||||
|
||||
|
15
.github/ISSUE_TEMPLATE/10-proposal.yml
vendored
Normal file
15
.github/ISSUE_TEMPLATE/10-proposal.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: Proposals
|
||||
description: New external API or other notable changes
|
||||
title: "proposal: import/path: proposal title"
|
||||
labels: ["Proposal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Our proposal process is documented here: https://go.dev/s/proposal-process"
|
||||
- type: textarea
|
||||
id: proposal-details
|
||||
attributes:
|
||||
label: "Proposal Details"
|
||||
description: "Please provide the details of your proposal here."
|
||||
validations:
|
||||
required: true
|
55
.github/ISSUE_TEMPLATE/11-language-change.md
vendored
55
.github/ISSUE_TEMPLATE/11-language-change.md
vendored
@ -1,55 +0,0 @@
|
||||
---
|
||||
name: Language Change Proposals
|
||||
about: Changes to the language
|
||||
title: "proposal: Go 2: "
|
||||
labels:
|
||||
- Proposal
|
||||
- v2
|
||||
- LanguageChange
|
||||
---
|
||||
|
||||
<!--
|
||||
Our process for evaluating language changes can be found here:
|
||||
https://go.googlesource.com/proposal/+/refs/heads/master#language-changes
|
||||
-->
|
||||
|
||||
### Author background
|
||||
|
||||
- **Would you consider yourself a novice, intermediate, or experienced Go programmer?**
|
||||
- **What other languages do you have experience with?**
|
||||
|
||||
### Related proposals
|
||||
|
||||
- **Has this idea, or one like it, been proposed before?**
|
||||
- **If so, how does this proposal differ?**
|
||||
- **Does this affect error handling?**
|
||||
- **If so, how does this differ from previous error handling proposals?**
|
||||
- **Is this about generics?**
|
||||
- **If so, how does this relate to the accepted design and other generics proposals?**
|
||||
|
||||
### Proposal
|
||||
|
||||
- **What is the proposed change?**
|
||||
- **Who does this proposal help, and why?**
|
||||
- **Please describe as precisely as possible the change to the language.**
|
||||
- **What would change in the language spec?**
|
||||
- **Please also describe the change informally, as in a class teaching Go.**
|
||||
- **Is this change backward compatible?**
|
||||
- Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
|
||||
Show example code before and after the change.
|
||||
- **Before**
|
||||
- **After**
|
||||
- **Orthogonality: how does this change interact or overlap with existing features?**
|
||||
- **Is the goal of this change a performance improvement?**
|
||||
- **If so, what quantifiable improvement should we expect?**
|
||||
- **How would we measure it?**
|
||||
|
||||
### Costs
|
||||
|
||||
- **Would this change make Go easier or harder to learn, and why?**
|
||||
- **What is the cost of this proposal? (Every language change has a cost).**
|
||||
- **How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?**
|
||||
- **What is the compile time cost?**
|
||||
- **What is the run time cost?**
|
||||
- **Can you describe a possible implementation?**
|
||||
- **Do you have a prototype? (This is not required.)**
|
165
.github/ISSUE_TEMPLATE/11-language-change.yml
vendored
Normal file
165
.github/ISSUE_TEMPLATE/11-language-change.yml
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
name: Language Change Proposals
|
||||
description: Changes to the language
|
||||
labels: ["Proposal", "v2", "LanguageChange"]
|
||||
title: "proposal: Go 2: proposal title"
|
||||
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Our process for evaluating language changes can be found [here](https://go.googlesource.com/proposal/+/refs/heads/master#language-changes)
|
||||
|
||||
- type: dropdown
|
||||
id: author-go-experience
|
||||
attributes:
|
||||
label: "Go Programming Experience"
|
||||
description: "Would you consider yourself a novice, intermediate, or experienced Go programmer?"
|
||||
options:
|
||||
- "Novice"
|
||||
- "Intermediate"
|
||||
- "Experienced"
|
||||
default: 1
|
||||
|
||||
- type: input
|
||||
id: author-other-languages-experience
|
||||
attributes:
|
||||
label: "Other Languages Experience"
|
||||
description: "What other languages do you have experience with?"
|
||||
placeholder: "Go, Python, JS, Rust"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: related-idea
|
||||
attributes:
|
||||
label: "Related Idea"
|
||||
options:
|
||||
- label: "Has this idea, or one like it, been proposed before?"
|
||||
- label: "Does this affect error handling?"
|
||||
- label: "Is this about generics?"
|
||||
- label: "Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit"
|
||||
|
||||
- type: textarea
|
||||
id: related-proposals
|
||||
attributes:
|
||||
label: Has this idea, or one like it, been proposed before?
|
||||
description: If so, how does this proposal differ?
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1. Mention the related proposals
|
||||
2. then describe how this proposal differs
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error-handling-proposal
|
||||
attributes:
|
||||
label: Does this affect error handling?
|
||||
description: If so, how does this differ from previous error handling proposals?
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1.how does this differ from previous error handling proposals?
|
||||
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: generics-proposal
|
||||
attributes:
|
||||
label: Is this about generics?
|
||||
description: If so, how does this relate to the accepted design and other generics proposals?
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1. how does this relate to the accepted design and other generics proposals?
|
||||
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposal
|
||||
attributes:
|
||||
label: "Proposal"
|
||||
description: "What is the proposed change? Who does this proposal help, and why? Please describe as precisely as possible the change to the language."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: language-spec-changes
|
||||
attributes:
|
||||
label: "Language Spec Changes"
|
||||
description: "What would change in the language spec?"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: informal-change
|
||||
attributes:
|
||||
label: "Informal Change"
|
||||
description: "Please also describe the change informally, as in a class teaching Go."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: go-backwards-compatiblity
|
||||
attributes:
|
||||
label: Is this change backward compatible?
|
||||
description: Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
|
||||
placeholder: |
|
||||
Yes or No
|
||||
|
||||
If yes,
|
||||
1. Show example code before and after the change.
|
||||
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: orthogonality
|
||||
attributes:
|
||||
label: "Orthogonality: How does this change interact or overlap with existing features?"
|
||||
description: "Is the goal of this change a performance improvement? If so, what quantifiable improvement should we expect? How would we measure it?"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: learning-curve
|
||||
attributes:
|
||||
label: "Would this change make Go easier or harder to learn, and why?"
|
||||
|
||||
- type: textarea
|
||||
id: cost-description
|
||||
attributes:
|
||||
label: "Cost Description"
|
||||
description: "What is the cost of this proposal? (Every language change has a cost)"
|
||||
|
||||
- type: input
|
||||
id: go-toolchain
|
||||
attributes:
|
||||
label: Changes to Go ToolChain
|
||||
description: "How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected? "
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: perf-costs
|
||||
attributes:
|
||||
label: Performance Costs
|
||||
description: "What is the compile time cost? What is the run time cost? "
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: prototype
|
||||
attributes:
|
||||
label: "Prototype"
|
||||
description: "Can you describe a possible implementation?"
|
||||
validations:
|
||||
required: false
|
||||
|
2
.github/ISSUE_TEMPLATE/12-telemetry.yml
vendored
2
.github/ISSUE_TEMPLATE/12-telemetry.yml
vendored
@ -1,6 +1,6 @@
|
||||
name: Go Telemetry Proposals
|
||||
description: New telemetry counter or update on an existing one
|
||||
title: "x/telemetry/config: "
|
||||
title: "x/telemetry/config: proposal title"
|
||||
labels: ["Telemetry-Proposal"]
|
||||
projects: ["golang/29"]
|
||||
body:
|
||||
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,4 +1,4 @@
|
||||
blank_issues_enabled: false
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Questions
|
||||
about: Please use one of the forums for questions or general discussions
|
||||
|
144
api/go1.22.txt
Normal file
144
api/go1.22.txt
Normal file
@ -0,0 +1,144 @@
|
||||
pkg archive/tar, method (*Writer) AddFS(fs.FS) error #58000
|
||||
pkg archive/tar, type FileInfoNames interface { Gname, IsDir, ModTime, Mode, Name, Size, Sys, Uname } #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Gname(int) (string, error) #50102
|
||||
pkg archive/tar, type FileInfoNames interface, IsDir() bool #50102
|
||||
pkg archive/tar, type FileInfoNames interface, ModTime() time.Time #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Mode() fs.FileMode #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Name() string #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Size() int64 #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Sys() interface{} #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Uname(int) (string, error) #50102
|
||||
pkg archive/zip, method (*Writer) AddFS(fs.FS) error #54898
|
||||
pkg cmp, func Or[$0 comparable](...$0) $0 #60204
|
||||
pkg crypto/x509, func OIDFromInts([]uint64) (OID, error) #60665
|
||||
pkg crypto/x509, method (*CertPool) AddCertWithConstraint(*Certificate, func([]*Certificate) error) #57178
|
||||
pkg crypto/x509, method (OID) Equal(OID) bool #60665
|
||||
pkg crypto/x509, method (OID) EqualASN1OID(asn1.ObjectIdentifier) bool #60665
|
||||
pkg crypto/x509, method (OID) String() string #60665
|
||||
pkg crypto/x509, type Certificate struct, Policies []OID #60665
|
||||
pkg crypto/x509, type OID struct #60665
|
||||
pkg database/sql, method (*Null[$0]) Scan(interface{}) error #60370
|
||||
pkg database/sql, method (Null[$0]) Value() (driver.Value, error) #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct, V $0 #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct, Valid bool #60370
|
||||
pkg debug/elf, const R_LARCH_64_PCREL = 109 #63725
|
||||
pkg debug/elf, const R_LARCH_64_PCREL R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_ADD6 = 105 #63725
|
||||
pkg debug/elf, const R_LARCH_ADD6 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_ADD_ULEB128 = 107 #63725
|
||||
pkg debug/elf, const R_LARCH_ADD_ULEB128 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_ALIGN = 102 #63725
|
||||
pkg debug/elf, const R_LARCH_ALIGN R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_CFA = 104 #63725
|
||||
pkg debug/elf, const R_LARCH_CFA R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_DELETE = 101 #63725
|
||||
pkg debug/elf, const R_LARCH_DELETE R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_PCREL20_S2 = 103 #63725
|
||||
pkg debug/elf, const R_LARCH_PCREL20_S2 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_SUB6 = 106 #63725
|
||||
pkg debug/elf, const R_LARCH_SUB6 R_LARCH #63725
|
||||
pkg debug/elf, const R_LARCH_SUB_ULEB128 = 108 #63725
|
||||
pkg debug/elf, const R_LARCH_SUB_ULEB128 R_LARCH #63725
|
||||
pkg debug/elf, const R_MIPS_PC32 = 248 #61974
|
||||
pkg debug/elf, const R_MIPS_PC32 R_MIPS #61974
|
||||
pkg encoding/base32, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/base32, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg encoding/base64, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/base64, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg encoding/hex, func AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/hex, func AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg go/ast, func NewPackage //deprecated #52463
|
||||
pkg go/ast, func Unparen(Expr) Expr #60061
|
||||
pkg go/ast, type Importer //deprecated #52463
|
||||
pkg go/ast, type Object //deprecated #52463
|
||||
pkg go/ast, type Package //deprecated #52463
|
||||
pkg go/ast, type Scope //deprecated #52463
|
||||
pkg go/types, func NewAlias(*TypeName, Type) *Alias #63223
|
||||
pkg go/types, func Unalias(Type) Type #63223
|
||||
pkg go/types, method (*Alias) Obj() *TypeName #63223
|
||||
pkg go/types, method (*Alias) String() string #63223
|
||||
pkg go/types, method (*Alias) Underlying() Type #63223
|
||||
pkg go/types, method (*Info) PkgNameOf(*ast.ImportSpec) *PkgName #62037
|
||||
pkg go/types, method (Checker) PkgNameOf(*ast.ImportSpec) *PkgName #62037
|
||||
pkg go/types, type Alias struct #63223
|
||||
pkg go/types, type Info struct, FileVersions map[*ast.File]string #62605
|
||||
pkg go/version, func Compare(string, string) int #62039
|
||||
pkg go/version, func IsValid(string) bool #62039
|
||||
pkg go/version, func Lang(string) string #62039
|
||||
pkg html/template, const ErrJSTemplate //deprecated #61619
|
||||
pkg io, method (*SectionReader) Outer() (ReaderAt, int64, int64) #61870
|
||||
pkg log/slog, func SetLogLoggerLevel(Level) Level #62418
|
||||
pkg math/big, method (*Rat) FloatPrec() (int, bool) #50489
|
||||
pkg math/rand/v2, func ExpFloat64() float64 #61716
|
||||
pkg math/rand/v2, func Float32() float32 #61716
|
||||
pkg math/rand/v2, func Float64() float64 #61716
|
||||
pkg math/rand/v2, func Int() int #61716
|
||||
pkg math/rand/v2, func Int32() int32 #61716
|
||||
pkg math/rand/v2, func Int32N(int32) int32 #61716
|
||||
pkg math/rand/v2, func Int64() int64 #61716
|
||||
pkg math/rand/v2, func Int64N(int64) int64 #61716
|
||||
pkg math/rand/v2, func IntN(int) int #61716
|
||||
pkg math/rand/v2, func N[$0 intType]($0) $0 #61716
|
||||
pkg math/rand/v2, func New(Source) *Rand #61716
|
||||
pkg math/rand/v2, func NewChaCha8([32]uint8) *ChaCha8 #61716
|
||||
pkg math/rand/v2, func NewPCG(uint64, uint64) *PCG #61716
|
||||
pkg math/rand/v2, func NewZipf(*Rand, float64, float64, uint64) *Zipf #61716
|
||||
pkg math/rand/v2, func NormFloat64() float64 #61716
|
||||
pkg math/rand/v2, func Perm(int) []int #61716
|
||||
pkg math/rand/v2, func Shuffle(int, func(int, int)) #61716
|
||||
pkg math/rand/v2, func Uint32() uint32 #61716
|
||||
pkg math/rand/v2, func Uint32N(uint32) uint32 #61716
|
||||
pkg math/rand/v2, func Uint64() uint64 #61716
|
||||
pkg math/rand/v2, func Uint64N(uint64) uint64 #61716
|
||||
pkg math/rand/v2, func UintN(uint) uint #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) MarshalBinary() ([]uint8, error) #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) Seed([32]uint8) #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, method (*ChaCha8) UnmarshalBinary([]uint8) error #61716
|
||||
pkg math/rand/v2, method (*PCG) MarshalBinary() ([]uint8, error) #61716
|
||||
pkg math/rand/v2, method (*PCG) Seed(uint64, uint64) #61716
|
||||
pkg math/rand/v2, method (*PCG) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, method (*PCG) UnmarshalBinary([]uint8) error #61716
|
||||
pkg math/rand/v2, method (*Rand) ExpFloat64() float64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Float32() float32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Float64() float64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int() int #61716
|
||||
pkg math/rand/v2, method (*Rand) Int32() int32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int32N(int32) int32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int64() int64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Int64N(int64) int64 #61716
|
||||
pkg math/rand/v2, method (*Rand) IntN(int) int #61716
|
||||
pkg math/rand/v2, method (*Rand) NormFloat64() float64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Perm(int) []int #61716
|
||||
pkg math/rand/v2, method (*Rand) Shuffle(int, func(int, int)) #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint32() uint32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint32N(uint32) uint32 #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, method (*Rand) Uint64N(uint64) uint64 #61716
|
||||
pkg math/rand/v2, method (*Rand) UintN(uint) uint #61716
|
||||
pkg math/rand/v2, method (*Zipf) Uint64() uint64 #61716
|
||||
pkg math/rand/v2, type ChaCha8 struct #61716
|
||||
pkg math/rand/v2, type PCG struct #61716
|
||||
pkg math/rand/v2, type Rand struct #61716
|
||||
pkg math/rand/v2, type Source interface { Uint64 } #61716
|
||||
pkg math/rand/v2, type Source interface, Uint64() uint64 #61716
|
||||
pkg math/rand/v2, type Zipf struct #61716
|
||||
pkg net, method (*TCPConn) WriteTo(io.Writer) (int64, error) #58808
|
||||
pkg net/http, func FileServerFS(fs.FS) Handler #51971
|
||||
pkg net/http, func NewFileTransportFS(fs.FS) RoundTripper #51971
|
||||
pkg net/http, func ServeFileFS(ResponseWriter, *Request, fs.FS, string) #51971
|
||||
pkg net/http, method (*Request) PathValue(string) string #61410
|
||||
pkg net/http, method (*Request) SetPathValue(string, string) #61410
|
||||
pkg net/netip, method (AddrPort) Compare(AddrPort) int #61642
|
||||
pkg os, method (*File) WriteTo(io.Writer) (int64, error) #58808
|
||||
pkg reflect, func PtrTo //deprecated #59599
|
||||
pkg reflect, func TypeFor[$0 interface{}]() Type #60088
|
||||
pkg slices, func Concat[$0 interface{ ~[]$1 }, $1 interface{}](...$0) $0 #56353
|
||||
pkg syscall (linux-386), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-386-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-amd64), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-arm), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-arm-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg testing/slogtest, func Run(*testing.T, func(*testing.T) slog.Handler, func(*testing.T) map[string]interface{}) #61758
|
@ -1,9 +0,0 @@
|
||||
pkg archive/tar, type FileInfoNames interface { Gname, IsDir, ModTime, Mode, Name, Size, Sys, Uname } #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Gname(int) (string, error) #50102
|
||||
pkg archive/tar, type FileInfoNames interface, IsDir() bool #50102
|
||||
pkg archive/tar, type FileInfoNames interface, ModTime() time.Time #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Mode() fs.FileMode #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Name() string #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Size() int64 #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Sys() interface{} #50102
|
||||
pkg archive/tar, type FileInfoNames interface, Uname(int) (string, error) #50102
|
@ -1,6 +0,0 @@
|
||||
pkg syscall (linux-386), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-386-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-amd64), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-arm), type SysProcAttr struct, PidFD *int #51246
|
||||
pkg syscall (linux-arm-cgo), type SysProcAttr struct, PidFD *int #51246
|
@ -1,3 +0,0 @@
|
||||
pkg net/http, func ServeFileFS(ResponseWriter, *Request, fs.FS, string) #51971
|
||||
pkg net/http, func FileServerFS(fs.FS) Handler #51971
|
||||
pkg net/http, func NewFileTransportFS(fs.FS) RoundTripper #51971
|
@ -1,6 +0,0 @@
|
||||
pkg encoding/base32, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/base32, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg encoding/base64, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/base64, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
|
||||
pkg encoding/hex, func AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
|
||||
pkg encoding/hex, func AppendEncode([]uint8, []uint8) []uint8 #53693
|
@ -1 +0,0 @@
|
||||
pkg archive/zip, method (*Writer) AddFS(fs.FS) error #54898
|
@ -1 +0,0 @@
|
||||
pkg slices, func Concat[$0 interface{ ~[]$1 }, $1 interface{}](...$0) $0 #56353
|
@ -1 +0,0 @@
|
||||
pkg archive/tar, method (*Writer) AddFS(fs.FS) error #58000
|
@ -1 +0,0 @@
|
||||
pkg reflect, func PtrTo //deprecated #59599
|
@ -1 +0,0 @@
|
||||
pkg go/ast, func Unparen(Expr) Expr #60061
|
@ -1 +0,0 @@
|
||||
pkg reflect, func TypeFor[$0 interface{}]() Type #60088
|
@ -1 +0,0 @@
|
||||
pkg cmp, func Or[$0 comparable](...$0) $0 #60204
|
@ -1,5 +0,0 @@
|
||||
pkg database/sql, method (*Null[$0]) Scan(interface{}) error #60370
|
||||
pkg database/sql, method (Null[$0]) Value() (driver.Value, error) #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct, Valid bool #60370
|
||||
pkg database/sql, type Null[$0 interface{}] struct, V $0 #60370
|
@ -1,2 +0,0 @@
|
||||
pkg net/http, method (*Request) PathValue(string) string #61410
|
||||
pkg net/http, method (*Request) SetPathValue(string, string) #61410
|
@ -1,2 +0,0 @@
|
||||
pkg net/netip, method (AddrPort) Compare(AddrPort) int #61642
|
||||
pkg net/netip, method (Prefix) Compare(Prefix) int #61642
|
@ -1 +0,0 @@
|
||||
pkg testing/slogtest, func Run(*testing.T, func(*testing.T) slog.Handler, func(*testing.T) map[string]interface{}) #61758
|
@ -1,2 +0,0 @@
|
||||
pkg debug/elf, const R_MIPS_PC32 = 248 #61974
|
||||
pkg debug/elf, const R_MIPS_PC32 R_MIPS #61974
|
17
doc/asm.html
17
doc/asm.html
@ -464,6 +464,23 @@ Function is the outermost frame of the call stack. Traceback should stop at this
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="special-instructions">Special instructions</h3>
|
||||
|
||||
<p>
|
||||
The <code>PCALIGN</code> pseudo-instruction is used to indicate that the next instruction should be aligned
|
||||
to a specified boundary by padding with no-op instructions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is currently supported on arm64, amd64, ppc64, loong64 and riscv64.
|
||||
|
||||
For example, the start of the <code>MOVD</code> instruction below is aligned to 32 bytes:
|
||||
<pre>
|
||||
PCALIGN $32
|
||||
MOVD $2, R0
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h3 id="data-offsets">Interacting with Go types and constants</h3>
|
||||
|
||||
<p>
|
||||
|
@ -7,8 +7,11 @@
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
|
||||
<p>
|
||||
This is a reference manual for the Go programming language. For
|
||||
more information and other documents, see <a href="/">golang.org</a>.
|
||||
This is the reference manual for the Go programming language as it was for
|
||||
language version 1.17, in October 2021, before the introduction of generics.
|
||||
It is provided for historical interest.
|
||||
The current reference manual can be found <a href="/doc/go_spec.html">here</a>.
|
||||
For more information and other documents, see <a href="/">go.dev</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
953
doc/go1.22.html
953
doc/go1.22.html
File diff suppressed because it is too large
Load Diff
317
doc/go_spec.html
317
doc/go_spec.html
@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of Sep 13, 2023",
|
||||
"Subtitle": "Version of Dec 27, 2023",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
This is the reference manual for the Go programming language.
|
||||
The pre-Go1.18 version, without generics, can be found
|
||||
<a href="/doc/go1.17_spec.html">here</a>.
|
||||
For more information and other documents, see <a href="/">golang.org</a>.
|
||||
For more information and other documents, see <a href="/">go.dev</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -70,6 +70,14 @@ enumerations or code snippets that are not further specified. The character <cod
|
||||
language.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A link of the form [<a href="#Language_versions">Go 1.xx</a>] indicates that a described
|
||||
language feature (or some aspect of it) was changed or added with language version 1.xx and
|
||||
thus requires at minimum that language version to build.
|
||||
For details, see the <a href="#Language_versions">linked section</a>
|
||||
in the <a href="#Appendix">appendix</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="Source_code_representation">Source code representation</h2>
|
||||
|
||||
<p>
|
||||
@ -263,7 +271,8 @@ continue for import return var
|
||||
|
||||
<p>
|
||||
The following character sequences represent <a href="#Operators">operators</a>
|
||||
(including <a href="#Assignment_statements">assignment operators</a>) and punctuation:
|
||||
(including <a href="#Assignment_statements">assignment operators</a>) and punctuation
|
||||
[<a href="#Go_1.18">Go 1.18</a>]:
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
+ & += &= && == != ( )
|
||||
@ -281,7 +290,8 @@ An integer literal is a sequence of digits representing an
|
||||
<a href="#Constants">integer constant</a>.
|
||||
An optional prefix sets a non-decimal base: <code>0b</code> or <code>0B</code>
|
||||
for binary, <code>0</code>, <code>0o</code>, or <code>0O</code> for octal,
|
||||
and <code>0x</code> or <code>0X</code> for hexadecimal.
|
||||
and <code>0x</code> or <code>0X</code> for hexadecimal
|
||||
[<a href="#Go_1.13">Go 1.13</a>].
|
||||
A single <code>0</code> is considered a decimal zero.
|
||||
In hexadecimal literals, letters <code>a</code> through <code>f</code>
|
||||
and <code>A</code> through <code>F</code> represent values 10 through 15.
|
||||
@ -347,7 +357,8 @@ prefix, an integer part (hexadecimal digits), a radix point, a fractional part (
|
||||
and an exponent part (<code>p</code> or <code>P</code> followed by an optional sign and decimal digits).
|
||||
One of the integer part or the fractional part may be elided; the radix point may be elided as well,
|
||||
but the exponent part is required. (This syntax matches the one given in IEEE 754-2008 §5.12.3.)
|
||||
An exponent value exp scales the mantissa (integer and fractional part) by 2<sup>exp</sup>.
|
||||
An exponent value exp scales the mantissa (integer and fractional part) by 2<sup>exp</sup>
|
||||
[<a href="#Go_1.13">Go 1.13</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -411,7 +422,8 @@ It consists of an <a href="#Integer_literals">integer</a> or
|
||||
<a href="#Floating-point_literals">floating-point</a> literal
|
||||
followed by the lowercase letter <code>i</code>.
|
||||
The value of an imaginary literal is the value of the respective
|
||||
integer or floating-point literal multiplied by the imaginary unit <i>i</i>.
|
||||
integer or floating-point literal multiplied by the imaginary unit <i>i</i>
|
||||
[<a href="#Go_1.13">Go 1.13</a>]
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
@ -1340,6 +1352,7 @@ interface{}
|
||||
|
||||
<p>
|
||||
For convenience, the predeclared type <code>any</code> is an alias for the empty interface.
|
||||
[<a href="#Go_1.18">Go 1.18</a>]
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -1375,13 +1388,15 @@ as the <code>File</code> interface.
|
||||
In a slightly more general form
|
||||
an interface <code>T</code> may use a (possibly qualified) interface type
|
||||
name <code>E</code> as an interface element. This is called
|
||||
<i>embedding</i> interface <code>E</code> in <code>T</code>.
|
||||
<i>embedding</i> interface <code>E</code> in <code>T</code>
|
||||
[<a href="#Go_1.14">Go 1.14</a>].
|
||||
The type set of <code>T</code> is the <i>intersection</i> of the type sets
|
||||
defined by <code>T</code>'s explicitly declared methods and the type sets
|
||||
of <code>T</code>’s embedded interfaces.
|
||||
In other words, the type set of <code>T</code> is the set of all types that implement all the
|
||||
explicitly declared methods of <code>T</code> and also all the methods of
|
||||
<code>E</code>.
|
||||
<code>E</code>
|
||||
[<a href="#Go_1.18">Go 1.18</a>].
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@ -1420,7 +1435,8 @@ type ReadCloser interface {
|
||||
<p>
|
||||
In their most general form, an interface element may also be an arbitrary type term
|
||||
<code>T</code>, or a term of the form <code>~T</code> specifying the underlying type <code>T</code>,
|
||||
or a union of terms <code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>.
|
||||
or a union of terms <code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>
|
||||
[<a href="#Go_1.18">Go 1.18</a>].
|
||||
Together with method specifications, these elements enable the precise
|
||||
definition of an interface's type set as follows:
|
||||
</p>
|
||||
@ -2303,7 +2319,9 @@ as an <a href="#Operands">operand</a>, and in <a href="#Assignment_statements">a
|
||||
|
||||
<p>
|
||||
The following identifiers are implicitly declared in the
|
||||
<a href="#Blocks">universe block</a>:
|
||||
<a href="#Blocks">universe block</a>
|
||||
[<a href="#Go_1.18">Go 1.18</a>]
|
||||
[<a href="#Go_1.21">Go 1.21</a>]:
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
Types:
|
||||
@ -2487,7 +2505,8 @@ TypeSpec = AliasDecl | TypeDef .
|
||||
<h4 id="Alias_declarations">Alias declarations</h4>
|
||||
|
||||
<p>
|
||||
An alias declaration binds an identifier to the given type.
|
||||
An alias declaration binds an identifier to the given type
|
||||
[<a href="#Go_1.9">Go 1.9</a>].
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
@ -2636,7 +2655,8 @@ func (l *List[T]) Len() int { … }
|
||||
A type parameter list declares the <i>type parameters</i> of a generic function or type declaration.
|
||||
The type parameter list looks like an ordinary <a href="#Function_types">function parameter list</a>
|
||||
except that the type parameter names must all be present and the list is enclosed
|
||||
in square brackets rather than parentheses.
|
||||
in square brackets rather than parentheses
|
||||
[<a href="#Go_1.18">Go 1.18</a>].
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
@ -2719,7 +2739,8 @@ type T6[P int] struct{ f *T6[P] } // ok: reference to T6 is not in type para
|
||||
<p>
|
||||
A <i>type constraint</i> is an <a href="#Interface_types">interface</a> that defines the
|
||||
set of permissible type arguments for the respective type parameter and controls the
|
||||
operations supported by values of that type parameter.
|
||||
operations supported by values of that type parameter
|
||||
[<a href="#Go_1.18">Go 1.18</a>].
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
@ -2749,7 +2770,8 @@ other interfaces based on their type sets. But this should get us going for now.
|
||||
The <a href="#Predeclared_identifiers">predeclared</a>
|
||||
<a href="#Interface_types">interface type</a> <code>comparable</code>
|
||||
denotes the set of all non-interface types that are
|
||||
<a href="#Comparison_operators">strictly comparable</a>.
|
||||
<a href="#Comparison_operators">strictly comparable</a>
|
||||
[<a href="#Go_1.18">Go 1.18</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -2782,7 +2804,8 @@ if <code>T</code> is an element of the type set defined by <code>C</code>; i.e.,
|
||||
if <code>T</code> <a href="#Implementing_an_interface">implements</a> <code>C</code>.
|
||||
As an exception, a <a href="#Comparison_operators">strictly comparable</a>
|
||||
type constraint may also be satisfied by a <a href="#Comparison_operators">comparable</a>
|
||||
(not necessarily strictly comparable) type argument.
|
||||
(not necessarily strictly comparable) type argument
|
||||
[<a href="#Go_1.20">Go 1.20</a>].
|
||||
More precisely:
|
||||
</p>
|
||||
|
||||
@ -4306,7 +4329,7 @@ with the same underlying array.
|
||||
|
||||
<p>
|
||||
A generic function or type is <i>instantiated</i> by substituting <i>type arguments</i>
|
||||
for the type parameters.
|
||||
for the type parameters [<a href="#Go_1.18">Go 1.18</a>].
|
||||
Instantiation proceeds in two steps:
|
||||
</p>
|
||||
|
||||
@ -4759,6 +4782,7 @@ to the type of the other operand.
|
||||
|
||||
<p>
|
||||
The right operand in a shift expression must have <a href="#Numeric_types">integer type</a>
|
||||
[<a href="#Go_1.13">Go 1.13</a>]
|
||||
or be an untyped constant <a href="#Representability">representable</a> by a
|
||||
value of type <code>uint</code>.
|
||||
If the left operand of a non-constant shift expression is an untyped constant,
|
||||
@ -4826,12 +4850,13 @@ For instance, <code>x / y * z</code> is the same as <code>(x / y) * z</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
+x
|
||||
23 + 3*x[i]
|
||||
x <= f()
|
||||
^a >> b
|
||||
f() || g()
|
||||
x == y+1 && <-chanInt > 0
|
||||
+x // x
|
||||
42 + a - b // (42 + a) - b
|
||||
23 + 3*x[i] // 23 + (3 * x[i])
|
||||
x <= f() // x <= f()
|
||||
^a >> b // (^a) >> b
|
||||
f() || g() // f() || g()
|
||||
x == y+1 && <-chanInt > 0 // (x == (y+1)) && ((<-chanInt) > 0)
|
||||
</pre>
|
||||
|
||||
|
||||
@ -5425,7 +5450,8 @@ in any of these cases:
|
||||
<code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code> is a slice, <code>T</code> is an array or a pointer to an array,
|
||||
<code>x</code> is a slice, <code>T</code> is an array [<a href="#Go_1.20">Go 1.20</a>]
|
||||
or a pointer to an array [<a href="#Go_1.17">Go 1.17</a>],
|
||||
and the slice and array types have <a href="#Type_identity">identical</a> element types.
|
||||
</li>
|
||||
</ul>
|
||||
@ -6515,7 +6541,6 @@ additionally it may specify an <i>init</i>
|
||||
and a <i>post</i> statement, such as an assignment,
|
||||
an increment or decrement statement. The init statement may be a
|
||||
<a href="#Short_variable_declarations">short variable declaration</a>, but the post statement must not.
|
||||
Variables declared by the init statement are re-used in each iteration.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
@ -6547,12 +6572,55 @@ for cond { S() } is the same as for ; cond ; { S() }
|
||||
for { S() } is the same as for true { S() }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Each iteration has its own separate declared variable (or variables)
|
||||
[<a href="#Go_1.22">Go 1.22</a>].
|
||||
The variable used by the first iteration is declared by the init statement.
|
||||
The variable used by each subsequent iteration is declared implicitly before
|
||||
executing the post statement and initialized to the value of the previous
|
||||
iteration's variable at that moment.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var prints []func()
|
||||
for i := 0; i < 5; i++ {
|
||||
prints = append(prints, func() { println(i) })
|
||||
i++
|
||||
}
|
||||
for _, p := range prints {
|
||||
p()
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
prints
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
1
|
||||
3
|
||||
5
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Prior to [<a href="#Go_1.22">Go 1.22</a>], iterations share one set of variables
|
||||
instead of having their own separate variables.
|
||||
In that case, the example above prints
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
6
|
||||
6
|
||||
6
|
||||
</pre>
|
||||
|
||||
<h4 id="For_range">For statements with <code>range</code> clause</h4>
|
||||
|
||||
<p>
|
||||
A "for" statement with a "range" clause
|
||||
iterates through all entries of an array, slice, string or map,
|
||||
or values received on a channel. For each entry it assigns <i>iteration values</i>
|
||||
iterates through all entries of an array, slice, string or map, values received on
|
||||
a channel, or integer values from zero to an upper limit [<a href="#Go_1.22">Go 1.22</a>].
|
||||
For each entry it assigns <i>iteration values</i>
|
||||
to corresponding <i>iteration variables</i> if present and then executes the block.
|
||||
</p>
|
||||
|
||||
@ -6563,12 +6631,12 @@ RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
|
||||
<p>
|
||||
The expression on the right in the "range" clause is called the <i>range expression</i>,
|
||||
its <a href="#Core_types">core type</a> must be
|
||||
an array, pointer to an array, slice, string, map, or channel permitting
|
||||
<a href="#Receive_operator">receive operations</a>.
|
||||
an array, pointer to an array, slice, string, map, channel permitting
|
||||
<a href="#Receive_operator">receive operations</a>, or an integer.
|
||||
As with an assignment, if present the operands on the left must be
|
||||
<a href="#Address_operators">addressable</a> or map index expressions; they
|
||||
denote the iteration variables. If the range expression is a channel, at most
|
||||
one iteration variable is permitted, otherwise there may be up to two.
|
||||
denote the iteration variables. If the range expression is a channel or integer,
|
||||
at most one iteration variable is permitted, otherwise there may be up to two.
|
||||
If the last iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
|
||||
the range clause is equivalent to the same clause without that identifier.
|
||||
</p>
|
||||
@ -6593,6 +6661,7 @@ array or slice a [n]E, *[n]E, or []E index i int a[i] E
|
||||
string s string type index i int see below rune
|
||||
map m map[K]V key k K m[k] V
|
||||
channel c chan E, <-chan E element e E
|
||||
integer n integer type I value i I
|
||||
</pre>
|
||||
|
||||
<ol>
|
||||
@ -6631,6 +6700,12 @@ For channels, the iteration values produced are the successive values sent on
|
||||
the channel until the channel is <a href="#Close">closed</a>. If the channel
|
||||
is <code>nil</code>, the range expression blocks forever.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
For an integer value <code>n</code>, the iteration values 0 through <code>n-1</code>
|
||||
are produced in increasing order, with the same type as <code>n</code>.
|
||||
If <code>n</code> <= 0, the loop does not run any iterations.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
@ -6643,9 +6718,10 @@ The iteration variables may be declared by the "range" clause using a form of
|
||||
<a href="#Short_variable_declarations">short variable declaration</a>
|
||||
(<code>:=</code>).
|
||||
In this case their types are set to the types of the respective iteration values
|
||||
and their <a href="#Declarations_and_scope">scope</a> is the block of the "for"
|
||||
statement; they are re-used in each iteration.
|
||||
If the iteration variables are declared outside the "for" statement,
|
||||
and their <a href="#Declarations_and_scope">scope</a> is the block of the "for" statement;
|
||||
each iteration has its own separate variables [<a href="#Go_1.22">Go 1.22</a>]
|
||||
(see also <a href="#For_clause">"for" statements with a ForClause</a>).
|
||||
If the iteration variables are declared outside the “for” statement,
|
||||
after execution their values will be those of the last iteration.
|
||||
</p>
|
||||
|
||||
@ -6683,6 +6759,12 @@ for w := range ch {
|
||||
|
||||
// empty a channel
|
||||
for range ch {}
|
||||
|
||||
// call f(0), f(1), ... f(9)
|
||||
for i := range 10 {
|
||||
// type of i is int (default type for untyped constant 10)
|
||||
f(i)
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
@ -7234,7 +7316,8 @@ n3 := copy(b, "Hello, World!") // n3 == 5, b is []byte("Hello")
|
||||
<p>
|
||||
The built-in function <code>clear</code> takes an argument of <a href="#Map_types">map</a>,
|
||||
<a href="#Slice_types">slice</a>, or <a href="#Type_parameter_declarations">type parameter</a> type,
|
||||
and deletes or zeroes out all elements.
|
||||
and deletes or zeroes out all elements
|
||||
[<a href="#Go_1.21">Go 1.21</a>].
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
@ -7501,7 +7584,8 @@ The precise behavior is implementation-dependent.
|
||||
The built-in functions <code>min</code> and <code>max</code> compute the
|
||||
smallest—or largest, respectively—value of a fixed number of
|
||||
arguments of <a href="#Comparison_operators">ordered types</a>.
|
||||
There must be at least one argument.
|
||||
There must be at least one argument
|
||||
[<a href="#Go_1.21">Go 1.21</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -8217,8 +8301,8 @@ of if the general conversion rules take care of this.
|
||||
<p>
|
||||
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
|
||||
value may not be <a href="#Address_operators">dereferenced</a>.
|
||||
Any pointer or value of <a href="#Underlying_types">underlying type</a> <code>uintptr</code> can be
|
||||
<a href="#Conversions">converted</a> to a type of underlying type <code>Pointer</code> and vice versa.
|
||||
Any pointer or value of <a href="#Core_types">core type</a> <code>uintptr</code> can be
|
||||
<a href="#Conversions">converted</a> to a type of core type <code>Pointer</code> and vice versa.
|
||||
The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
|
||||
</p>
|
||||
|
||||
@ -8229,6 +8313,10 @@ bits = *(*uint64)(unsafe.Pointer(&f))
|
||||
type ptr unsafe.Pointer
|
||||
bits = *(*uint64)(ptr(&f))
|
||||
|
||||
func f[P ~*B, B any](p P) uintptr {
|
||||
return uintptr(unsafe.Pointer(p))
|
||||
}
|
||||
|
||||
var p ptr = nil
|
||||
</pre>
|
||||
|
||||
@ -8277,7 +8365,8 @@ of constant size.
|
||||
|
||||
<p>
|
||||
The function <code>Add</code> adds <code>len</code> to <code>ptr</code>
|
||||
and returns the updated pointer <code>unsafe.Pointer(uintptr(ptr) + uintptr(len))</code>.
|
||||
and returns the updated pointer <code>unsafe.Pointer(uintptr(ptr) + uintptr(len))</code>
|
||||
[<a href="#Go_1.17">Go 1.17</a>].
|
||||
The <code>len</code> argument must be of <a href="#Numeric_types">integer type</a> or an untyped <a href="#Constants">constant</a>.
|
||||
A constant <code>len</code> argument must be <a href="#Representability">representable</a> by a value of type <code>int</code>;
|
||||
if it is an untyped constant it is given type <code>int</code>.
|
||||
@ -8297,7 +8386,8 @@ and whose length and capacity are <code>len</code>.
|
||||
<p>
|
||||
except that, as a special case, if <code>ptr</code>
|
||||
is <code>nil</code> and <code>len</code> is zero,
|
||||
<code>Slice</code> returns <code>nil</code>.
|
||||
<code>Slice</code> returns <code>nil</code>
|
||||
[<a href="#Go_1.17">Go 1.17</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -8306,14 +8396,16 @@ A constant <code>len</code> argument must be non-negative and <a href="#Represen
|
||||
if it is an untyped constant it is given type <code>int</code>.
|
||||
At run time, if <code>len</code> is negative,
|
||||
or if <code>ptr</code> is <code>nil</code> and <code>len</code> is not zero,
|
||||
a <a href="#Run_time_panics">run-time panic</a> occurs.
|
||||
a <a href="#Run_time_panics">run-time panic</a> occurs
|
||||
[<a href="#Go_1.17">Go 1.17</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The function <code>SliceData</code> returns a pointer to the underlying array of the <code>slice</code> argument.
|
||||
If the slice's capacity <code>cap(slice)</code> is not zero, that pointer is <code>&slice[:1][0]</code>.
|
||||
If <code>slice</code> is <code>nil</code>, the result is <code>nil</code>.
|
||||
Otherwise it is a non-<code>nil</code> pointer to an unspecified memory address.
|
||||
Otherwise it is a non-<code>nil</code> pointer to an unspecified memory address
|
||||
[<a href="#Go_1.20">Go 1.20</a>].
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -8322,12 +8414,14 @@ The function <code>String</code> returns a <code>string</code> value whose under
|
||||
The same requirements apply to the <code>ptr</code> and <code>len</code> argument as in the function
|
||||
<code>Slice</code>. If <code>len</code> is zero, the result is the empty string <code>""</code>.
|
||||
Since Go strings are immutable, the bytes passed to <code>String</code> must not be modified afterwards.
|
||||
[<a href="#Go_1.20">Go 1.20</a>]
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The function <code>StringData</code> returns a pointer to the underlying bytes of the <code>str</code> argument.
|
||||
For an empty string the return value is unspecified, and may be <code>nil</code>.
|
||||
Since Go strings are immutable, the bytes returned by <code>StringData</code> must not be modified.
|
||||
Since Go strings are immutable, the bytes returned by <code>StringData</code> must not be modified
|
||||
[<a href="#Go_1.20">Go 1.20</a>].
|
||||
</p>
|
||||
|
||||
<h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
|
||||
@ -8368,6 +8462,145 @@ A struct or array type has size zero if it contains no fields (or elements, resp
|
||||
|
||||
<h2 id="Appendix">Appendix</h2>
|
||||
|
||||
<h3 id="Language_versions">Language versions</h3>
|
||||
|
||||
<p>
|
||||
The <a href="/doc/go1compat">Go 1 compatibility guarantee</a> ensures that
|
||||
programs written to the Go 1 specification will continue to compile and run
|
||||
correctly, unchanged, over the lifetime of that specification.
|
||||
More generally, as adjustments are made and features added to the language,
|
||||
the compatibility guarantee ensures that a Go program that works with a
|
||||
specific Go language version will continue to work with any subsequent version.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For instance, the ability to use the prefix <code>0b</code> for binary
|
||||
integer literals was introduced with Go 1.13, indicated
|
||||
by [<a href="#Go_1.13">Go 1.13</a>] in the section on
|
||||
<a href="#Integer_literals">integer literals</a>.
|
||||
Source code containing an integer literal such as <code>0b1011</code>
|
||||
will be rejected if the implied or required language version used by
|
||||
the compiler is older than Go 1.13.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following table describes the minimum language version required for
|
||||
features introduced after Go 1.
|
||||
</p>
|
||||
|
||||
<h4 id="Go_1.9">Go 1.9</h4>
|
||||
<ul>
|
||||
<li>
|
||||
An <a href="#Alias_declarations">alias declaration</a> may be used to declare an alias name for a type.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.13">Go 1.13</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#Integer_literals">Integer literals</a> may use the prefixes <code>0b</code>, <code>0B</code>, <code>0o</code>,
|
||||
and <code>0O</code> for binary, and octal literals, respectively.
|
||||
</li>
|
||||
<li>
|
||||
Hexadecimal <a href="#Floating-point_literals">floating-point literals</a> may be written using the prefixes
|
||||
<code>0x</code> and <code>0X</code>.
|
||||
</li>
|
||||
<li>
|
||||
The <a href="#Imaginary_literals">imaginary suffix</a> <code>i</code> may be used with any (binary, decimal, hexadecimal)
|
||||
integer or floating-point literal, not just decimal literals.
|
||||
</li>
|
||||
<li>
|
||||
The digits of any number literal may be <a href="#Integer_literals">separated</a> (grouped)
|
||||
using underscores <code>_</code>.
|
||||
</li>
|
||||
<li>
|
||||
The shift count in a <a href="#Operators">shift operation</a> may be a signed integer type.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.14">Go 1.14</h4>
|
||||
<ul>
|
||||
<li>
|
||||
Emdedding a method more than once through different <a href="#Embedded_interfaces">embedded interfaces</a>
|
||||
is not an error.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.17">Go 1.17</h4>
|
||||
<ul>
|
||||
<li>
|
||||
A slice may be <a href="#Conversions">converted</a> to an array pointer if the slice and array element
|
||||
types match, and the array is not longer than the slice.
|
||||
</li>
|
||||
<li>
|
||||
The built-in <a href="#Package_unsafe">package <code>unsafe</code></a> includes the new functions
|
||||
<code>Add</code> and <code>Slice</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.18">Go 1.18</h4>
|
||||
<p>
|
||||
The 1.18 release adds polymorphic functions and types ("generics") to the language.
|
||||
Specifically:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
The set of <a href="#Operators_and_punctuation">operators and punctuation</a> includes the new token <code>~</code>.
|
||||
</li>
|
||||
<li>
|
||||
Function and type declarations may declare <a href="#Type_parameter_declarations">type parameters</a>.
|
||||
</li>
|
||||
<li>
|
||||
Interface types may <a href="#General_interfaces">embed arbitrary types</a> (not just type names of interfaces)
|
||||
as well as union and <code>~T</code> type elements.
|
||||
</li>
|
||||
<li>
|
||||
The set of <a href="#Predeclared_identifiers">predeclared</a> types includes the new types
|
||||
<code>any</code> and <code>comparable</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.20">Go 1.20</h4>
|
||||
<ul>
|
||||
<li>
|
||||
A slice may be <a href="#Conversions">converted</a> to an array if the slice and array element
|
||||
types match and the array is not longer than the slice.
|
||||
</li>
|
||||
<li>
|
||||
The built-in <a href="#Package_unsafe">package <code>unsafe</code></a> includes the new functions
|
||||
<code>SliceData</code>, <code>String</code>, and <code>StringData</code>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="#Comparison_operators">Comparable types</a> (such as ordinary interfaces) may satisfy
|
||||
<code>comparable</code> constraints, even if the type arguments are not strictly comparable.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.21">Go 1.21</h4>
|
||||
<ul>
|
||||
<li>
|
||||
The set of <a href="#Predeclared_identifiers">predeclared</a> functions includes the new functions
|
||||
<code>min</code>, <code>max</code>, and <code>clear</code>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="#Type_inference">Type inference</a> uses the types of interface methods for inference.
|
||||
It also infers type arguments for generic functions assigned to variables or
|
||||
passed as arguments to other (possibly generic) functions.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Go_1.22">Go 1.22</h4>
|
||||
<ul>
|
||||
<li>
|
||||
In a <a href="#For_statements">"for" statement</a>, each iteration has its own set of iteration
|
||||
variables rather than sharing the same variables in each iteration.
|
||||
</li>
|
||||
<li>
|
||||
A "for" statement with <a href="#For_range">"range" clause</a> may iterate over
|
||||
integer values from zero to an upper limit.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="Type_unification_rules">Type unification rules</h3>
|
||||
|
||||
<p>
|
||||
|
@ -129,7 +129,7 @@ and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
|
||||
### Go 1.22
|
||||
|
||||
Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size
|
||||
that can be used in TLS handshakes, controlled by the [`tlsmaxrsasize`setting](/pkg/crypto/tls#Conn.Handshake).
|
||||
that can be used in TLS handshakes, controlled by the [`tlsmaxrsasize` setting](/pkg/crypto/tls#Conn.Handshake).
|
||||
The default is tlsmaxrsasize=8192, limiting RSA to 8192-bit keys. To avoid
|
||||
denial of service attacks, this setting and default was backported to Go
|
||||
1.19.13, Go 1.20.8, and Go 1.21.1.
|
||||
@ -138,6 +138,62 @@ Go 1.22 made it an error for a request or response read by a net/http
|
||||
client or server to have an empty Content-Length header.
|
||||
This behavior is controlled by the `httplaxcontentlength` setting.
|
||||
|
||||
Go 1.22 changed the behavior of ServeMux to accept extended
|
||||
patterns and unescape both patterns and request paths by segment.
|
||||
This behavior can be controlled by the
|
||||
[`httpmuxgo121` setting](/pkg/net/http/#ServeMux).
|
||||
|
||||
Go 1.22 added the [Alias type](/pkg/go/types#Alias) to [go/types](/pkg/go/types)
|
||||
for the explicit representation of [type aliases](/ref/spec#Type_declarations).
|
||||
Whether the type checker produces `Alias` types or not is controlled by the
|
||||
[`gotypesalias` setting](/pkg/go/types#Alias).
|
||||
For Go 1.22 it defaults to `gotypesalias=0`.
|
||||
For Go 1.23, `gotypealias=1` will become the default.
|
||||
This setting will be removed in a future release, Go 1.24 at the earliest.
|
||||
|
||||
Go 1.22 changed the default minimum TLS version supported by both servers
|
||||
and clients to TLS 1.2. The default can be reverted to TLS 1.0 using the
|
||||
[`tls10server` setting](/pkg/crypto/tls/#Config).
|
||||
|
||||
Go 1.22 changed the default TLS cipher suites used by clients and servers when
|
||||
not explicitly configured, removing the cipher suites which used RSA based key
|
||||
exchange. The default can be revert using the [`tlsrsakex` setting](/pkg/crypto/tls/#Config).
|
||||
|
||||
Go 1.22 disabled
|
||||
[`ConnectionState.ExportKeyingMaterial`](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial)
|
||||
when the connection supports neither TLS 1.3 nor Extended Master Secret
|
||||
(implemented in Go 1.21). It can be reenabled with the [`tlsunsafeekm`
|
||||
setting](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial).
|
||||
|
||||
Go 1.22 changed how the runtime interacts with transparent huge pages on Linux.
|
||||
In particular, a common default Linux kernel configuration can result in
|
||||
significant memory overheads, and Go 1.22 no longer works around this default.
|
||||
To work around this issue without adjusting kernel settings, transparent huge
|
||||
pages can be disabled for Go memory with the
|
||||
[`disablethp` setting](/pkg/runtime#hdr-Environment_Variable).
|
||||
This behavior was backported to Go 1.21.1, but the setting is only available
|
||||
starting with Go 1.21.6.
|
||||
This setting may be removed in a future release, and users impacted by this issue
|
||||
should adjust their Linux configuration according to the recommendations in the
|
||||
[GC guide](/doc/gc-guide#Linux_transparent_huge_pages), or switch to a Linux
|
||||
distribution that disables transparent huge pages altogether.
|
||||
|
||||
Go 1.22 added contention on runtime-internal locks to the [`mutex`
|
||||
profile](/pkg/runtime/pprof#Profile). Contention on these locks is always
|
||||
reported at `runtime._LostContendedRuntimeLock`. Complete stack traces of
|
||||
runtime locks can be enabled with the [`runtimecontentionstacks`
|
||||
setting](/pkg/runtime#hdr-Environment_Variable). These stack traces have
|
||||
non-standard semantics, see setting documentation for details.
|
||||
|
||||
Go 1.22 added a new [`crypto/x509.Certificate`](/pkg/crypto/x509/#Certificate)
|
||||
field, [`Policies`](/pkg/crypto/x509/#Certificate.Policies), which supports
|
||||
certificate policy OIDs with components larger than 31 bits. By default this
|
||||
field is only used during parsing, when it is populated with policy OIDs, but
|
||||
not used during marshaling. It can be used to marshal these larger OIDs, instead
|
||||
of the existing PolicyIdentifiers field, by using the
|
||||
[`x509usepolicies` setting.](/pkg/crypto/x509/#CreateCertificate).
|
||||
|
||||
|
||||
### Go 1.21
|
||||
|
||||
Go 1.21 made it a run-time error to call `panic` with a nil interface value,
|
||||
|
@ -24,8 +24,8 @@
|
||||
# in the CL match the update.bash in the CL.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2023c
|
||||
DATA=2023c
|
||||
CODE=2023d
|
||||
DATA=2023d
|
||||
|
||||
set -e
|
||||
|
||||
|
Binary file not shown.
@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
// detect attempts to autodetect the correct
|
||||
// values of the environment variables
|
||||
|
@ -14,7 +14,15 @@ case "$GOWASIRUNTIME" in
|
||||
exec wazero run -mount /:/ -env-inherit -cachedir "${TMPDIR:-/tmp}"/wazero ${GOWASIRUNTIMEARGS:-} "$1" "${@:2}"
|
||||
;;
|
||||
"wasmtime" | "")
|
||||
exec wasmtime run --dir=/ --env PWD="$PWD" --env PATH="$PATH" --max-wasm-stack 1048576 ${GOWASIRUNTIMEARGS:-} "$1" -- "${@:2}"
|
||||
# Match the major version in "wasmtime-cli 14.0.0". For versions before 14
|
||||
# we need to use the old CLI. This requires Bash v3.0 and above.
|
||||
# TODO(johanbrandhorst): Remove this condition once 1.22 is released.
|
||||
# From 1.23 onwards we'll only support the new wasmtime CLI.
|
||||
if [[ "$(wasmtime --version)" =~ wasmtime-cli[[:space:]]([0-9]+)\.[0-9]+\.[0-9]+ && "${BASH_REMATCH[1]}" -lt 14 ]]; then
|
||||
exec wasmtime run --dir=/ --env PWD="$PWD" --env PATH="$PATH" --max-wasm-stack 1048576 ${GOWASIRUNTIMEARGS:-} "$1" -- "${@:2}"
|
||||
else
|
||||
exec wasmtime run --dir=/ --env PWD="$PWD" --env PATH="$PATH" -W max-wasm-stack=1048576 ${GOWASIRUNTIMEARGS:-} "$1" "${@:2}"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unknown Go WASI runtime specified: $GOWASIRUNTIME"
|
||||
|
@ -634,7 +634,7 @@ const (
|
||||
c_ISSOCK = 0140000 // Socket
|
||||
)
|
||||
|
||||
// FileInfoHeader creates a partially-populated Header from fi.
|
||||
// FileInfoHeader creates a partially-populated [Header] from fi.
|
||||
// If fi describes a symlink, FileInfoHeader records link as the link target.
|
||||
// If fi describes a directory, a slash is appended to the name.
|
||||
//
|
||||
|
@ -33,7 +33,7 @@ import "strings"
|
||||
// sub-second times | no | yes | no
|
||||
// sparse files | no | yes | yes
|
||||
//
|
||||
// The table's upper portion shows the Header fields, where each format reports
|
||||
// The table's upper portion shows the [Header] fields, where each format reports
|
||||
// the maximum number of bytes allowed for each string field and
|
||||
// the integer type used to store each numeric field
|
||||
// (where timestamps are stored as the number of seconds since the Unix epoch).
|
||||
|
@ -35,7 +35,7 @@ type fileReader interface {
|
||||
WriteTo(io.Writer) (int64, error)
|
||||
}
|
||||
|
||||
// NewReader creates a new Reader reading from r.
|
||||
// NewReader creates a new [Reader] reading from r.
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
return &Reader{r: r, curr: ®FileReader{r, 0}}
|
||||
}
|
||||
@ -47,10 +47,10 @@ func NewReader(r io.Reader) *Reader {
|
||||
//
|
||||
// If Next encounters a non-local name (as defined by [filepath.IsLocal])
|
||||
// and the GODEBUG environment variable contains `tarinsecurepath=0`,
|
||||
// Next returns the header with an ErrInsecurePath error.
|
||||
// Next returns the header with an [ErrInsecurePath] error.
|
||||
// A future version of Go may introduce this behavior by default.
|
||||
// Programs that want to accept non-local names can ignore
|
||||
// the ErrInsecurePath error and use the returned header.
|
||||
// the [ErrInsecurePath] error and use the returned header.
|
||||
func (tr *Reader) Next() (*Header, error) {
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
@ -623,14 +623,14 @@ func readGNUSparseMap0x1(paxHdrs map[string]string) (sparseDatas, error) {
|
||||
|
||||
// Read reads from the current file in the tar archive.
|
||||
// It returns (0, io.EOF) when it reaches the end of that file,
|
||||
// until Next is called to advance to the next file.
|
||||
// until [Next] is called to advance to the next file.
|
||||
//
|
||||
// If the current file is sparse, then the regions marked as a hole
|
||||
// are read back as NUL-bytes.
|
||||
//
|
||||
// Calling Read on special types like TypeLink, TypeSymlink, TypeChar,
|
||||
// TypeBlock, TypeDir, and TypeFifo returns (0, io.EOF) regardless of what
|
||||
// the Header.Size claims.
|
||||
// Calling Read on special types like [TypeLink], [TypeSymlink], [TypeChar],
|
||||
// [TypeBlock], [TypeDir], and [TypeFifo] returns (0, [io.EOF]) regardless of what
|
||||
// the [Header.Size] claims.
|
||||
func (tr *Reader) Read(b []byte) (int, error) {
|
||||
if tr.err != nil {
|
||||
return 0, tr.err
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// Writer provides sequential writing of a tar archive.
|
||||
// Write.WriteHeader begins a new file with the provided Header,
|
||||
// [Writer.WriteHeader] begins a new file with the provided [Header],
|
||||
// and then Writer can be treated as an io.Writer to supply that file's data.
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
@ -46,7 +46,7 @@ type fileWriter interface {
|
||||
// Flush finishes writing the current file's block padding.
|
||||
// The current file must be fully written before Flush can be called.
|
||||
//
|
||||
// This is unnecessary as the next call to WriteHeader or Close
|
||||
// This is unnecessary as the next call to [Writer.WriteHeader] or [Writer.Close]
|
||||
// will implicitly flush out the file's padding.
|
||||
func (tw *Writer) Flush() error {
|
||||
if tw.err != nil {
|
||||
@ -464,12 +464,12 @@ func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
|
||||
}
|
||||
|
||||
// Write writes to the current file in the tar archive.
|
||||
// Write returns the error ErrWriteTooLong if more than
|
||||
// Header.Size bytes are written after WriteHeader.
|
||||
// Write returns the error [ErrWriteTooLong] if more than
|
||||
// Header.Size bytes are written after [Writer.WriteHeader].
|
||||
//
|
||||
// Calling Write on special types like TypeLink, TypeSymlink, TypeChar,
|
||||
// TypeBlock, TypeDir, and TypeFifo returns (0, ErrWriteTooLong) regardless
|
||||
// of what the Header.Size claims.
|
||||
// Calling Write on special types like [TypeLink], [TypeSymlink], [TypeChar],
|
||||
// [TypeBlock], [TypeDir], and [TypeFifo] returns (0, [ErrWriteTooLong]) regardless
|
||||
// of what the [Header.Size] claims.
|
||||
func (tw *Writer) Write(b []byte) (int, error) {
|
||||
if tw.err != nil {
|
||||
return 0, tw.err
|
||||
@ -503,7 +503,7 @@ func (tw *Writer) readFrom(r io.Reader) (int64, error) {
|
||||
}
|
||||
|
||||
// Close closes the tar archive by flushing the padding, and writing the footer.
|
||||
// If the current file (from a prior call to WriteHeader) is not fully written,
|
||||
// If the current file (from a prior call to [Writer.WriteHeader]) is not fully written,
|
||||
// then this returns an error.
|
||||
func (tw *Writer) Close() error {
|
||||
if tw.err == ErrWriteAfterClose {
|
||||
|
@ -48,15 +48,15 @@ type Reader struct {
|
||||
fileList []fileListEntry
|
||||
}
|
||||
|
||||
// A ReadCloser is a Reader that must be closed when no longer needed.
|
||||
// A ReadCloser is a [Reader] that must be closed when no longer needed.
|
||||
type ReadCloser struct {
|
||||
f *os.File
|
||||
Reader
|
||||
}
|
||||
|
||||
// A File is a single file in a ZIP archive.
|
||||
// The file information is in the embedded FileHeader.
|
||||
// The file content can be accessed by calling Open.
|
||||
// The file information is in the embedded [FileHeader].
|
||||
// The file content can be accessed by calling [File.Open].
|
||||
type File struct {
|
||||
FileHeader
|
||||
zip *Reader
|
||||
@ -93,16 +93,16 @@ func OpenReader(name string) (*ReadCloser, error) {
|
||||
return r, err
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader reading from r, which is assumed to
|
||||
// NewReader returns a new [Reader] reading from r, which is assumed to
|
||||
// have the given size in bytes.
|
||||
//
|
||||
// If any file inside the archive uses a non-local name
|
||||
// (as defined by [filepath.IsLocal]) or a name containing backslashes
|
||||
// and the GODEBUG environment variable contains `zipinsecurepath=0`,
|
||||
// NewReader returns the reader with an ErrInsecurePath error.
|
||||
// NewReader returns the reader with an [ErrInsecurePath] error.
|
||||
// A future version of Go may introduce this behavior by default.
|
||||
// Programs that want to accept non-local names can ignore
|
||||
// the ErrInsecurePath error and use the returned reader.
|
||||
// the [ErrInsecurePath] error and use the returned reader.
|
||||
func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
|
||||
if size < 0 {
|
||||
return nil, errors.New("zip: size cannot be negative")
|
||||
@ -178,7 +178,7 @@ func (r *Reader) init(rdr io.ReaderAt, size int64) error {
|
||||
|
||||
// RegisterDecompressor registers or overrides a custom decompressor for a
|
||||
// specific method ID. If a decompressor for a given method is not found,
|
||||
// Reader will default to looking up the decompressor at the package level.
|
||||
// [Reader] will default to looking up the decompressor at the package level.
|
||||
func (r *Reader) RegisterDecompressor(method uint16, dcomp Decompressor) {
|
||||
if r.decompressors == nil {
|
||||
r.decompressors = make(map[uint16]Decompressor)
|
||||
@ -202,7 +202,7 @@ func (rc *ReadCloser) Close() error {
|
||||
// DataOffset returns the offset of the file's possibly-compressed
|
||||
// data, relative to the beginning of the zip file.
|
||||
//
|
||||
// Most callers should instead use Open, which transparently
|
||||
// Most callers should instead use [File.Open], which transparently
|
||||
// decompresses data and verifies checksums.
|
||||
func (f *File) DataOffset() (offset int64, err error) {
|
||||
bodyOffset, err := f.findBodyOffset()
|
||||
@ -212,7 +212,7 @@ func (f *File) DataOffset() (offset int64, err error) {
|
||||
return f.headerOffset + bodyOffset, nil
|
||||
}
|
||||
|
||||
// Open returns a ReadCloser that provides access to the File's contents.
|
||||
// Open returns a [ReadCloser] that provides access to the [File]'s contents.
|
||||
// Multiple files may be read concurrently.
|
||||
func (f *File) Open() (io.ReadCloser, error) {
|
||||
bodyOffset, err := f.findBodyOffset()
|
||||
@ -255,7 +255,7 @@ func (f *File) Open() (io.ReadCloser, error) {
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
// OpenRaw returns a Reader that provides access to the File's contents without
|
||||
// OpenRaw returns a [Reader] that provides access to the [File]'s contents without
|
||||
// decompression.
|
||||
func (f *File) OpenRaw() (io.Reader, error) {
|
||||
bodyOffset, err := f.findBodyOffset()
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
type Compressor func(w io.Writer) (io.WriteCloser, error)
|
||||
|
||||
// A Decompressor returns a new decompressing reader, reading from r.
|
||||
// The ReadCloser's Close method must be used to release associated resources.
|
||||
// The [io.ReadCloser]'s Close method must be used to release associated resources.
|
||||
// The Decompressor itself must be safe to invoke from multiple goroutines
|
||||
// simultaneously, but each returned reader will be used only by
|
||||
// one goroutine at a time.
|
||||
@ -115,7 +115,7 @@ func init() {
|
||||
}
|
||||
|
||||
// RegisterDecompressor allows custom decompressors for a specified method ID.
|
||||
// The common methods Store and Deflate are built in.
|
||||
// The common methods [Store] and [Deflate] are built in.
|
||||
func RegisterDecompressor(method uint16, dcomp Decompressor) {
|
||||
if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
|
||||
panic("decompressor already registered")
|
||||
@ -123,7 +123,7 @@ func RegisterDecompressor(method uint16, dcomp Decompressor) {
|
||||
}
|
||||
|
||||
// RegisterCompressor registers custom compressors for a specified method ID.
|
||||
// The common methods Store and Deflate are built in.
|
||||
// The common methods [Store] and [Deflate] are built in.
|
||||
func RegisterCompressor(method uint16, comp Compressor) {
|
||||
if _, dup := compressors.LoadOrStore(method, comp); dup {
|
||||
panic("compressor already registered")
|
||||
|
@ -160,12 +160,12 @@ type FileHeader struct {
|
||||
ExternalAttrs uint32 // Meaning depends on CreatorVersion
|
||||
}
|
||||
|
||||
// FileInfo returns an fs.FileInfo for the FileHeader.
|
||||
// FileInfo returns an fs.FileInfo for the [FileHeader].
|
||||
func (h *FileHeader) FileInfo() fs.FileInfo {
|
||||
return headerFileInfo{h}
|
||||
}
|
||||
|
||||
// headerFileInfo implements fs.FileInfo.
|
||||
// headerFileInfo implements [fs.FileInfo].
|
||||
type headerFileInfo struct {
|
||||
fh *FileHeader
|
||||
}
|
||||
@ -194,7 +194,7 @@ func (fi headerFileInfo) String() string {
|
||||
return fs.FormatFileInfo(fi)
|
||||
}
|
||||
|
||||
// FileInfoHeader creates a partially-populated FileHeader from an
|
||||
// FileInfoHeader creates a partially-populated [FileHeader] from an
|
||||
// fs.FileInfo.
|
||||
// Because fs.FileInfo's Name method returns only the base name of
|
||||
// the file it describes, it may be necessary to modify the Name field
|
||||
@ -273,17 +273,17 @@ func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) {
|
||||
}
|
||||
|
||||
// ModTime returns the modification time in UTC using the legacy
|
||||
// ModifiedDate and ModifiedTime fields.
|
||||
// [ModifiedDate] and [ModifiedTime] fields.
|
||||
//
|
||||
// Deprecated: Use Modified instead.
|
||||
// Deprecated: Use [Modified] instead.
|
||||
func (h *FileHeader) ModTime() time.Time {
|
||||
return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
|
||||
}
|
||||
|
||||
// SetModTime sets the Modified, ModifiedTime, and ModifiedDate fields
|
||||
// SetModTime sets the [Modified], [ModifiedTime], and [ModifiedDate] fields
|
||||
// to the given time in UTC.
|
||||
//
|
||||
// Deprecated: Use Modified instead.
|
||||
// Deprecated: Use [Modified] instead.
|
||||
func (h *FileHeader) SetModTime(t time.Time) {
|
||||
t = t.UTC() // Convert to UTC for compatibility
|
||||
h.Modified = t
|
||||
@ -309,7 +309,7 @@ const (
|
||||
msdosReadOnly = 0x01
|
||||
)
|
||||
|
||||
// Mode returns the permission and mode bits for the FileHeader.
|
||||
// Mode returns the permission and mode bits for the [FileHeader].
|
||||
func (h *FileHeader) Mode() (mode fs.FileMode) {
|
||||
switch h.CreatorVersion >> 8 {
|
||||
case creatorUnix, creatorMacOSX:
|
||||
@ -323,7 +323,7 @@ func (h *FileHeader) Mode() (mode fs.FileMode) {
|
||||
return mode
|
||||
}
|
||||
|
||||
// SetMode changes the permission and mode bits for the FileHeader.
|
||||
// SetMode changes the permission and mode bits for the [FileHeader].
|
||||
func (h *FileHeader) SetMode(mode fs.FileMode) {
|
||||
h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
|
||||
h.ExternalAttrs = fileModeToUnixMode(mode) << 16
|
||||
|
@ -41,7 +41,7 @@ type header struct {
|
||||
raw bool
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer writing a zip file to w.
|
||||
// NewWriter returns a new [Writer] writing a zip file to w.
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}}
|
||||
}
|
||||
@ -64,7 +64,7 @@ func (w *Writer) Flush() error {
|
||||
}
|
||||
|
||||
// SetComment sets the end-of-central-directory comment field.
|
||||
// It can only be called before Close.
|
||||
// It can only be called before [Writer.Close].
|
||||
func (w *Writer) SetComment(comment string) error {
|
||||
if len(comment) > uint16max {
|
||||
return errors.New("zip: Writer.Comment too long")
|
||||
@ -208,14 +208,14 @@ func (w *Writer) Close() error {
|
||||
}
|
||||
|
||||
// Create adds a file to the zip file using the provided name.
|
||||
// It returns a Writer to which the file contents should be written.
|
||||
// The file contents will be compressed using the Deflate method.
|
||||
// It returns a [Writer] to which the file contents should be written.
|
||||
// The file contents will be compressed using the [Deflate] method.
|
||||
// The name must be a relative path: it must not start with a drive
|
||||
// letter (e.g. C:) or leading slash, and only forward slashes are
|
||||
// allowed. To create a directory instead of a file, add a trailing
|
||||
// slash to the name.
|
||||
// The file's contents must be written to the io.Writer before the next
|
||||
// call to Create, CreateHeader, or Close.
|
||||
// The file's contents must be written to the [io.Writer] before the next
|
||||
// call to [Writer.Create], [Writer.CreateHeader], or [Writer.Close].
|
||||
func (w *Writer) Create(name string) (io.Writer, error) {
|
||||
header := &FileHeader{
|
||||
Name: name,
|
||||
@ -262,13 +262,13 @@ func (w *Writer) prepare(fh *FileHeader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateHeader adds a file to the zip archive using the provided FileHeader
|
||||
// for the file metadata. Writer takes ownership of fh and may mutate
|
||||
// its fields. The caller must not modify fh after calling CreateHeader.
|
||||
// CreateHeader adds a file to the zip archive using the provided [FileHeader]
|
||||
// for the file metadata. [Writer] takes ownership of fh and may mutate
|
||||
// its fields. The caller must not modify fh after calling [Writer.CreateHeader].
|
||||
//
|
||||
// This returns a Writer to which the file contents should be written.
|
||||
// This returns a [Writer] to which the file contents should be written.
|
||||
// The file's contents must be written to the io.Writer before the next
|
||||
// call to Create, CreateHeader, CreateRaw, or Close.
|
||||
// call to [Writer.Create], [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close].
|
||||
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
||||
if err := w.prepare(fh); err != nil {
|
||||
return nil, err
|
||||
@ -427,12 +427,12 @@ func writeHeader(w io.Writer, h *header) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateRaw adds a file to the zip archive using the provided FileHeader and
|
||||
// returns a Writer to which the file contents should be written. The file's
|
||||
// contents must be written to the io.Writer before the next call to Create,
|
||||
// CreateHeader, CreateRaw, or Close.
|
||||
// CreateRaw adds a file to the zip archive using the provided [FileHeader] and
|
||||
// returns a [Writer] to which the file contents should be written. The file's
|
||||
// contents must be written to the io.Writer before the next call to [Writer.Create],
|
||||
// [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close].
|
||||
//
|
||||
// In contrast to CreateHeader, the bytes passed to Writer are not compressed.
|
||||
// In contrast to [Writer.CreateHeader], the bytes passed to Writer are not compressed.
|
||||
func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
|
||||
if err := w.prepare(fh); err != nil {
|
||||
return nil, err
|
||||
@ -464,7 +464,7 @@ func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
|
||||
return fw, nil
|
||||
}
|
||||
|
||||
// Copy copies the file f (obtained from a Reader) into w. It copies the raw
|
||||
// Copy copies the file f (obtained from a [Reader]) into w. It copies the raw
|
||||
// form directly bypassing decompression, compression, and validation.
|
||||
func (w *Writer) Copy(f *File) error {
|
||||
r, err := f.OpenRaw()
|
||||
@ -480,7 +480,7 @@ func (w *Writer) Copy(f *File) error {
|
||||
}
|
||||
|
||||
// RegisterCompressor registers or overrides a custom compressor for a specific
|
||||
// method ID. If a compressor for a given method is not found, Writer will
|
||||
// method ID. If a compressor for a given method is not found, [Writer] will
|
||||
// default to looking up the compressor at the package level.
|
||||
func (w *Writer) RegisterCompressor(method uint16, comp Compressor) {
|
||||
if w.compressors == nil {
|
||||
|
@ -41,24 +41,21 @@ type Reader struct {
|
||||
const minReadBufferSize = 16
|
||||
const maxConsecutiveEmptyReads = 100
|
||||
|
||||
// NewReaderSize returns a new Reader whose buffer has at least the specified
|
||||
// size. If the argument io.Reader is already a Reader with large enough
|
||||
// size, it returns the underlying Reader.
|
||||
// NewReaderSize returns a new [Reader] whose buffer has at least the specified
|
||||
// size. If the argument io.Reader is already a [Reader] with large enough
|
||||
// size, it returns the underlying [Reader].
|
||||
func NewReaderSize(rd io.Reader, size int) *Reader {
|
||||
// Is it already a Reader?
|
||||
b, ok := rd.(*Reader)
|
||||
if ok && len(b.buf) >= size {
|
||||
return b
|
||||
}
|
||||
if size < minReadBufferSize {
|
||||
size = minReadBufferSize
|
||||
}
|
||||
r := new(Reader)
|
||||
r.reset(make([]byte, size), rd)
|
||||
r.reset(make([]byte, max(size, minReadBufferSize)), rd)
|
||||
return r
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader whose buffer has the default size.
|
||||
// NewReader returns a new [Reader] whose buffer has the default size.
|
||||
func NewReader(rd io.Reader) *Reader {
|
||||
return NewReaderSize(rd, defaultBufSize)
|
||||
}
|
||||
@ -68,9 +65,9 @@ func (b *Reader) Size() int { return len(b.buf) }
|
||||
|
||||
// Reset discards any buffered data, resets all state, and switches
|
||||
// the buffered reader to read from r.
|
||||
// Calling Reset on the zero value of Reader initializes the internal buffer
|
||||
// Calling Reset on the zero value of [Reader] initializes the internal buffer
|
||||
// to the default size.
|
||||
// Calling b.Reset(b) (that is, resetting a Reader to itself) does nothing.
|
||||
// Calling b.Reset(b) (that is, resetting a [Reader] to itself) does nothing.
|
||||
func (b *Reader) Reset(r io.Reader) {
|
||||
// If a Reader r is passed to NewReader, NewReader will return r.
|
||||
// Different layers of code may do that, and then later pass r
|
||||
@ -135,9 +132,9 @@ func (b *Reader) readErr() error {
|
||||
// Peek returns the next n bytes without advancing the reader. The bytes stop
|
||||
// being valid at the next read call. If Peek returns fewer than n bytes, it
|
||||
// also returns an error explaining why the read is short. The error is
|
||||
// ErrBufferFull if n is larger than b's buffer size.
|
||||
// [ErrBufferFull] if n is larger than b's buffer size.
|
||||
//
|
||||
// Calling Peek prevents a UnreadByte or UnreadRune call from succeeding
|
||||
// Calling Peek prevents a [Reader.UnreadByte] or [Reader.UnreadRune] call from succeeding
|
||||
// until the next read operation.
|
||||
func (b *Reader) Peek(n int) ([]byte, error) {
|
||||
if n < 0 {
|
||||
@ -207,10 +204,10 @@ func (b *Reader) Discard(n int) (discarded int, err error) {
|
||||
|
||||
// Read reads data into p.
|
||||
// It returns the number of bytes read into p.
|
||||
// The bytes are taken from at most one Read on the underlying Reader,
|
||||
// The bytes are taken from at most one Read on the underlying [Reader],
|
||||
// hence n may be less than len(p).
|
||||
// To read exactly len(p) bytes, use io.ReadFull(b, p).
|
||||
// If the underlying Reader can return a non-zero count with io.EOF,
|
||||
// If the underlying [Reader] can return a non-zero count with io.EOF,
|
||||
// then this Read method can do so as well; see the [io.Reader] docs.
|
||||
func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
@ -280,7 +277,7 @@ func (b *Reader) ReadByte() (byte, error) {
|
||||
// UnreadByte unreads the last byte. Only the most recently read byte can be unread.
|
||||
//
|
||||
// UnreadByte returns an error if the most recent method called on the
|
||||
// Reader was not a read operation. Notably, Peek, Discard, and WriteTo are not
|
||||
// [Reader] was not a read operation. Notably, [Reader.Peek], [Reader.Discard], and [Reader.WriteTo] are not
|
||||
// considered read operations.
|
||||
func (b *Reader) UnreadByte() error {
|
||||
if b.lastByte < 0 || b.r == 0 && b.w > 0 {
|
||||
@ -321,8 +318,8 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||
}
|
||||
|
||||
// UnreadRune unreads the last rune. If the most recent method called on
|
||||
// the Reader was not a ReadRune, UnreadRune returns an error. (In this
|
||||
// regard it is stricter than UnreadByte, which will unread the last byte
|
||||
// the [Reader] was not a [Reader.ReadRune], [Reader.UnreadRune] returns an error. (In this
|
||||
// regard it is stricter than [Reader.UnreadByte], which will unread the last byte
|
||||
// from any read operation.)
|
||||
func (b *Reader) UnreadRune() error {
|
||||
if b.lastRuneSize < 0 || b.r < b.lastRuneSize {
|
||||
@ -342,10 +339,10 @@ func (b *Reader) Buffered() int { return b.w - b.r }
|
||||
// The bytes stop being valid at the next read.
|
||||
// If ReadSlice encounters an error before finding a delimiter,
|
||||
// it returns all the data in the buffer and the error itself (often io.EOF).
|
||||
// ReadSlice fails with error ErrBufferFull if the buffer fills without a delim.
|
||||
// ReadSlice fails with error [ErrBufferFull] if the buffer fills without a delim.
|
||||
// Because the data returned from ReadSlice will be overwritten
|
||||
// by the next I/O operation, most clients should use
|
||||
// ReadBytes or ReadString instead.
|
||||
// [Reader.ReadBytes] or ReadString instead.
|
||||
// ReadSlice returns err != nil if and only if line does not end in delim.
|
||||
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
s := 0 // search start index
|
||||
@ -389,7 +386,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
}
|
||||
|
||||
// ReadLine is a low-level line-reading primitive. Most callers should use
|
||||
// ReadBytes('\n') or ReadString('\n') instead or use a Scanner.
|
||||
// [Reader.ReadBytes]('\n') or [Reader.ReadString]('\n') instead or use a [Scanner].
|
||||
//
|
||||
// ReadLine tries to return a single line, not including the end-of-line bytes.
|
||||
// If the line was too long for the buffer then isPrefix is set and the
|
||||
@ -401,7 +398,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
|
||||
//
|
||||
// The text returned from ReadLine does not include the line end ("\r\n" or "\n").
|
||||
// No indication or error is given if the input ends without a final line end.
|
||||
// Calling UnreadByte after ReadLine will always unread the last byte read
|
||||
// Calling [Reader.UnreadByte] after ReadLine will always unread the last byte read
|
||||
// (possibly a character belonging to the line end) even if that byte is not
|
||||
// part of the line returned by ReadLine.
|
||||
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
|
||||
@ -511,9 +508,9 @@ func (b *Reader) ReadString(delim byte) (string, error) {
|
||||
}
|
||||
|
||||
// WriteTo implements io.WriterTo.
|
||||
// This may make multiple calls to the Read method of the underlying Reader.
|
||||
// If the underlying reader supports the WriteTo method,
|
||||
// this calls the underlying WriteTo without buffering.
|
||||
// This may make multiple calls to the [Reader.Read] method of the underlying [Reader].
|
||||
// If the underlying reader supports the [Reader.WriteTo] method,
|
||||
// this calls the underlying [Reader.WriteTo] without buffering.
|
||||
func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
b.lastByte = -1
|
||||
b.lastRuneSize = -1
|
||||
@ -558,7 +555,7 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
|
||||
var errNegativeWrite = errors.New("bufio: writer returned negative count from Write")
|
||||
|
||||
// writeBuf writes the Reader's buffer to the writer.
|
||||
// writeBuf writes the [Reader]'s buffer to the writer.
|
||||
func (b *Reader) writeBuf(w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b.buf[b.r:b.w])
|
||||
if n < 0 {
|
||||
@ -570,12 +567,12 @@ func (b *Reader) writeBuf(w io.Writer) (int64, error) {
|
||||
|
||||
// buffered output
|
||||
|
||||
// Writer implements buffering for an io.Writer object.
|
||||
// If an error occurs writing to a Writer, no more data will be
|
||||
// accepted and all subsequent writes, and Flush, will return the error.
|
||||
// Writer implements buffering for an [io.Writer] object.
|
||||
// If an error occurs writing to a [Writer], no more data will be
|
||||
// accepted and all subsequent writes, and [Writer.Flush], will return the error.
|
||||
// After all data has been written, the client should call the
|
||||
// Flush method to guarantee all data has been forwarded to
|
||||
// the underlying io.Writer.
|
||||
// [Writer.Flush] method to guarantee all data has been forwarded to
|
||||
// the underlying [io.Writer].
|
||||
type Writer struct {
|
||||
err error
|
||||
buf []byte
|
||||
@ -583,9 +580,9 @@ type Writer struct {
|
||||
wr io.Writer
|
||||
}
|
||||
|
||||
// NewWriterSize returns a new Writer whose buffer has at least the specified
|
||||
// size. If the argument io.Writer is already a Writer with large enough
|
||||
// size, it returns the underlying Writer.
|
||||
// NewWriterSize returns a new [Writer] whose buffer has at least the specified
|
||||
// size. If the argument io.Writer is already a [Writer] with large enough
|
||||
// size, it returns the underlying [Writer].
|
||||
func NewWriterSize(w io.Writer, size int) *Writer {
|
||||
// Is it already a Writer?
|
||||
b, ok := w.(*Writer)
|
||||
@ -601,9 +598,9 @@ func NewWriterSize(w io.Writer, size int) *Writer {
|
||||
}
|
||||
}
|
||||
|
||||
// NewWriter returns a new Writer whose buffer has the default size.
|
||||
// If the argument io.Writer is already a Writer with large enough buffer size,
|
||||
// it returns the underlying Writer.
|
||||
// NewWriter returns a new [Writer] whose buffer has the default size.
|
||||
// If the argument io.Writer is already a [Writer] with large enough buffer size,
|
||||
// it returns the underlying [Writer].
|
||||
func NewWriter(w io.Writer) *Writer {
|
||||
return NewWriterSize(w, defaultBufSize)
|
||||
}
|
||||
@ -613,9 +610,9 @@ func (b *Writer) Size() int { return len(b.buf) }
|
||||
|
||||
// Reset discards any unflushed buffered data, clears any error, and
|
||||
// resets b to write its output to w.
|
||||
// Calling Reset on the zero value of Writer initializes the internal buffer
|
||||
// Calling Reset on the zero value of [Writer] initializes the internal buffer
|
||||
// to the default size.
|
||||
// Calling w.Reset(w) (that is, resetting a Writer to itself) does nothing.
|
||||
// Calling w.Reset(w) (that is, resetting a [Writer] to itself) does nothing.
|
||||
func (b *Writer) Reset(w io.Writer) {
|
||||
// If a Writer w is passed to NewWriter, NewWriter will return w.
|
||||
// Different layers of code may do that, and then later pass w
|
||||
@ -631,7 +628,7 @@ func (b *Writer) Reset(w io.Writer) {
|
||||
b.wr = w
|
||||
}
|
||||
|
||||
// Flush writes any buffered data to the underlying io.Writer.
|
||||
// Flush writes any buffered data to the underlying [io.Writer].
|
||||
func (b *Writer) Flush() error {
|
||||
if b.err != nil {
|
||||
return b.err
|
||||
@ -660,7 +657,7 @@ func (b *Writer) Available() int { return len(b.buf) - b.n }
|
||||
|
||||
// AvailableBuffer returns an empty buffer with b.Available() capacity.
|
||||
// This buffer is intended to be appended to and
|
||||
// passed to an immediately succeeding Write call.
|
||||
// passed to an immediately succeeding [Writer.Write] call.
|
||||
// The buffer is only valid until the next write operation on b.
|
||||
func (b *Writer) AvailableBuffer() []byte {
|
||||
return b.buf[b.n:][:0]
|
||||
@ -777,7 +774,7 @@ func (b *Writer) WriteString(s string) (int, error) {
|
||||
return nn, nil
|
||||
}
|
||||
|
||||
// ReadFrom implements io.ReaderFrom. If the underlying writer
|
||||
// ReadFrom implements [io.ReaderFrom]. If the underlying writer
|
||||
// supports the ReadFrom method, this calls the underlying ReadFrom.
|
||||
// If there is buffered data and an underlying ReadFrom, this fills
|
||||
// the buffer and writes it before calling ReadFrom.
|
||||
@ -829,14 +826,14 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
|
||||
// buffered input and output
|
||||
|
||||
// ReadWriter stores pointers to a Reader and a Writer.
|
||||
// It implements io.ReadWriter.
|
||||
// ReadWriter stores pointers to a [Reader] and a [Writer].
|
||||
// It implements [io.ReadWriter].
|
||||
type ReadWriter struct {
|
||||
*Reader
|
||||
*Writer
|
||||
}
|
||||
|
||||
// NewReadWriter allocates a new ReadWriter that dispatches to r and w.
|
||||
// NewReadWriter allocates a new [ReadWriter] that dispatches to r and w.
|
||||
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
|
||||
return &ReadWriter{r, w}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package bufio_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
@ -137,3 +138,36 @@ func ExampleScanner_emptyFinalToken() {
|
||||
}
|
||||
// Output: "1" "2" "3" "4" ""
|
||||
}
|
||||
|
||||
// Use a Scanner with a custom split function to parse a comma-separated
|
||||
// list with an empty final value but stops at the token "STOP".
|
||||
func ExampleScanner_earlyStop() {
|
||||
onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
i := bytes.IndexByte(data, ',')
|
||||
if i == -1 {
|
||||
if !atEOF {
|
||||
return 0, nil, nil
|
||||
}
|
||||
// If we have reached the end, return the last token.
|
||||
return 0, data, bufio.ErrFinalToken
|
||||
}
|
||||
// If the token is "STOP", stop the scanning and ignore the rest.
|
||||
if string(data[:i]) == "STOP" {
|
||||
return i + 1, nil, bufio.ErrFinalToken
|
||||
}
|
||||
// Otherwise, return the token before the comma.
|
||||
return i + 1, data[:i], nil
|
||||
}
|
||||
const input = "1,2,STOP,4,"
|
||||
scanner := bufio.NewScanner(strings.NewReader(input))
|
||||
scanner.Split(onComma)
|
||||
for scanner.Scan() {
|
||||
fmt.Printf("Got a token %q\n", scanner.Text())
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "reading input:", err)
|
||||
}
|
||||
// Output:
|
||||
// Got a token "1"
|
||||
// Got a token "2"
|
||||
}
|
||||
|
@ -13,19 +13,19 @@ import (
|
||||
|
||||
// Scanner provides a convenient interface for reading data such as
|
||||
// a file of newline-delimited lines of text. Successive calls to
|
||||
// the Scan method will step through the 'tokens' of a file, skipping
|
||||
// the [Scanner.Scan] method will step through the 'tokens' of a file, skipping
|
||||
// the bytes between the tokens. The specification of a token is
|
||||
// defined by a split function of type SplitFunc; the default split
|
||||
// function breaks the input into lines with line termination stripped. Split
|
||||
// defined by a split function of type [SplitFunc]; the default split
|
||||
// function breaks the input into lines with line termination stripped. [Scanner.Split]
|
||||
// functions are defined in this package for scanning a file into
|
||||
// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
|
||||
// client may instead provide a custom split function.
|
||||
//
|
||||
// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
|
||||
// large to fit in the buffer. When a scan stops, the reader may have
|
||||
// large to fit in the [Scanner.Buffer]. When a scan stops, the reader may have
|
||||
// advanced arbitrarily far past the last token. Programs that need more
|
||||
// control over error handling or large tokens, or must run sequential scans
|
||||
// on a reader, should use bufio.Reader instead.
|
||||
// on a reader, should use [bufio.Reader] instead.
|
||||
type Scanner struct {
|
||||
r io.Reader // The reader provided by the client.
|
||||
split SplitFunc // The function to split the tokens.
|
||||
@ -42,21 +42,23 @@ type Scanner struct {
|
||||
|
||||
// SplitFunc is the signature of the split function used to tokenize the
|
||||
// input. The arguments are an initial substring of the remaining unprocessed
|
||||
// data and a flag, atEOF, that reports whether the Reader has no more data
|
||||
// data and a flag, atEOF, that reports whether the [Reader] has no more data
|
||||
// to give. The return values are the number of bytes to advance the input
|
||||
// and the next token to return to the user, if any, plus an error, if any.
|
||||
//
|
||||
// Scanning stops if the function returns an error, in which case some of
|
||||
// the input may be discarded. If that error is ErrFinalToken, scanning
|
||||
// stops with no error.
|
||||
// the input may be discarded. If that error is [ErrFinalToken], scanning
|
||||
// stops with no error. A non-nil token delivered with [ErrFinalToken]
|
||||
// will be the last token, and a nil token with [ErrFinalToken]
|
||||
// immediately stops the scanning.
|
||||
//
|
||||
// Otherwise, the Scanner advances the input. If the token is not nil,
|
||||
// the Scanner returns it to the user. If the token is nil, the
|
||||
// Otherwise, the [Scanner] advances the input. If the token is not nil,
|
||||
// the [Scanner] returns it to the user. If the token is nil, the
|
||||
// Scanner reads more data and continues scanning; if there is no more
|
||||
// data--if atEOF was true--the Scanner returns. If the data does not
|
||||
// data--if atEOF was true--the [Scanner] returns. If the data does not
|
||||
// yet hold a complete token, for instance if it has no newline while
|
||||
// scanning lines, a SplitFunc can return (0, nil, nil) to signal the
|
||||
// Scanner to read more data into the slice and try again with a
|
||||
// scanning lines, a [SplitFunc] can return (0, nil, nil) to signal the
|
||||
// [Scanner] to read more data into the slice and try again with a
|
||||
// longer slice starting at the same point in the input.
|
||||
//
|
||||
// The function is never called with an empty data slice unless atEOF
|
||||
@ -74,7 +76,7 @@ var (
|
||||
|
||||
const (
|
||||
// MaxScanTokenSize is the maximum size used to buffer a token
|
||||
// unless the user provides an explicit buffer with Scanner.Buffer.
|
||||
// unless the user provides an explicit buffer with [Scanner.Buffer].
|
||||
// The actual maximum token size may be smaller as the buffer
|
||||
// may need to include, for instance, a newline.
|
||||
MaxScanTokenSize = 64 * 1024
|
||||
@ -82,8 +84,8 @@ const (
|
||||
startBufSize = 4096 // Size of initial allocation for buffer.
|
||||
)
|
||||
|
||||
// NewScanner returns a new Scanner to read from r.
|
||||
// The split function defaults to ScanLines.
|
||||
// NewScanner returns a new [Scanner] to read from r.
|
||||
// The split function defaults to [ScanLines].
|
||||
func NewScanner(r io.Reader) *Scanner {
|
||||
return &Scanner{
|
||||
r: r,
|
||||
@ -92,7 +94,7 @@ func NewScanner(r io.Reader) *Scanner {
|
||||
}
|
||||
}
|
||||
|
||||
// Err returns the first non-EOF error that was encountered by the Scanner.
|
||||
// Err returns the first non-EOF error that was encountered by the [Scanner].
|
||||
func (s *Scanner) Err() error {
|
||||
if s.err == io.EOF {
|
||||
return nil
|
||||
@ -100,34 +102,36 @@ func (s *Scanner) Err() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
// Bytes returns the most recent token generated by a call to Scan.
|
||||
// Bytes returns the most recent token generated by a call to [Scanner.Scan].
|
||||
// The underlying array may point to data that will be overwritten
|
||||
// by a subsequent call to Scan. It does no allocation.
|
||||
func (s *Scanner) Bytes() []byte {
|
||||
return s.token
|
||||
}
|
||||
|
||||
// Text returns the most recent token generated by a call to Scan
|
||||
// Text returns the most recent token generated by a call to [Scanner.Scan]
|
||||
// as a newly allocated string holding its bytes.
|
||||
func (s *Scanner) Text() string {
|
||||
return string(s.token)
|
||||
}
|
||||
|
||||
// ErrFinalToken is a special sentinel error value. It is intended to be
|
||||
// returned by a Split function to indicate that the token being delivered
|
||||
// with the error is the last token and scanning should stop after this one.
|
||||
// After ErrFinalToken is received by Scan, scanning stops with no error.
|
||||
// returned by a Split function to indicate that the scanning should stop
|
||||
// with no error. If the token being delivered with this error is not nil,
|
||||
// the token is the last token.
|
||||
//
|
||||
// The value is useful to stop processing early or when it is necessary to
|
||||
// deliver a final empty token. One could achieve the same behavior
|
||||
// with a custom error value but providing one here is tidier.
|
||||
// deliver a final empty token (which is different from a nil token).
|
||||
// One could achieve the same behavior with a custom error value but
|
||||
// providing one here is tidier.
|
||||
// See the emptyFinalToken example for a use of this value.
|
||||
var ErrFinalToken = errors.New("final token")
|
||||
|
||||
// Scan advances the Scanner to the next token, which will then be
|
||||
// available through the Bytes or Text method. It returns false when the
|
||||
// scan stops, either by reaching the end of the input or an error.
|
||||
// After Scan returns false, the Err method will return any error that
|
||||
// occurred during scanning, except that if it was io.EOF, Err
|
||||
// Scan advances the [Scanner] to the next token, which will then be
|
||||
// available through the [Scanner.Bytes] or [Scanner.Text] method. It returns false when
|
||||
// there are no more tokens, either by reaching the end of the input or an error.
|
||||
// After Scan returns false, the [Scanner.Err] method will return any error that
|
||||
// occurred during scanning, except that if it was [io.EOF], [Scanner.Err]
|
||||
// will return nil.
|
||||
// Scan panics if the split function returns too many empty
|
||||
// tokens without advancing the input. This is a common error mode for
|
||||
@ -148,7 +152,10 @@ func (s *Scanner) Scan() bool {
|
||||
if err == ErrFinalToken {
|
||||
s.token = token
|
||||
s.done = true
|
||||
return true
|
||||
// When token is not nil, it means the scanning stops
|
||||
// with a trailing token, and thus the return value
|
||||
// should be true to indicate the existence of the token.
|
||||
return token != nil
|
||||
}
|
||||
s.setErr(err)
|
||||
return false
|
||||
@ -198,9 +205,7 @@ func (s *Scanner) Scan() bool {
|
||||
if newSize == 0 {
|
||||
newSize = startBufSize
|
||||
}
|
||||
if newSize > s.maxTokenSize {
|
||||
newSize = s.maxTokenSize
|
||||
}
|
||||
newSize = min(newSize, s.maxTokenSize)
|
||||
newBuf := make([]byte, newSize)
|
||||
copy(newBuf, s.buf[s.start:s.end])
|
||||
s.buf = newBuf
|
||||
@ -258,10 +263,10 @@ func (s *Scanner) setErr(err error) {
|
||||
// Buffer sets the initial buffer to use when scanning
|
||||
// and the maximum size of buffer that may be allocated during scanning.
|
||||
// The maximum token size must be less than the larger of max and cap(buf).
|
||||
// If max <= cap(buf), Scan will use this buffer only and do no allocation.
|
||||
// If max <= cap(buf), [Scanner.Scan] will use this buffer only and do no allocation.
|
||||
//
|
||||
// By default, Scan uses an internal buffer and sets the
|
||||
// maximum token size to MaxScanTokenSize.
|
||||
// By default, [Scanner.Scan] uses an internal buffer and sets the
|
||||
// maximum token size to [MaxScanTokenSize].
|
||||
//
|
||||
// Buffer panics if it is called after scanning has started.
|
||||
func (s *Scanner) Buffer(buf []byte, max int) {
|
||||
@ -272,8 +277,8 @@ func (s *Scanner) Buffer(buf []byte, max int) {
|
||||
s.maxTokenSize = max
|
||||
}
|
||||
|
||||
// Split sets the split function for the Scanner.
|
||||
// The default split function is ScanLines.
|
||||
// Split sets the split function for the [Scanner].
|
||||
// The default split function is [ScanLines].
|
||||
//
|
||||
// Split panics if it is called after scanning has started.
|
||||
func (s *Scanner) Split(split SplitFunc) {
|
||||
@ -285,7 +290,7 @@ func (s *Scanner) Split(split SplitFunc) {
|
||||
|
||||
// Split functions
|
||||
|
||||
// ScanBytes is a split function for a Scanner that returns each byte as a token.
|
||||
// ScanBytes is a split function for a [Scanner] that returns each byte as a token.
|
||||
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
if atEOF && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
@ -295,7 +300,7 @@ func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
|
||||
var errorRune = []byte(string(utf8.RuneError))
|
||||
|
||||
// ScanRunes is a split function for a Scanner that returns each
|
||||
// ScanRunes is a split function for a [Scanner] that returns each
|
||||
// UTF-8-encoded rune as a token. The sequence of runes returned is
|
||||
// equivalent to that from a range loop over the input as a string, which
|
||||
// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
|
||||
@ -341,7 +346,7 @@ func dropCR(data []byte) []byte {
|
||||
return data
|
||||
}
|
||||
|
||||
// ScanLines is a split function for a Scanner that returns each line of
|
||||
// ScanLines is a split function for a [Scanner] that returns each line of
|
||||
// text, stripped of any trailing end-of-line marker. The returned line may
|
||||
// be empty. The end-of-line marker is one optional carriage return followed
|
||||
// by one mandatory newline. In regular expression notation, it is `\r?\n`.
|
||||
@ -388,7 +393,7 @@ func isSpace(r rune) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ScanWords is a split function for a Scanner that returns each
|
||||
// ScanWords is a split function for a [Scanner] that returns each
|
||||
// space-separated word of text, with surrounding spaces deleted. It will
|
||||
// never return an empty string. The definition of space is set by
|
||||
// unicode.IsSpace.
|
||||
|
@ -284,9 +284,10 @@ func panic(v any)
|
||||
// by restoring normal execution and retrieves the error value passed to the
|
||||
// call of panic. If recover is called outside the deferred function it will
|
||||
// not stop a panicking sequence. In this case, or when the goroutine is not
|
||||
// panicking, or if the argument supplied to panic was nil, recover returns
|
||||
// nil. Thus the return value from recover reports whether the goroutine is
|
||||
// panicking.
|
||||
// panicking, recover returns nil.
|
||||
//
|
||||
// Prior to Go 1.21, recover would also return nil if panic is called with
|
||||
// a nil argument. See [panic] for details.
|
||||
func recover() any
|
||||
|
||||
// The print built-in function formats its arguments in an
|
||||
|
@ -98,3 +98,18 @@ func TestIndexNearPageBoundary(t *testing.T) {
|
||||
}
|
||||
q[len(q)-1] = 0
|
||||
}
|
||||
|
||||
func TestCountNearPageBoundary(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := dangerousSlice(t)
|
||||
for i := range b {
|
||||
c := Count(b[i:], []byte{1})
|
||||
if c != 0 {
|
||||
t.Fatalf("Count(b[%d:], {1})=%d, want 0\n", i, c)
|
||||
}
|
||||
c = Count(b[:i], []byte{0})
|
||||
if c != i {
|
||||
t.Fatalf("Count(b[:%d], {0})=%d, want %d\n", i, c, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
// smallBufferSize is an initial allocation minimal capacity.
|
||||
const smallBufferSize = 64
|
||||
|
||||
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
|
||||
// A Buffer is a variable-sized buffer of bytes with [Buffer.Read] and [Buffer.Write] methods.
|
||||
// The zero value for Buffer is an empty buffer ready to use.
|
||||
type Buffer struct {
|
||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||
@ -48,19 +48,19 @@ const maxInt = int(^uint(0) >> 1)
|
||||
|
||||
// Bytes returns a slice of length b.Len() holding the unread portion of the buffer.
|
||||
// The slice is valid for use only until the next buffer modification (that is,
|
||||
// only until the next call to a method like Read, Write, Reset, or Truncate).
|
||||
// only until the next call to a method like [Buffer.Read], [Buffer.Write], [Buffer.Reset], or [Buffer.Truncate]).
|
||||
// The slice aliases the buffer content at least until the next buffer modification,
|
||||
// so immediate changes to the slice will affect the result of future reads.
|
||||
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
|
||||
|
||||
// AvailableBuffer returns an empty buffer with b.Available() capacity.
|
||||
// This buffer is intended to be appended to and
|
||||
// passed to an immediately succeeding Write call.
|
||||
// passed to an immediately succeeding [Buffer.Write] call.
|
||||
// The buffer is only valid until the next write operation on b.
|
||||
func (b *Buffer) AvailableBuffer() []byte { return b.buf[len(b.buf):] }
|
||||
|
||||
// String returns the contents of the unread portion of the buffer
|
||||
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
|
||||
// as a string. If the [Buffer] is a nil pointer, it returns "<nil>".
|
||||
//
|
||||
// To build strings more efficiently, see the strings.Builder type.
|
||||
func (b *Buffer) String() string {
|
||||
@ -102,7 +102,7 @@ func (b *Buffer) Truncate(n int) {
|
||||
|
||||
// Reset resets the buffer to be empty,
|
||||
// but it retains the underlying storage for use by future writes.
|
||||
// Reset is the same as Truncate(0).
|
||||
// Reset is the same as [Buffer.Truncate](0).
|
||||
func (b *Buffer) Reset() {
|
||||
b.buf = b.buf[:0]
|
||||
b.off = 0
|
||||
@ -160,7 +160,7 @@ func (b *Buffer) grow(n int) int {
|
||||
// another n bytes. After Grow(n), at least n bytes can be written to the
|
||||
// buffer without another allocation.
|
||||
// If n is negative, Grow will panic.
|
||||
// If the buffer can't grow it will panic with ErrTooLarge.
|
||||
// If the buffer can't grow it will panic with [ErrTooLarge].
|
||||
func (b *Buffer) Grow(n int) {
|
||||
if n < 0 {
|
||||
panic("bytes.Buffer.Grow: negative count")
|
||||
@ -171,7 +171,7 @@ func (b *Buffer) Grow(n int) {
|
||||
|
||||
// Write appends the contents of p to the buffer, growing the buffer as
|
||||
// needed. The return value n is the length of p; err is always nil. If the
|
||||
// buffer becomes too large, Write will panic with ErrTooLarge.
|
||||
// buffer becomes too large, Write will panic with [ErrTooLarge].
|
||||
func (b *Buffer) Write(p []byte) (n int, err error) {
|
||||
b.lastRead = opInvalid
|
||||
m, ok := b.tryGrowByReslice(len(p))
|
||||
@ -183,7 +183,7 @@ func (b *Buffer) Write(p []byte) (n int, err error) {
|
||||
|
||||
// WriteString appends the contents of s to the buffer, growing the buffer as
|
||||
// needed. The return value n is the length of s; err is always nil. If the
|
||||
// buffer becomes too large, WriteString will panic with ErrTooLarge.
|
||||
// buffer becomes too large, WriteString will panic with [ErrTooLarge].
|
||||
func (b *Buffer) WriteString(s string) (n int, err error) {
|
||||
b.lastRead = opInvalid
|
||||
m, ok := b.tryGrowByReslice(len(s))
|
||||
@ -194,7 +194,7 @@ func (b *Buffer) WriteString(s string) (n int, err error) {
|
||||
}
|
||||
|
||||
// MinRead is the minimum slice size passed to a Read call by
|
||||
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
|
||||
// [Buffer.ReadFrom]. As long as the [Buffer] has at least MinRead bytes beyond
|
||||
// what is required to hold the contents of r, ReadFrom will not grow the
|
||||
// underlying buffer.
|
||||
const MinRead = 512
|
||||
@ -202,7 +202,7 @@ const MinRead = 512
|
||||
// ReadFrom reads data from r until EOF and appends it to the buffer, growing
|
||||
// the buffer as needed. The return value n is the number of bytes read. Any
|
||||
// error except io.EOF encountered during the read is also returned. If the
|
||||
// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
|
||||
// buffer becomes too large, ReadFrom will panic with [ErrTooLarge].
|
||||
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
b.lastRead = opInvalid
|
||||
for {
|
||||
@ -279,9 +279,9 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
|
||||
}
|
||||
|
||||
// WriteByte appends the byte c to the buffer, growing the buffer as needed.
|
||||
// The returned error is always nil, but is included to match bufio.Writer's
|
||||
// The returned error is always nil, but is included to match [bufio.Writer]'s
|
||||
// WriteByte. If the buffer becomes too large, WriteByte will panic with
|
||||
// ErrTooLarge.
|
||||
// [ErrTooLarge].
|
||||
func (b *Buffer) WriteByte(c byte) error {
|
||||
b.lastRead = opInvalid
|
||||
m, ok := b.tryGrowByReslice(1)
|
||||
@ -294,8 +294,8 @@ func (b *Buffer) WriteByte(c byte) error {
|
||||
|
||||
// WriteRune appends the UTF-8 encoding of Unicode code point r to the
|
||||
// buffer, returning its length and an error, which is always nil but is
|
||||
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
|
||||
// if it becomes too large, WriteRune will panic with ErrTooLarge.
|
||||
// included to match [bufio.Writer]'s WriteRune. The buffer is grown as needed;
|
||||
// if it becomes too large, WriteRune will panic with [ErrTooLarge].
|
||||
func (b *Buffer) WriteRune(r rune) (n int, err error) {
|
||||
// Compare as uint32 to correctly handle negative runes.
|
||||
if uint32(r) < utf8.RuneSelf {
|
||||
@ -334,7 +334,7 @@ func (b *Buffer) Read(p []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
// Next returns a slice containing the next n bytes from the buffer,
|
||||
// advancing the buffer as if the bytes had been returned by Read.
|
||||
// advancing the buffer as if the bytes had been returned by [Buffer.Read].
|
||||
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
|
||||
// The slice is only valid until the next call to a read or write method.
|
||||
func (b *Buffer) Next(n int) []byte {
|
||||
@ -388,10 +388,10 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
|
||||
return r, n, nil
|
||||
}
|
||||
|
||||
// UnreadRune unreads the last rune returned by ReadRune.
|
||||
// UnreadRune unreads the last rune returned by [Buffer.ReadRune].
|
||||
// If the most recent read or write operation on the buffer was
|
||||
// not a successful ReadRune, UnreadRune returns an error. (In this regard
|
||||
// it is stricter than UnreadByte, which will unread the last byte
|
||||
// not a successful [Buffer.ReadRune], UnreadRune returns an error. (In this regard
|
||||
// it is stricter than [Buffer.UnreadByte], which will unread the last byte
|
||||
// from any read operation.)
|
||||
func (b *Buffer) UnreadRune() error {
|
||||
if b.lastRead <= opInvalid {
|
||||
@ -460,23 +460,23 @@ func (b *Buffer) ReadString(delim byte) (line string, err error) {
|
||||
return string(slice), err
|
||||
}
|
||||
|
||||
// NewBuffer creates and initializes a new Buffer using buf as its
|
||||
// initial contents. The new Buffer takes ownership of buf, and the
|
||||
// NewBuffer creates and initializes a new [Buffer] using buf as its
|
||||
// initial contents. The new [Buffer] takes ownership of buf, and the
|
||||
// caller should not use buf after this call. NewBuffer is intended to
|
||||
// prepare a Buffer to read existing data. It can also be used to set
|
||||
// prepare a [Buffer] to read existing data. It can also be used to set
|
||||
// the initial size of the internal buffer for writing. To do that,
|
||||
// buf should have the desired capacity but a length of zero.
|
||||
//
|
||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
||||
// sufficient to initialize a Buffer.
|
||||
// In most cases, new([Buffer]) (or just declaring a [Buffer] variable) is
|
||||
// sufficient to initialize a [Buffer].
|
||||
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
|
||||
|
||||
// NewBufferString creates and initializes a new Buffer using string s as its
|
||||
// NewBufferString creates and initializes a new [Buffer] using string s as its
|
||||
// initial contents. It is intended to prepare a buffer to read an existing
|
||||
// string.
|
||||
//
|
||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
|
||||
// sufficient to initialize a Buffer.
|
||||
// In most cases, new([Buffer]) (or just declaring a [Buffer] variable) is
|
||||
// sufficient to initialize a [Buffer].
|
||||
func NewBufferString(s string) *Buffer {
|
||||
return &Buffer{buf: []byte(s)}
|
||||
}
|
||||
|
@ -121,25 +121,7 @@ func LastIndex(s, sep []byte) int {
|
||||
case n > len(s):
|
||||
return -1
|
||||
}
|
||||
// Rabin-Karp search from the end of the string
|
||||
hashss, pow := bytealg.HashStrRevBytes(sep)
|
||||
last := len(s) - n
|
||||
var h uint32
|
||||
for i := len(s) - 1; i >= last; i-- {
|
||||
h = h*bytealg.PrimeRK + uint32(s[i])
|
||||
}
|
||||
if h == hashss && Equal(s[last:], sep) {
|
||||
return last
|
||||
}
|
||||
for i := last - 1; i >= 0; i-- {
|
||||
h *= bytealg.PrimeRK
|
||||
h += uint32(s[i])
|
||||
h -= pow * uint32(s[i+n])
|
||||
if h == hashss && Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
return bytealg.LastIndexRabinKarp(s, sep)
|
||||
}
|
||||
|
||||
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
|
||||
@ -1331,7 +1313,7 @@ func Index(s, sep []byte) int {
|
||||
// we should cutover at even larger average skips,
|
||||
// because Equal becomes that much more expensive.
|
||||
// This code does not take that effect into account.
|
||||
j := bytealg.IndexRabinKarpBytes(s[i:], sep)
|
||||
j := bytealg.IndexRabinKarp(s[i:], sep)
|
||||
if j < 0 {
|
||||
return -1
|
||||
}
|
||||
|
@ -212,6 +212,17 @@ func ExampleContainsRune() {
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleContainsFunc() {
|
||||
f := func(r rune) bool {
|
||||
return r >= 'a' && r <= 'z'
|
||||
}
|
||||
fmt.Println(bytes.ContainsFunc([]byte("HELLO"), f))
|
||||
fmt.Println(bytes.ContainsFunc([]byte("World"), f))
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleCount() {
|
||||
fmt.Println(bytes.Count([]byte("cheese"), []byte("e")))
|
||||
fmt.Println(bytes.Count([]byte("five"), []byte(""))) // before & after each rune
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
// A Reader implements the io.Reader, io.ReaderAt, io.WriterTo, io.Seeker,
|
||||
// io.ByteScanner, and io.RuneScanner interfaces by reading from
|
||||
// a byte slice.
|
||||
// Unlike a Buffer, a Reader is read-only and supports seeking.
|
||||
// Unlike a [Buffer], a Reader is read-only and supports seeking.
|
||||
// The zero value for Reader operates like a Reader of an empty slice.
|
||||
type Reader struct {
|
||||
s []byte
|
||||
@ -31,11 +31,11 @@ func (r *Reader) Len() int {
|
||||
}
|
||||
|
||||
// Size returns the original length of the underlying byte slice.
|
||||
// Size is the number of bytes available for reading via ReadAt.
|
||||
// The result is unaffected by any method calls except Reset.
|
||||
// Size is the number of bytes available for reading via [Reader.ReadAt].
|
||||
// The result is unaffected by any method calls except [Reader.Reset].
|
||||
func (r *Reader) Size() int64 { return int64(len(r.s)) }
|
||||
|
||||
// Read implements the io.Reader interface.
|
||||
// Read implements the [io.Reader] interface.
|
||||
func (r *Reader) Read(b []byte) (n int, err error) {
|
||||
if r.i >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
@ -46,7 +46,7 @@ func (r *Reader) Read(b []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReadAt implements the io.ReaderAt interface.
|
||||
// ReadAt implements the [io.ReaderAt] interface.
|
||||
func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
// cannot modify state - see io.ReaderAt
|
||||
if off < 0 {
|
||||
@ -62,7 +62,7 @@ func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ReadByte implements the io.ByteReader interface.
|
||||
// ReadByte implements the [io.ByteReader] interface.
|
||||
func (r *Reader) ReadByte() (byte, error) {
|
||||
r.prevRune = -1
|
||||
if r.i >= int64(len(r.s)) {
|
||||
@ -73,7 +73,7 @@ func (r *Reader) ReadByte() (byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UnreadByte complements ReadByte in implementing the io.ByteScanner interface.
|
||||
// UnreadByte complements [Reader.ReadByte] in implementing the [io.ByteScanner] interface.
|
||||
func (r *Reader) UnreadByte() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
|
||||
@ -83,7 +83,7 @@ func (r *Reader) UnreadByte() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadRune implements the io.RuneReader interface.
|
||||
// ReadRune implements the [io.RuneReader] interface.
|
||||
func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||
if r.i >= int64(len(r.s)) {
|
||||
r.prevRune = -1
|
||||
@ -99,7 +99,7 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// UnreadRune complements ReadRune in implementing the io.RuneScanner interface.
|
||||
// UnreadRune complements [Reader.ReadRune] in implementing the [io.RuneScanner] interface.
|
||||
func (r *Reader) UnreadRune() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader.UnreadRune: at beginning of slice")
|
||||
@ -112,7 +112,7 @@ func (r *Reader) UnreadRune() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Seek implements the io.Seeker interface.
|
||||
// Seek implements the [io.Seeker] interface.
|
||||
func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||
r.prevRune = -1
|
||||
var abs int64
|
||||
@ -133,7 +133,7 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
|
||||
return abs, nil
|
||||
}
|
||||
|
||||
// WriteTo implements the io.WriterTo interface.
|
||||
// WriteTo implements the [io.WriterTo] interface.
|
||||
func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
r.prevRune = -1
|
||||
if r.i >= int64(len(r.s)) {
|
||||
@ -152,8 +152,8 @@ func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Reset resets the Reader to be reading from b.
|
||||
// Reset resets the [Reader.Reader] to be reading from b.
|
||||
func (r *Reader) Reset(b []byte) { *r = Reader{b, 0, -1} }
|
||||
|
||||
// NewReader returns a new Reader reading from b.
|
||||
// NewReader returns a new [Reader.Reader] reading from b.
|
||||
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }
|
||||
|
@ -285,6 +285,25 @@ func TestIssue41358(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue64958(t *testing.T) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
t.Errorf("expected no panic; recovered %v", x)
|
||||
}
|
||||
}()
|
||||
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
for _, context := range contexts {
|
||||
w := NewWalker(context, "testdata/src/issue64958")
|
||||
pkg, err := w.importFrom("p", "", 0)
|
||||
if err != nil {
|
||||
t.Errorf("expected no error importing; got %T", err)
|
||||
}
|
||||
w.export(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) {
|
||||
if !*flagCheck {
|
||||
t.Skip("-check not specified")
|
||||
|
@ -106,7 +106,7 @@ func Check(t *testing.T) {
|
||||
}
|
||||
|
||||
var nextFiles []string
|
||||
if strings.Contains(runtime.Version(), "devel") {
|
||||
if v := runtime.Version(); strings.Contains(v, "devel") || strings.Contains(v, "beta") {
|
||||
next, err := filepath.Glob(filepath.Join(testenv.GOROOT(t), "api/next/*.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -957,17 +957,17 @@ func (w *Walker) emitType(obj *types.TypeName) {
|
||||
if w.isDeprecated(obj) {
|
||||
w.emitf("type %s //deprecated", name)
|
||||
}
|
||||
typ := obj.Type()
|
||||
if obj.IsAlias() {
|
||||
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||
return
|
||||
}
|
||||
if tparams := obj.Type().(*types.Named).TypeParams(); tparams != nil {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(name)
|
||||
w.writeTypeParams(&buf, tparams, true)
|
||||
name = buf.String()
|
||||
}
|
||||
typ := obj.Type()
|
||||
if obj.IsAlias() {
|
||||
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||
return
|
||||
}
|
||||
switch typ := typ.Underlying().(type) {
|
||||
case *types.Struct:
|
||||
w.emitStructType(name, typ)
|
||||
|
3
src/cmd/api/testdata/src/issue64958/p/p.go
vendored
Normal file
3
src/cmd/api/testdata/src/issue64958/p/p.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package p
|
||||
|
||||
type BasicAlias = uint8
|
@ -141,11 +141,17 @@ Diff:
|
||||
// Turn relative (PC) into absolute (PC) automatically,
|
||||
// so that most branch instructions don't need comments
|
||||
// giving the absolute form.
|
||||
if len(f) > 0 && strings.HasSuffix(printed, "(PC)") {
|
||||
last := f[len(f)-1]
|
||||
n, err := strconv.Atoi(last[:len(last)-len("(PC)")])
|
||||
if len(f) > 0 && strings.Contains(printed, "(PC)") {
|
||||
index := len(f) - 1
|
||||
suf := "(PC)"
|
||||
for !strings.HasSuffix(f[index], suf) {
|
||||
index--
|
||||
suf = "(PC),"
|
||||
}
|
||||
str := f[index]
|
||||
n, err := strconv.Atoi(str[:len(str)-len(suf)])
|
||||
if err == nil {
|
||||
f[len(f)-1] = fmt.Sprintf("%d(PC)", seq+n)
|
||||
f[index] = fmt.Sprintf("%d%s", seq+n, suf)
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,10 +378,10 @@ func Test386EndToEnd(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestARMEndToEnd(t *testing.T) {
|
||||
defer func(old int) { buildcfg.GOARM = old }(buildcfg.GOARM)
|
||||
defer func(old int) { buildcfg.GOARM.Version = old }(buildcfg.GOARM.Version)
|
||||
for _, goarm := range []int{5, 6, 7} {
|
||||
t.Logf("GOARM=%d", goarm)
|
||||
buildcfg.GOARM = goarm
|
||||
buildcfg.GOARM.Version = goarm
|
||||
testEndToEnd(t, "arm", "arm")
|
||||
if goarm == 6 {
|
||||
testEndToEnd(t, "arm", "armv6")
|
||||
|
22
src/cmd/asm/internal/asm/testdata/arm.s
vendored
22
src/cmd/asm/internal/asm/testdata/arm.s
vendored
@ -870,10 +870,13 @@ jmp_label_3:
|
||||
BIC.S R0@>R1, R2 // 7021d2e1
|
||||
|
||||
// SRL
|
||||
SRL $0, R5, R6 // 0560a0e1
|
||||
SRL $1, R5, R6 // a560a0e1
|
||||
SRL $14, R5, R6 // 2567a0e1
|
||||
SRL $15, R5, R6 // a567a0e1
|
||||
SRL $30, R5, R6 // 256fa0e1
|
||||
SRL $31, R5, R6 // a56fa0e1
|
||||
SRL $32, R5, R6 // 2560a0e1
|
||||
SRL.S $14, R5, R6 // 2567b0e1
|
||||
SRL.S $15, R5, R6 // a567b0e1
|
||||
SRL.S $30, R5, R6 // 256fb0e1
|
||||
@ -892,10 +895,13 @@ jmp_label_3:
|
||||
SRL.S R5, R7 // 3775b0e1
|
||||
|
||||
// SRA
|
||||
SRA $0, R5, R6 // 0560a0e1
|
||||
SRA $1, R5, R6 // c560a0e1
|
||||
SRA $14, R5, R6 // 4567a0e1
|
||||
SRA $15, R5, R6 // c567a0e1
|
||||
SRA $30, R5, R6 // 456fa0e1
|
||||
SRA $31, R5, R6 // c56fa0e1
|
||||
SRA $32, R5, R6 // 4560a0e1
|
||||
SRA.S $14, R5, R6 // 4567b0e1
|
||||
SRA.S $15, R5, R6 // c567b0e1
|
||||
SRA.S $30, R5, R6 // 456fb0e1
|
||||
@ -914,6 +920,8 @@ jmp_label_3:
|
||||
SRA.S R5, R7 // 5775b0e1
|
||||
|
||||
// SLL
|
||||
SLL $0, R5, R6 // 0560a0e1
|
||||
SLL $1, R5, R6 // 8560a0e1
|
||||
SLL $14, R5, R6 // 0567a0e1
|
||||
SLL $15, R5, R6 // 8567a0e1
|
||||
SLL $30, R5, R6 // 056fa0e1
|
||||
@ -935,6 +943,20 @@ jmp_label_3:
|
||||
SLL R5, R7 // 1775a0e1
|
||||
SLL.S R5, R7 // 1775b0e1
|
||||
|
||||
// Ops with zero shifts should encode as left shifts
|
||||
ADD R0<<0, R1, R2 // 002081e0
|
||||
ADD R0>>0, R1, R2 // 002081e0
|
||||
ADD R0->0, R1, R2 // 002081e0
|
||||
ADD R0@>0, R1, R2 // 002081e0
|
||||
MOVW R0<<0(R1), R2 // 002091e7
|
||||
MOVW R0>>0(R1), R2 // 002091e7
|
||||
MOVW R0->0(R1), R2 // 002091e7
|
||||
MOVW R0@>0(R1), R2 // 002091e7
|
||||
MOVW R0, R1<<0(R2) // 010082e7
|
||||
MOVW R0, R1>>0(R2) // 010082e7
|
||||
MOVW R0, R1->0(R2) // 010082e7
|
||||
MOVW R0, R1@>0(R2) // 010082e7
|
||||
|
||||
// MULA / MULS
|
||||
MULAWT R1, R2, R3, R4 // c23124e1
|
||||
MULAWB R1, R2, R3, R4 // 823124e1
|
||||
|
11
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
11
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
@ -981,6 +981,14 @@ again:
|
||||
ADR next, R11 // ADR R11 // 2b000010
|
||||
next:
|
||||
NOP
|
||||
ADR -2(PC), R10 // 0a000010
|
||||
ADR 2(PC), R16 // 10000010
|
||||
ADR -26(PC), R1 // 01000010
|
||||
ADR 12(PC), R2 // 02000010
|
||||
ADRP -2(PC), R10 // 0a000090
|
||||
ADRP 2(PC), R16 // 10000090
|
||||
ADRP -26(PC), R1 // 01000090
|
||||
ADRP 12(PC), R2 // 02000090
|
||||
|
||||
// LDP/STP
|
||||
LDP (R0), (R0, R1) // 000440a9
|
||||
@ -1003,6 +1011,7 @@ next:
|
||||
LDP -8(R0), (R1, R2) // 01887fa9
|
||||
LDP x(SB), (R1, R2)
|
||||
LDP x+8(SB), (R1, R2)
|
||||
LDP 8(R1), (ZR, R2) // 3f8840a9
|
||||
LDPW -5(R0), (R1, R2) // 1b1400d1610b4029
|
||||
LDPW (R0), (R1, R2) // 01084029
|
||||
LDPW 4(R0), (R1, R2) // 01884029
|
||||
@ -1020,6 +1029,7 @@ next:
|
||||
LDPW 1024(RSP), (R1, R2) // fb031091610b4029
|
||||
LDPW x(SB), (R1, R2)
|
||||
LDPW x+8(SB), (R1, R2)
|
||||
LDPW 8(R1), (ZR, R2) // 3f084129
|
||||
LDPSW (R0), (R1, R2) // 01084069
|
||||
LDPSW 4(R0), (R1, R2) // 01884069
|
||||
LDPSW -4(R0), (R1, R2) // 01887f69
|
||||
@ -1036,6 +1046,7 @@ next:
|
||||
LDPSW 1024(RSP), (R1, R2) // fb031091610b4069
|
||||
LDPSW x(SB), (R1, R2)
|
||||
LDPSW x+8(SB), (R1, R2)
|
||||
LDPSW 8(R1), (ZR, R2) // 3f084169
|
||||
STP (R3, R4), (R5) // a31000a9
|
||||
STP (R3, R4), 8(R5) // a39000a9
|
||||
STP.W (R3, R4), 8(R5) // a39080a9
|
||||
|
@ -66,7 +66,6 @@ TEXT errors(SB),$0
|
||||
LDP.W 8(R3), (R2, R3) // ERROR "constrained unpredictable behavior"
|
||||
LDP (R1), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||
LDP (R0), (F0, F1) // ERROR "invalid register pair"
|
||||
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
|
||||
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||
MOVD.P 300(R2), R3 // ERROR "offset out of range [-256,255]"
|
||||
|
51
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
51
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
@ -17,14 +17,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVD $1, R3 // 38600001
|
||||
MOVD $-1, R4 // 3880ffff
|
||||
MOVD $65535, R5 // 6005ffff
|
||||
MOVD $65536, R6 // 64060001
|
||||
MOVD $65536, R6 // 3cc00001
|
||||
MOVD $-32767, R5 // 38a08001
|
||||
MOVD $-32768, R6 // 38c08000
|
||||
MOVD $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
|
||||
MOVW $1, R3 // 38600001
|
||||
MOVW $-1, R4 // 3880ffff
|
||||
MOVW $65535, R5 // 6005ffff
|
||||
MOVW $65536, R6 // 64060001
|
||||
MOVW $65536, R6 // 3cc00001
|
||||
MOVW $-32767, R5 // 38a08001
|
||||
MOVW $-32768, R6 // 38c08000
|
||||
MOVW $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
|
||||
@ -32,7 +32,26 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVW $2147483649, R5 // 6405800060a50001 or 0600800038a00001
|
||||
MOVD $2147483649, R5 // 6405800060a50001 or 0600800038a00001
|
||||
// Hex constant 0xFFFFFFFF80000001
|
||||
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
|
||||
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
|
||||
// Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
|
||||
MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
|
||||
|
||||
// For backwards compatibility, MOVW $const,Rx and MOVWZ $const,Rx assemble identically
|
||||
// and accept the same constants.
|
||||
MOVW $2147483648, R5 // 64058000
|
||||
MOVWZ $-2147483648, R5 // 3ca08000
|
||||
|
||||
// TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
|
||||
// This only captures the MOVD. Should the SLD be appended to the encoding by the test?
|
||||
// Hex constant 0x20004000000
|
||||
MOVD $2199090364416, R5 // 60058001
|
||||
// Hex constant 0xFFFFFE0004000000
|
||||
MOVD $-2198956146688, R5 // 38a08001
|
||||
// TODO: On GOPPC64={power8,power9}, this is preprocessed into MOVD $-1, R5; RLDC R5, $33, $63, R5.
|
||||
// This only captures the MOVD. Should the RLDC be appended to the encoding by the test?
|
||||
// Hex constant 0xFFFFFFFE00000001
|
||||
MOVD $-8589934591, R5 // 38a0ffff or 0602000038a00001
|
||||
|
||||
MOVD 8(R3), R4 // e8830008
|
||||
MOVD (R3)(R4), R5 // 7ca4182a
|
||||
MOVD (R3)(R0), R5 // 7ca0182a
|
||||
@ -164,6 +183,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ADD $-32767, R5, R4 // 38858001
|
||||
ADD $-32768, R6 // 38c68000
|
||||
ADD $-32768, R6, R5 // 38a68000
|
||||
// Hex constant 0xFFFFFFFE00000000
|
||||
ADD $-8589934592, R5 // 3fe0fffe600000007bff83e4600000007cbf2a14 or 0602000038a50000
|
||||
// Hex constant 0xFFFFFFFE00010001
|
||||
ADD $-8589869055, R5 // 3fe0fffe63ff00017bff83e463ff00017cbf2a14 or 0602000138a50001
|
||||
|
||||
//TODO: this compiles to add r5,r6,r0. It should be addi r5,r6,0.
|
||||
// this is OK since r0 == $0, but the latter is preferred.
|
||||
@ -174,6 +197,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ADDEX R3, R5, $3, R6 // 7cc32f54
|
||||
ADDEX R3, $3, R5, R6 // 7cc32f54
|
||||
ADDIS $8, R3 // 3c630008
|
||||
ADD $524288, R3 // 3c630008
|
||||
ADDIS $1000, R3, R4 // 3c8303e8
|
||||
|
||||
ANDCC $1, R3 // 70630001
|
||||
@ -192,6 +216,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ANDCC $1234567, R5, R6 // 641f001263ffd6877fe62839
|
||||
ANDISCC $1, R3 // 74630001
|
||||
ANDISCC $1000, R3, R4 // 746403e8
|
||||
ANDCC $65536000, R3, R4 // 746403e8
|
||||
|
||||
OR $1, R3 // 60630001
|
||||
OR $1, R3, R4 // 60640001
|
||||
@ -207,7 +232,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
OR $-32768, R6, R7 // 3be080007fe73378
|
||||
OR $1234567, R5 // 641f001263ffd6877fe52b78
|
||||
OR $1234567, R5, R3 // 641f001263ffd6877fe32b78
|
||||
ORIS $255, R3, R4
|
||||
OR $2147483648, R5, R3 // 64a38000
|
||||
OR $2147483649, R5, R3 // 641f800063ff00017fe32b78
|
||||
ORIS $255, R3, R4 // 646400ff
|
||||
OR $16711680, R3, R4 // 646400ff
|
||||
|
||||
XOR $1, R3 // 68630001
|
||||
XOR $1, R3, R4 // 68640001
|
||||
@ -223,7 +251,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
XOR $-32768, R6, R7 // 3be080007fe73278
|
||||
XOR $1234567, R5 // 641f001263ffd6877fe52a78
|
||||
XOR $1234567, R5, R3 // 641f001263ffd6877fe32a78
|
||||
XORIS $15, R3, R4
|
||||
XORIS $15, R3, R4 // 6c64000f
|
||||
XOR $983040, R3, R4 // 6c64000f
|
||||
|
||||
// TODO: the order of CR operands don't match
|
||||
CMP R3, R4 // 7c232000
|
||||
@ -233,7 +262,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
CMPB R3,R4,R4 // 7c6423f8
|
||||
CMPEQB R3,R4,CR6 // 7f0321c0
|
||||
|
||||
// TODO: constants for ADDC?
|
||||
ADD R3, R4 // 7c841a14
|
||||
ADD R3, R4, R5 // 7ca41a14
|
||||
ADDC R3, R4 // 7c841814
|
||||
@ -246,6 +274,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
ADDV R3, R4 // 7c841e14
|
||||
ADDVCC R3, R4 // 7c841e15
|
||||
ADDCCC R3, R4, R5 // 7ca41815
|
||||
ADDCCC $65536, R4, R5 // 641f0001600000007cbf2015
|
||||
ADDCCC $65537, R4, R5 // 641f000163ff00017cbf2015
|
||||
ADDME R3, R4 // 7c8301d4
|
||||
ADDMECC R3, R4 // 7c8301d5
|
||||
ADDMEV R3, R4 // 7c8305d4
|
||||
@ -299,6 +329,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
SUBECC R3, R4, R5 // 7ca32111
|
||||
SUBEV R3, R4, R5 // 7ca32510
|
||||
SUBEVCC R3, R4, R5 // 7ca32511
|
||||
SUBC R3, $65536, R4 // 3fe00001600000007c83f810
|
||||
SUBC R3, $65537, R4 // 3fe0000163ff00017c83f810
|
||||
|
||||
MULLW R3, R4 // 7c8419d6
|
||||
MULLW R3, R4, R5 // 7ca419d6
|
||||
@ -393,6 +425,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
EXTSHCC R3, R4 // 7c640735
|
||||
EXTSW R3, R4 // 7c6407b4
|
||||
EXTSWCC R3, R4 // 7c6407b5
|
||||
RLWMI $7, R3, $4026531855, R6 // 50663f06
|
||||
RLWMI $7, R3, $1, R6 // 50663ffe
|
||||
RLWMI $7, R3, $2147483648, R6 // 50663800
|
||||
RLWMI $7, R3, $65535, R6 // 50663c3e
|
||||
RLWMI $7, R3, $16, $31, R6 // 50663c3e
|
||||
RLWMICC $7, R3, $65535, R6 // 50663c3f
|
||||
@ -414,6 +449,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
RLDIMI $0, R4, $7, R6 // 788601cc
|
||||
RLDIMICC $0, R4, $7, R6 // 788601cd
|
||||
RLDC $0, R4, $15, R6 // 78860728
|
||||
RLDC R3, $32, $12, R4 // 7864030a
|
||||
RLDC R3, $8, $32, R4 // 78644028
|
||||
RLDCCC R3, $32, $12, R4 // 7864030b
|
||||
RLDCCC R3, $8, $32, R4 // 78644029
|
||||
RLDCCC $0, R4, $15, R6 // 78860729
|
||||
RLDCL $0, R4, $7, R6 // 78860770
|
||||
RLDCLCC $0, R4, $15, R6 // 78860721
|
||||
|
5
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
5
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
@ -94,6 +94,10 @@ start:
|
||||
|
||||
SUB X6, X5, X7 // b3836240
|
||||
SUB X5, X6 // 33035340
|
||||
SUB $-2047, X5, X6 // 1383f27f
|
||||
SUB $2048, X5, X6 // 13830280
|
||||
SUB $-2047, X5 // 9382f27f
|
||||
SUB $2048, X5 // 93820280
|
||||
|
||||
SRA X6, X5, X7 // b3d36240
|
||||
SRA X5, X6 // 33535340
|
||||
@ -157,6 +161,7 @@ start:
|
||||
ADDW $1, X6 // 1b031300
|
||||
SLLW $1, X6 // 1b131300
|
||||
SRLW $1, X6 // 1b531300
|
||||
SUBW $1, X6 // 1b03f3ff
|
||||
SRAW $1, X6 // 1b531340
|
||||
|
||||
// 5.3: Load and Store Instructions (RV64I)
|
||||
|
@ -38,5 +38,8 @@ TEXT errors(SB),$0
|
||||
SLLIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
|
||||
SRLIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
|
||||
SRAIW $-1, X5, X6 // ERROR "shift amount out of range 0 to 31"
|
||||
|
||||
SD X5, 4294967296(X6) // ERROR "constant 4294967296 too large"
|
||||
SRLI $1, X5, F1 // ERROR "expected integer register in rd position but got non-integer register F1"
|
||||
SRLI $1, F1, X5 // ERROR "expected integer register in rs1 position but got non-integer register F1"
|
||||
FNES F1, (X5) // ERROR "needs an integer register output"
|
||||
RET
|
||||
|
6
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
6
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
@ -419,9 +419,9 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
||||
KMC R2, R6 // b92f0026
|
||||
KLMD R2, R8 // b93f0028
|
||||
KIMD R0, R4 // b93e0004
|
||||
KDSA R0, R8 // b93a0008
|
||||
KMA R6, R2, R4 // b9296024
|
||||
KMCTR R6, R2, R4 // b92d6024
|
||||
KDSA R0, R8 // b93a0008
|
||||
KMA R2, R6, R4 // b9296024
|
||||
KMCTR R2, R6, R4 // b92d6024
|
||||
|
||||
// vector add and sub instructions
|
||||
VAB V3, V4, V4 // e743400000f3
|
||||
|
@ -420,30 +420,6 @@ passing uninitialized C memory to Go code if the Go code is going to
|
||||
store pointer values in it. Zero out the memory in C before passing it
|
||||
to Go.
|
||||
|
||||
# Optimizing calls of C code
|
||||
|
||||
When passing a Go pointer to a C function the compiler normally ensures
|
||||
that the Go object lives on the heap. If the C function does not keep
|
||||
a copy of the Go pointer, and never passes the Go pointer back to Go code,
|
||||
then this is unnecessary. The #cgo noescape directive may be used to tell
|
||||
the compiler that no Go pointers escape via the named C function.
|
||||
If the noescape directive is used and the C function does not handle the
|
||||
pointer safely, the program may crash or see memory corruption.
|
||||
|
||||
For example:
|
||||
|
||||
// #cgo noescape cFunctionName
|
||||
|
||||
When a Go function calls a C function, it prepares for the C function to
|
||||
call back to a Go function. the #cgo nocallback directive may be used to
|
||||
tell the compiler that these preparations are not necessary.
|
||||
If the nocallback directive is used and the C function does call back into
|
||||
Go code, the program will panic.
|
||||
|
||||
For example:
|
||||
|
||||
// #cgo nocallback cFunctionName
|
||||
|
||||
# Special cases
|
||||
|
||||
A few special C types which would normally be represented by a pointer
|
||||
|
@ -94,8 +94,10 @@ func (f *File) ProcessCgoDirectives() {
|
||||
directive := fields[1]
|
||||
funcName := fields[2]
|
||||
if directive == "nocallback" {
|
||||
fatalf("#cgo nocallback disabled until Go 1.23")
|
||||
f.NoCallbacks[funcName] = true
|
||||
} else if directive == "noescape" {
|
||||
fatalf("#cgo noescape disabled until Go 1.23")
|
||||
f.NoEscapes[funcName] = true
|
||||
}
|
||||
}
|
||||
|
109
src/cmd/cgo/internal/test/callback_windows.go
Normal file
109
src/cmd/cgo/internal/test/callback_windows.go
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <windows.h>
|
||||
USHORT backtrace(ULONG FramesToCapture, PVOID *BackTrace) {
|
||||
#ifdef _AMD64_
|
||||
CONTEXT context;
|
||||
RtlCaptureContext(&context);
|
||||
ULONG64 ControlPc;
|
||||
ControlPc = context.Rip;
|
||||
int i;
|
||||
for (i = 0; i < FramesToCapture; i++) {
|
||||
PRUNTIME_FUNCTION FunctionEntry;
|
||||
ULONG64 ImageBase;
|
||||
VOID *HandlerData;
|
||||
ULONG64 EstablisherFrame;
|
||||
|
||||
FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
|
||||
|
||||
if (!FunctionEntry) {
|
||||
// For simplicity, don't unwind leaf entries, which are not used in this test.
|
||||
break;
|
||||
} else {
|
||||
RtlVirtualUnwind(0, ImageBase, ControlPc, FunctionEntry, &context, &HandlerData, &EstablisherFrame, NULL);
|
||||
}
|
||||
|
||||
ControlPc = context.Rip;
|
||||
// Check if we left the user range.
|
||||
if (ControlPc < 0x10000) {
|
||||
break;
|
||||
}
|
||||
|
||||
BackTrace[i] = (PVOID)(ControlPc);
|
||||
}
|
||||
return i;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"internal/testenv"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Test that the stack can be unwound through a call out and call back
|
||||
// into Go.
|
||||
func testCallbackCallersSEH(t *testing.T) {
|
||||
testenv.SkipIfOptimizationOff(t) // This test requires inlining.
|
||||
if runtime.Compiler != "gc" {
|
||||
// The exact function names are not going to be the same.
|
||||
t.Skip("skipping for non-gc toolchain")
|
||||
}
|
||||
if runtime.GOARCH != "amd64" {
|
||||
// TODO: support SEH on other architectures.
|
||||
t.Skip("skipping on non-amd64")
|
||||
}
|
||||
// Only frames in the test package are checked.
|
||||
want := []string{
|
||||
"test._Cfunc_backtrace",
|
||||
"test.testCallbackCallersSEH.func1.1",
|
||||
"test.testCallbackCallersSEH.func1",
|
||||
"test.goCallback",
|
||||
"test._Cfunc_callback",
|
||||
"test.nestedCall.func1",
|
||||
"test.nestedCall",
|
||||
"test.testCallbackCallersSEH",
|
||||
"test.TestCallbackCallersSEH",
|
||||
}
|
||||
pc := make([]uintptr, 100)
|
||||
n := 0
|
||||
nestedCall(func() {
|
||||
n = int(C.backtrace(C.DWORD(len(pc)), (*C.PVOID)(unsafe.Pointer(&pc[0]))))
|
||||
})
|
||||
got := make([]string, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
f := runtime.FuncForPC(pc[i] - 1)
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
fname := f.Name()
|
||||
switch fname {
|
||||
case "goCallback":
|
||||
// TODO(qmuntal): investigate why this function doesn't appear
|
||||
// when using the external linker.
|
||||
continue
|
||||
}
|
||||
// In module mode, this package has a fully-qualified import path.
|
||||
// Remove it if present.
|
||||
fname = strings.TrimPrefix(fname, "cmd/cgo/internal/")
|
||||
if !strings.HasPrefix(fname, "test.") {
|
||||
continue
|
||||
}
|
||||
got = append(got, fname)
|
||||
}
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("incorrect backtrace:\nwant:\t%v\ngot:\t%v", want, got)
|
||||
}
|
||||
}
|
11
src/cmd/cgo/internal/test/cgo_windows_test.go
Normal file
11
src/cmd/cgo/internal/test/cgo_windows_test.go
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build cgo && windows
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCallbackCallersSEH(t *testing.T) { testCallbackCallersSEH(t) }
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <stdio.h>
|
||||
#include "issue4339.h"
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
typedef struct Issue4339 Issue4339;
|
||||
|
||||
struct Issue4339 {
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue8756
|
||||
|
||||
/*
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue8828
|
||||
|
||||
//void foo();
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue9026
|
||||
|
||||
// This file appears in its own package since the assertion tests the
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue9510a
|
||||
|
||||
/*
|
||||
|
@ -1,3 +1,7 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue9510b
|
||||
|
||||
/*
|
||||
|
@ -117,7 +117,8 @@ int add(int x, int y) {
|
||||
|
||||
// escape vs noescape
|
||||
|
||||
#cgo noescape handleGoStringPointerNoescape
|
||||
// TODO(#56378): enable in Go 1.23:
|
||||
// #cgo noescape handleGoStringPointerNoescape
|
||||
void handleGoStringPointerNoescape(void *s) {}
|
||||
|
||||
void handleGoStringPointerEscape(void *s) {}
|
||||
|
@ -1365,3 +1365,35 @@ func TestDeepStack(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSharedObject(t *testing.T) {
|
||||
// Test that we can put a Go c-archive into a C shared object.
|
||||
globalSkip(t)
|
||||
testenv.MustHaveGoBuild(t)
|
||||
testenv.MustHaveCGO(t)
|
||||
testenv.MustHaveBuildMode(t, "c-archive")
|
||||
|
||||
t.Parallel()
|
||||
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo_s.a")
|
||||
os.Remove("libgo_s.h")
|
||||
os.Remove("libgo_s.so")
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo_s.a", "./libgo")
|
||||
out, err := cmd.CombinedOutput()
|
||||
t.Logf("%v\n%s", cmd.Args, out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ccArgs := append(cc, "-shared", "-o", "libgo_s.so", "libgo_s.a")
|
||||
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
||||
t.Logf("%v\n%s", ccArgs, out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ func TestReportsTypeErrors(t *testing.T) {
|
||||
for _, file := range []string{
|
||||
"err1.go",
|
||||
"err2.go",
|
||||
"err5.go",
|
||||
"issue11097a.go",
|
||||
"issue11097b.go",
|
||||
"issue18452.go",
|
||||
|
11
src/cmd/cgo/internal/testerrors/testdata/err5.go
vendored
Normal file
11
src/cmd/cgo/internal/testerrors/testdata/err5.go
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
//line /tmp/_cgo_.go:1
|
||||
//go:cgo_dynamic_linker "/elf/interp"
|
||||
// ERROR MESSAGE: only allowed in cgo-generated code
|
||||
|
||||
func main() {}
|
@ -5,7 +5,8 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
// ERROR MESSAGE: #cgo noescape noMatchedCFunction: no matched C function
|
||||
// TODO(#56378): change back to "#cgo noescape noMatchedCFunction: no matched C function" in Go 1.23
|
||||
// ERROR MESSAGE: #cgo noescape disabled until Go 1.23
|
||||
#cgo noescape noMatchedCFunction
|
||||
*/
|
||||
import "C"
|
||||
|
@ -5,7 +5,6 @@
|
||||
package fortran
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -75,11 +74,18 @@ func TestFortran(t *testing.T) {
|
||||
|
||||
// Finally, run the actual test.
|
||||
t.Log("go", "run", "./testdata/testprog")
|
||||
out, err := exec.Command("go", "run", "./testdata/testprog").CombinedOutput()
|
||||
if err == nil && string(out) != "ok\n" {
|
||||
err = fmt.Errorf("expected ok")
|
||||
var stdout, stderr strings.Builder
|
||||
cmd := exec.Command("go", "run", "./testdata/testprog")
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
t.Logf("%v", cmd)
|
||||
if stderr.Len() != 0 {
|
||||
t.Logf("stderr:\n%s", stderr.String())
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("%s\nOutput:\n%s", err, string(out))
|
||||
t.Errorf("%v\n%s", err, stdout.String())
|
||||
} else if stdout.String() != "ok\n" {
|
||||
t.Errorf("stdout:\n%s\nwant \"ok\"", stdout.String())
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,10 @@ package main
|
||||
|
||||
// int the_answer();
|
||||
import "C"
|
||||
import "os"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func TheAnswer() int {
|
||||
return int(C.the_answer())
|
||||
@ -14,8 +17,8 @@ func TheAnswer() int {
|
||||
|
||||
func main() {
|
||||
if a := TheAnswer(); a != 42 {
|
||||
println("Unexpected result for The Answer. Got:", a, " Want: 42")
|
||||
fmt.Fprintln(os.Stderr, "Unexpected result for The Answer. Got:", a, " Want: 42")
|
||||
os.Exit(1)
|
||||
}
|
||||
println("ok")
|
||||
fmt.Fprintln(os.Stdout, "ok")
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserve d.
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
@ -7,11 +7,14 @@
|
||||
package sanitizers_test
|
||||
|
||||
import (
|
||||
"internal/testenv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLibFuzzer(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
testenv.MustHaveCGO(t)
|
||||
goos, err := goEnv("GOOS")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -8,11 +8,14 @@ package sanitizers_test
|
||||
|
||||
import (
|
||||
"internal/platform"
|
||||
"internal/testenv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMSAN(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
testenv.MustHaveCGO(t)
|
||||
goos, err := goEnv("GOOS")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -633,6 +633,56 @@ modifying or saving the FPCR.
|
||||
Functions are allowed to modify it between calls (as long as they
|
||||
restore it), but as of this writing Go code never does.
|
||||
|
||||
### loong64 architecture
|
||||
|
||||
The loong64 architecture uses R4 – R19 for integer arguments and integer results.
|
||||
|
||||
It uses F0 – F15 for floating-point arguments and results.
|
||||
|
||||
Registers R20 - R21, R23 – R28, R30 - R31, F16 – F31 are permanent scratch registers.
|
||||
|
||||
Register R2 is reserved and never used.
|
||||
|
||||
Register R20, R21 is Used by runtime.duffcopy, runtime.duffzero.
|
||||
|
||||
Special-purpose registers used within Go generated code and Go assembly code
|
||||
are as follows:
|
||||
|
||||
| Register | Call meaning | Return meaning | Body meaning |
|
||||
| --- | --- | --- | --- |
|
||||
| R0 | Zero value | Same | Same |
|
||||
| R1 | Link register | Link register | Scratch |
|
||||
| R3 | Stack pointer | Same | Same |
|
||||
| R20,R21 | Scratch | Scratch | Used by duffcopy, duffzero |
|
||||
| R22 | Current goroutine | Same | Same |
|
||||
| R29 | Closure context pointer | Same | Same |
|
||||
| R30, R31 | used by the assembler | Same | Same |
|
||||
|
||||
*Rationale*: These register meanings are compatible with Go’s stack-based
|
||||
calling convention.
|
||||
|
||||
#### Stack layout
|
||||
|
||||
The stack pointer, R3, grows down and is aligned to 8 bytes.
|
||||
|
||||
A function's stack frame, after the frame is created, is laid out as
|
||||
follows:
|
||||
|
||||
+------------------------------+
|
||||
| ... locals ... |
|
||||
| ... outgoing arguments ... |
|
||||
| return PC | ← R3 points to
|
||||
+------------------------------+ ↓ lower addresses
|
||||
|
||||
This stack layout is used by both register-based (ABIInternal) and
|
||||
stack-based (ABI0) calling conventions.
|
||||
|
||||
The "return PC" is loaded to the link register, R1, as part of the
|
||||
loong64 `JAL` operation.
|
||||
|
||||
#### Flags
|
||||
All bits in CSR are system flags and are not modified by Go.
|
||||
|
||||
### ppc64 architecture
|
||||
|
||||
The ppc64 architecture uses R3 – R10 and R14 – R17 for integer arguments
|
||||
|
Binary file not shown.
@ -8,6 +8,7 @@ import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/src"
|
||||
"fmt"
|
||||
"math"
|
||||
@ -261,12 +262,13 @@ type ABIConfig struct {
|
||||
// Do we need anything more than this?
|
||||
offsetForLocals int64 // e.g., obj.(*Link).Arch.FixedFrameSize -- extra linkage information on some architectures.
|
||||
regAmounts RegAmounts
|
||||
which obj.ABI
|
||||
}
|
||||
|
||||
// NewABIConfig returns a new ABI configuration for an architecture with
|
||||
// iRegsCount integer/pointer registers and fRegsCount floating point registers.
|
||||
func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64) *ABIConfig {
|
||||
return &ABIConfig{offsetForLocals: offsetForLocals, regAmounts: RegAmounts{iRegsCount, fRegsCount}}
|
||||
func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64, which uint8) *ABIConfig {
|
||||
return &ABIConfig{offsetForLocals: offsetForLocals, regAmounts: RegAmounts{iRegsCount, fRegsCount}, which: obj.ABI(which)}
|
||||
}
|
||||
|
||||
// Copy returns config.
|
||||
@ -276,6 +278,11 @@ func (config *ABIConfig) Copy() *ABIConfig {
|
||||
return config
|
||||
}
|
||||
|
||||
// Which returns the ABI number
|
||||
func (config *ABIConfig) Which() obj.ABI {
|
||||
return config.which
|
||||
}
|
||||
|
||||
// LocalsOffset returns the architecture-dependent offset from SP for args and results.
|
||||
// In theory this is only used for debugging; it ought to already be incorporated into
|
||||
// results from the ABI-related methods
|
||||
|
@ -15,7 +15,7 @@ func Init(arch *ssagen.ArchInfo) {
|
||||
arch.LinkArch = &arm.Linkarm
|
||||
arch.REGSP = arm.REGSP
|
||||
arch.MAXWIDTH = (1 << 32) - 1
|
||||
arch.SoftFloat = buildcfg.GOARM == 5
|
||||
arch.SoftFloat = buildcfg.GOARM.SoftFloat
|
||||
arch.ZeroRange = zerorange
|
||||
arch.Ginsnop = ginsnop
|
||||
|
||||
|
@ -289,7 +289,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||
case ssa.OpARMANDconst, ssa.OpARMBICconst:
|
||||
// try to optimize ANDconst and BICconst to BFC, which saves bytes and ticks
|
||||
// BFC is only available on ARMv7, and its result and source are in the same register
|
||||
if buildcfg.GOARM == 7 && v.Reg() == v.Args[0].Reg() {
|
||||
if buildcfg.GOARM.Version == 7 && v.Reg() == v.Args[0].Reg() {
|
||||
var val uint32
|
||||
if v.Op == ssa.OpARMANDconst {
|
||||
val = ^uint32(v.AuxInt)
|
||||
@ -646,7 +646,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||
default:
|
||||
}
|
||||
}
|
||||
if buildcfg.GOARM >= 6 {
|
||||
if buildcfg.GOARM.Version >= 6 {
|
||||
// generate more efficient "MOVB/MOVBU/MOVH/MOVHU Reg@>0, Reg" on ARMv6 & ARMv7
|
||||
genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, 0)
|
||||
return
|
||||
|
@ -23,6 +23,8 @@ type DebugFlags struct {
|
||||
DisableNil int `help:"disable nil checks" concurrent:"ok"`
|
||||
DumpInlFuncProps string `help:"dump function properties from inl heuristics to specified file"`
|
||||
DumpInlCallSiteScores int `help:"dump scored callsites during inlining"`
|
||||
InlScoreAdj string `help:"set inliner score adjustments (ex: -d=inlscoreadj=panicPathAdj:10/passConstToNestedIfAdj:-90)"`
|
||||
InlBudgetSlack int `help:"amount to expand the initial inline budget when new inliner enabled. Defaults to 80 if option not set." concurrent:"ok"`
|
||||
DumpPtrs int `help:"show Node pointers values in dump output"`
|
||||
DwarfInl int `help:"print information about DWARF inlined function creation"`
|
||||
EscapeMutationsCalls int `help:"print extra escape analysis diagnostics about mutations and calls" concurrent:"ok"`
|
||||
@ -34,7 +36,6 @@ type DebugFlags struct {
|
||||
Gossahash string `help:"hash value for use in debugging the compiler"`
|
||||
InlFuncsWithClosures int `help:"allow functions with closures to be inlined" concurrent:"ok"`
|
||||
InlStaticInit int `help:"allow static initialization of inlined calls" concurrent:"ok"`
|
||||
InterfaceCycles int `help:"allow anonymous interface cycles"`
|
||||
Libfuzzer int `help:"enable coverage instrumentation for libfuzzer"`
|
||||
LoopVar int `help:"shared (0, default), 1 (private loop variables), 2, private + log"`
|
||||
LoopVarHash string `help:"for debugging changes in loop behavior. Overrides experiment and loopvar flag."`
|
||||
@ -59,7 +60,8 @@ type DebugFlags struct {
|
||||
PGOInline int `help:"enable profile-guided inlining" concurrent:"ok"`
|
||||
PGOInlineCDFThreshold string `help:"cumulative threshold percentage for determining call sites as hot candidates for inlining" concurrent:"ok"`
|
||||
PGOInlineBudget int `help:"inline budget for hot functions" concurrent:"ok"`
|
||||
PGODevirtualize int `help:"enable profile-guided devirtualization" concurrent:"ok"`
|
||||
PGODevirtualize int `help:"enable profile-guided devirtualization; 0 to disable, 1 to enable interface devirtualization, 2 to enable function devirtualization" concurrent:"ok"`
|
||||
RangeFuncCheck int `help:"insert code to check behavior of range iterator functions" concurrent:"ok"`
|
||||
WrapGlobalMapDbg int `help:"debug trace output for global map init wrapping"`
|
||||
WrapGlobalMapCtl int `help:"global map init wrap control (0 => default, 1 => off, 2 => stress mode, no size cutoff)"`
|
||||
ZeroCopy int `help:"enable zero-copy string->[]byte conversions" concurrent:"ok"`
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user