此:
[]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)
}
輸出(嘗試在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
根據規範Pointer
可以轉化爲*[]Bar
(再次被轉換爲任何其他指針類型),然後解除引用該指針(*
運算符),因此結果是類型爲[]Bar
的值,如輸出中所示。
輸出(嘗試在Go Playground):
[{1} {2}]
[]main.Bar
注:
引用的unsafe
包DOC:
包不安全包含繞式步驟操作Go程序的安全性。
導入不安全的程序包可能不可移植,且不受Go 1兼容性準則的保護。
這是什麼意思?這意味着你不應該每次使用包usafe
時,它都會讓你的生活更輕鬆。您應該只在特殊情況下使用它,而不使用它會讓您的程序變得非常緩慢和複雜。
在你的程序中,情況並非如此,因爲我提出了一個只用一點重構(Foos
和Bars
爲切片)的工作示例。
unsafe
圍繞Go的類型安全採取措施。這是什麼意思?如果你想改變foos
的類型(例如foos := "trap!"
),你的程序仍然可以編譯和運行,但很可能會發生運行時恐慌。使用usafe
你會失去編譯器的類型檢查。
雖然如果您使用我的其他建議(Foos
和Bars
),則會在編譯時檢測到此類更改/拼寫錯誤。
你實質上是在問如何解決類型系統來優化循環。我認爲['unsafe']包(http://golang.org/pkg/unsafe/)可以讓你做到這一點 – Kos