如何在Go语言中使用带有范围的自定义整数类型?

3

我有

type DocId int

func foo(documents []String) {
    for i := range documents {
        id := DocId(i)
        ...
    }
}

如何去掉显式转换行?DocIds应该是用于索引单个文档的类型。

我想要的更像是:

func foo(documents []String) {
    for id := range documents {
        ... // id gets used as the DocId that it damn well *IS*
    }
}

当我试图使用来自range的id作为DocId时,它会给我“无效操作:...(类型不匹配int和DocId)”,即使DocId是一个int。

不,DocId是索引到文档数组的类型。 - user1244215
id被用作文档ID,虽然它看起来像是这样,但实际上并不是。 - zzzz
"DocId是一个int"并不完全正确:Go是有类型的。 - Denys Séguret
2个回答

4
只有未命名常量可以自动转换为正确的类型。您可以在此线程中找到不需要转换的示例,适用于未命名常量。根据规范
如果一个操作数是未命名常量,而另一个操作数不是,则该常量将转换为另一个操作数的类型。
但是,在这里,range显式地将迭代值分配给相应的迭代变量(i int, T a[i]),使得iint。(来自规范"For statement")
对于所有其他情况,都需要显式转换。规范的"Conversion"部分没有提到"自动"类型转换(相对于自动接口转换,后者经常发生:interface{})。 此线程添加了一些内容。
type A int
type B int

...

var a A = 5
var b B = a    // Compiler ERROR!!!!!!

基本上,由于(几乎)所有类型都是唯一的,即使是具有相同基础表示和原始操作的两种类型,也无法直接赋值而不进行强制转换。[...] 这使得该语言通过强制您在需要进行转换时明确地告诉编译器而实现类型安全。

range并不会“返回”任何东西,它不是一个函数。另外,这里怎么涉及到了error - zzzz
1
@jnml,我修复了“range clause”部分,并参考了“For Statement”规范。 - VonC

3

这里有另一个你可能喜欢或者不喜欢的想法 - 使用 map,因为 map 可以使用自定义类型作为键,而 slice 则不行。

type DocId int

func foo(documents map[DocId]string) {
    for id := range documents {
        // do stuff with id and documents[id]
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接