Как использовать настраиваемый тип int с диапазоном на ходу?

у меня есть

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*
    }
}

Это дает мне «недопустимую операцию: ... (несовпадающие типы int и DocId)», когда я пытаюсь использовать идентификатор из диапазона в качестве DocId, даже если DocId является int.


person user1244215    schedule 05.10.2012    source источник
comment
Нет, DocId - это тип индекса в массиве документов.   -  person user1244215    schedule 05.10.2012
comment
id gets used as the DocId that it damn well *IS*, за исключением того, что это не так.   -  person zzzz    schedule 05.10.2012
comment
DocId - это целое число, не совсем верно: Go набирается.   -  person Denys Séguret    schedule 05.10.2012


Ответы (2)


Только нетипизированная константа может быть автоматически преобразована в правильный тип.

Вы можете найти примеры, в которых приведение не требуется, например в этой теме, для нетипизированная константа. Из спецификаций:

если один операнд является нетипизированной константой, а другой - нет, константа преобразуется в тип другого операнда

Но здесь range явно присваивает значения итерации соответствующим переменным итерации (i int, T a[i]), что составляет i и int. (из спецификации «для заявления»)

Во всех остальных случаях требуется явное приведение типов.
Раздел "Конверсия" в спецификациях не упоминается «автоматическое» преобразование типов (в отличие от автоматического преобразования интерфейса, которое происходит постоянно: interface{}).

Эта ветка добавляет

type A int
type B int

...

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

По сути, поскольку (почти) все типы уникальны, даже два типа с одинаковым базовым представлением и примитивными операциями не могут быть присвоены без приведения. [...]
Это делает язык типобезопасным, заставляя вас явно указывать компилятору, когда вы хотите, чтобы произошло преобразование.

person VonC    schedule 05.10.2012
comment
range ничего не возвращает, это не функция. Кроме того, как error сюда попали? - person zzzz; 05.10.2012
comment
@jnml Я исправил часть предложения диапазона со ссылкой на спецификацию For Statement) - person VonC; 05.10.2012

Вот еще одна идея, которая может вам понравиться, а может и не понравиться - используйте map, поскольку карты могут иметь ключи настраиваемых типов, в отличие от срезов.

type DocId int

func foo(documents map[DocId]string) {
    for id := range documents {
        // do stuff with id and documents[id]
    }
}
person Nick Craig-Wood    schedule 05.10.2012