我正在尝试创建一个代表正数的抽象数据类型:
package m
type positiveNum int
func MakePositiveNum(i int) positiveNum {
if i < 1 { panic("non positive number") }
return positiveNum(i)
}
// some function that expects a positive number
func UsePositiveNum(s positiveNum) {}
以下是一些示例用途:
package main
import "m"
func main() {
pn := m.MakePositiveNum(123)
//i := 1; m.UsePositiveNum(i) // fails as expected because
// int is passed instead of positiveNum
//useInt(pn) // fails because trying to pass positiveNum instead of int
//pn = m.positiveNum(0) // fails as expected because the type is private
m.UsePositiveNum(pn)
}
func UseInt(int) {}
如果将 m.UsePositiveNum(pn)
替换为 m.UsePositiveNum(0)
,它仍然可以编译,绕过正数类型检查。为什么?
最佳答案
这里发生的事情是 0
是 untyped constant 。 this rule about assignability 涵盖了此类常量。 :
A value
x
is assignable to a variable of typeT
("x
is assignable toT
") in any of these cases:
- ...
x
is an untyped constant representable by a value of typeT
.
由于 positiveNum
的基础类型是 int
,它可以表示 0
,因此转换不会发生错误。
@peterSO 的答案提供了一种避免这种隐式转换的方法,因为没有从整数常量到结构体的隐式转换。请注意,它无法防止恶意用户创建 positive.Positive{0}
之类的值,但这通常不是问题。
关于go - 抽象数据类型构造函数可能会被意外绕过?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25598863/