【问题标题】:How do I use an custom int type with range in go?如何在 go 中使用带范围的自定义 int 类型?
【发布时间】:2012-09-26 13:42:48
【问题描述】:

我有

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 时,即使 DocId 是 int,这会给我“无效操作:...(不匹配的 int 和 DocId 类型)”。

【问题讨论】:

  • 不,DocId 是文档数组的索引类型。
  • id gets used as the DocId that it damn well *IS*,但不是。
  • "DocId is an int" 不完全正确:Go 是键入的。

标签: type-conversion go


【解决方案1】:

只有无类型的常量才能自动转换为正确的类型。

您可以找到不需要类型转换的示例,例如 in this thread,用于无类型常量。来自the specs

如果一个操作数是无类型常量而另一个操作数不是,则将常量转换为另一个操作数的类型

但是在这里,range 显式地将迭代值分配给相应的迭代变量(i int, T a[i]),这使得iint。 (来自规范“For statement”)

对于所有其他情况,需要显式转换。
规范的“Conversion”部分没有提到“自动”类型转换(与自动 interface 转换相反,这种转换一直在发生:interface{})。

This thread 补充

type A int
type B int

...

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

本质上,由于(几乎)所有类型都是唯一的,因此即使是具有相同底层表示和原始操作的两种类型,如果没有强制转换,也无法分配。 [...]
这通过强制您明确告诉编译器何时发生转换,从而使语言类型安全。

【讨论】:

  • range 不会“返回”任何东西,它不是函数。还有,error 是怎么参与进来的?
  • @jnml 我修复了“范围条款”部分,参考了“For Statement”规范)
【解决方案2】:

这是您可能喜欢也可能不喜欢的另一个想法 - 使用 map,因为地图可以具有与切片不同的自定义类型的键。

type DocId int

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

【讨论】:

    猜你喜欢
    • 2011-08-28
    • 1970-01-01
    • 2015-01-06
    • 2013-08-24
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多