forked from JohnCGriffin/overflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
123 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# overflow 溢出 | ||
检查 Golang 算术和类型转换中的整数溢出。 | ||
### 安装 | ||
|
||
*这是一份PR被上游合并之前的特殊README。* | ||
|
||
该库从`johncgriffin/overflow`派生而来并添加了无符号整数的算术和整数之间的溢出检测。 | ||
|
||
它经过了良好的测试和基准测试,并通过了由GitHub提供的Workflow代码安全扫描。 | ||
|
||
[![CodeQL](https://github.com/rwxe/overflow/actions/workflows/codeql.yml/badge.svg)](https://github.com/rwxe/overflow/actions/workflows/codeql.yml) | ||
|
||
```sh | ||
go get github.com/rwxe/overflow | ||
``` | ||
|
||
为了兼容旧代码并保持代码简单易读,新的代码仍然不使用泛型,而是使用模板来生成代码。 所以大多数重复代码由`overflow_template.sh`生成。 | ||
|
||
如果您必须更改算法,请在那里更改并通过以下方式重新生成 Go 代码: | ||
```sh | ||
go generate | ||
``` | ||
### 概要 | ||
|
||
#### 算术溢出检测 | ||
```go | ||
package main | ||
|
||
import "fmt" | ||
import "math" | ||
import "github.com/rwxe/overflow" | ||
|
||
func main() { | ||
addend := math.MaxInt64 - 5 | ||
for i := 0; i < 10; i++ { | ||
sum, ok := overflow.Add(addend, i) | ||
fmt.Printf("%v+%v -> (%v,%v)\n", | ||
addend, i, sum, ok) | ||
} | ||
} | ||
``` | ||
输出 | ||
```go | ||
9223372036854775802+0 -> (9223372036854775802,true) | ||
9223372036854775802+1 -> (9223372036854775803,true) | ||
9223372036854775802+2 -> (9223372036854775804,true) | ||
9223372036854775802+3 -> (9223372036854775805,true) | ||
9223372036854775802+4 -> (9223372036854775806,true) | ||
9223372036854775802+5 -> (9223372036854775807,true) | ||
9223372036854775802+6 -> (0,false) | ||
9223372036854775802+7 -> (0,false) | ||
9223372036854775802+8 -> (0,false) | ||
9223372036854775802+9 -> (0,false) | ||
``` | ||
对于 (u)int 类型,提供 (U)Add、(U)Sub、(U)Mul、(U)Div、(U)Quotient 等操作。 | ||
|
||
|
||
#### 类型转换溢出检测 | ||
```go | ||
func main() { | ||
var i uint | ||
for i = math.MaxInt - 5; i <= math.MaxInt+5; i++ { | ||
ret, ok := overflow.UintToInt(i) | ||
fmt.Printf("%v -> (%v,%v)\n", | ||
i, ret, ok) | ||
} | ||
} | ||
``` | ||
输出 | ||
```go | ||
9223372036854775802 -> (9223372036854775802,true) | ||
9223372036854775803 -> (9223372036854775803,true) | ||
9223372036854775804 -> (9223372036854775804,true) | ||
9223372036854775805 -> (9223372036854775805,true) | ||
9223372036854775806 -> (9223372036854775806,true) | ||
9223372036854775807 -> (9223372036854775807,true) | ||
9223372036854775808 -> (-9223372036854775808,false) | ||
9223372036854775809 -> (-9223372036854775807,false) | ||
9223372036854775810 -> (-9223372036854775806,false) | ||
9223372036854775811 -> (-9223372036854775805,false) | ||
9223372036854775812 -> (-9223372036854775804,false) | ||
``` | ||
提供UintToInt、IntToUint、Uint64ToInt32、Int32ToUint64等操作。 | ||
|
||
### 保持冷静并恐慌 | ||
|
||
有充分的证据表明,恐慌是一种不惯用但正确的反应。 如果你相信在算术和转换出现问题后,没有有效的方法可以继续你的程序,你可以使用更简单的 Addp、Mulp、Subp 、Divp、UintToIntp、IntToUintp 版本,它们返回正常结果或恐慌。 | ||
|
||
### 性能考虑 | ||
|
||
与其他语言(例如C++)的整数类型安全库相比,该库使用了一些看似缓慢的操作,例如除法。 但这并不意味着这些方法会很慢,相反,它会比其他语言中的复杂实现更快。 原因是Go不允许强制内联,任何复杂的函数都会被抛弃内联,导致额外的调用开销。 而短函数由于自动内联将快如闪电。 例如,对于无符号64位整数乘法溢出检测,当禁用内联时,除法所需的时间是长乘法的5倍,但允许自动内联后,除法所需的时间是长乘法的1/5。 | ||
|
||
请注意,在业务函数中使用 `//go:noinline` 不会影响本库函数的内联。 只有通过 `-gcflags="-l"` 禁用全局内联才会影响该本库函数的内联。 | ||
|
||
### 基于和依赖 | ||
|
||
该库基于Go的官方编译器实现和语言规范,其定义了整数溢出发生时的行为。 | ||
|
||
### 许可 | ||
|
||
[MIT LICENSE](./LICENSE.md) | ||
|