【发布时间】:2014-09-01 04:31:21
【问题描述】:
我正在尝试创建一个表示正数的抽象数据类型:
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),它仍然可以编译,绕过正数类型检查。为什么?
【问题讨论】:
-
因为
int.. 的值为零,因此positiveNum.. 为0。 -
如果人们通过文字创建你的类型是不安全的,那么就不要导出你的类型,只导出它满足的接口;
compress/bzip2通过返回io.Reader来执行类似的操作。否则,Go 风格对公开数据是开放的,不像 C++ 等;像http.Server这样的标准库类型可以做到这一点。如您所见,试图在 Go 中遵循 C++ 规则并不顺利。 Go 实际上是一种 style 和 set of conventions,而不仅仅是一种语言,所以如果你想学习它,那就学习整个东西。 -
它没有被导出。第 3 行:
type positiveNum int。小写表示不导出,对吧? -
啊,注意,我误解了你的问题,它比我想象的更有趣(詹姆斯和彼得的回答实际上回应了你的问题,不像我的评论)。通常来说,将您的类型与不是通过您的函数的访问隔离开来的一种方法是遵循
compress/bzip2的示例并返回一个接口而不是您在内部表示类型的任何内容。 peterSO 的方式看起来也不错。
标签: go abstract-data-type