Это:
[]Bar(foos)
тип conversion. Конверсии имеют конкретные правила в соответствии со спецификацией:
Непостоянного значение x
может быть преобразован в типе T
в любом из этих случаев:
x
является assignable к T
.
x
тип и T
имеют одинаковые базовые типы.
x
тип и T
являются неназванными типами указателей, а их базовые типы указателей имеют одинаковые базовые типы.
x
тип и T
являются целыми или с плавающей точкой.
x
тип и T
являются сложными типами.
x
- целое число или кусочек байтов или рун, а T
- это строковый тип.
x
- это строка, а T
- фрагмент байтов или рун.
Здесь не применяется. Зачем?
Поскольку базовый тип []Foo
не совпадает с базовым типом []Bar
. И значение типа []Foo
не может быть присвоено переменной типа []Bar
, см. Assignability rules here.
Основной тип Foo
такой же, как основной тип Bar
, но то же самое не относится к ломтиков, когда тип элемента является Foo
и Bar
.
Так следующие работы:
type Foo struct{ A int }
type Foos []Foo
type Bars Foos
func main() {
foos := []Foo{Foo{1}, Foo{2}}
bars := Bars(foos)
fmt.Println(bars)
}
Output (попробуйте на Go Playground):
[{1} {2}]
Обратите внимание, что с момента фактического представления памяти Foo
и Bar
одно и то же (так как основной тип Bar
- Foo
), в этом случае с использованием пакета unsafe
вы можете «просмотреть» значение []Foo
в качестве значения []Bar
:
type Foo struct{ A int }
type Bar Foo
func main() {
foos := []Foo{Foo{1}, Foo{2}}
bars := *(*[]Bar)(unsafe.Pointer(&foos))
fmt.Println(bars)
fmt.Printf("%T", bars)
}
Это: *(*[]Bar)(unsafe.Pointer(&foos))
означает, что принимают адрес foos
, преобразующие его unsafe.Pointer
(according to spec все указатели могут быть преобразованы в unsafe.Pointer
), то это Pointer
преобразуется в *[]Bar
(опять же в соответствии со спецификацией Pointer
может преобразуется в любой другой тип указателя), а затем этот указатель разыменовывается (оператор *
), поэтому результатом является значение типа []Bar
, как видно на выходе.
Output (попробуйте на Go Playground):
[{1} {2}]
[]main.Bar
Примечания:
Цитирование пакет док из unsafe
:
Пакет небезопасным содержит операции, что шаг по типу безопасность программ Go.
Пакеты, которые импортируют небезопасные, могут быть не переносимыми и не защищены Руководством по совместимости Go 1.
Что это значит? Это означает, что вы не должны возвращаться к использованию пакета usafe
каждый раз, когда это облегчает вашу жизнь. Вы должны использовать его только в исключительных случаях, когда его не использовать, это сделает вашу программу очень медленной и сложной.
В вашей программе это не так, поскольку я предложил рабочий пример с небольшим рефакторингом (Foos
и Bars
, являющимся срезами).
unsafe
шаги по типу безопасности Go. Что это значит?Если вы измените тип foos
(например, как foos := "trap!"
), ваша программа все равно будет компилироваться и запускаться, но скорее всего произойдет паника. Используя usafe
, вы теряете проверки типов компилятора.
Хотя, если вы используете мое другое предложение (Foos
и Bars
), такие изменения/опечатки обнаруживаются во время компиляции.
Вы, по сути, спрашиваете, как работать с системой типов, чтобы оптимизировать цикл. Я думаю, что пакет ['unsafe'] (http://golang.org/pkg/unsafe/) позволит вам сделать это – Kos