如何在Go中使用自定义的int类型与范围?

huangapple go评论74阅读模式
英文:

How do I use an custom int type with range in go?

问题

我有

type DocId int

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

我如何摆脱显式转换行? DocIds 应该 是索引单个文档的类型。

我想要的更像是:

func foo(documents []String) {
    for id := range documents {
        ... // id被用作它真正是的DocId
    }
}

当我尝试将range中的id用作DocId时,会出现“无效操作:...(类型不匹配int和DocId)”。尽管DocId是int类型。

英文:

I have

type DocId int

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

How do I get rid of the explicit conversion line? DocIds are meant to be the type that indexes individual documents.

What I want is more like:

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

Which gives me 'invalid operation: ... (mismatched types int and DocId)' when I attempt to use the id from range as a DocId, even though DocId is an int.

答案1

得分: 4

只有未指定类型的常量可以自动转换为正确的类型。您可以在这个帖子中找到不需要转换的示例,用于未指定类型的常量。根据规范,如果一个操作数是未指定类型的常量,而另一个操作数不是,则常量将转换为另一个操作数的类型。但是在这里,range明确地将迭代值分配给相应的迭代变量(i int, T a[i]),这使得iint。对于所有其他情况,需要显式转换。规范中的“转换”部分没有提到“自动”类型转换(与自动接口转换相反,后者经常发生:interface{})。这个帖子补充说,基本上,由于(几乎)所有类型都是唯一的,即使具有相同底层表示和原始操作的两个类型也无法进行赋值而不需要转换。这使得语言具有类型安全性,强制您在希望进行转换时明确告诉编译器。

英文:

Only untyped constant can be automatically converted in the right type.

You can find examples where the cast is not needed like in this thread, for untyped constant. From the specs:

> if one operand is an untyped constant and the other operand is not, the constant is converted to the type of the other operand

But here, range explicitly assign iteration values to the corresponding iteration variables (i int, T a[i]), which makes i and int. (from spec "For statement")

For all the other case, an explicit cast is required.
The "Conversion" section of the specs doesn't mention an "automatic" type conversion (as opposed to automatic interface conversion, which happens all the time: interface{}).

This thread adds

type A int
type B int

...

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

> Essentially, since (nearly) all types are unique, even two types with the same underlying representation and primitive operations are unassignable without a cast. [...]
This makes the language type-safe by forcing you to explicitly tell the compiler when you want the conversion to happen.

答案2

得分: 3

这里有另一个你可能喜欢或不喜欢的想法 - 使用map,因为map可以有自定义类型的键,而不像切片那样。

type DocId int

func foo(documents map[DocId]string) {
    for id := range documents {
        // 使用id和documents[id]进行操作
    }
}
英文:

Here is another idea which you may or may not like - use a map since maps can have keys of custom types unlike slices.

type DocId int

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

huangapple
  • 本文由 发表于 2012年10月5日 19:45:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/12745600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定