Go語言是個強類型語言。也就是說Go對類型要求嚴格,不同類型不能進行賦值操作。指針也是具有明確類型的對象,進行嚴格類型檢查。下面的代碼會產生編譯錯誤
package main
import (
"fmt"
)
func main() {
u := uint32(32)
i := int32(1)
fmt.Println(&u, &i) // 打印出地址
p := &i // p 的類型是 *int32
p = &u // &u的類型是 *uint32,於 p 的類型不同,不能賦值
p = (*int32)(&u) // 這種類型轉換語法也是無效的
fmt.Println(p)
}
unsafe 包提供的Pointer方法可以完成這個任務
package main
import (
"fmt"
"unsafe"
)
func main() {
u := uint32(32)
i := int32(1)
fmt.Println(&u, &i)
p := &i
p = (*int32)(&u)
p = (*int32)(unsafe.Pointer(&u))
fmt.Println(p)
}
補充:實際使用中unsafe可用場景很少,稍微復雜一點的結構,比如struct,unsafe根本不能適用,正確的方法還是要靠 type assertion
ps:發現一種用法,看代碼
package main
import (
"fmt"
"text/template"
"unsafe"
)
// MyTemplate 定義和 template.Template 只是形似
type MyTemplate struct {
name string
parseTree *unsafe.Pointer
common *unsafe.Pointer
leftDelim string
rightDelim string
}
func main() {
t := template.New("Foo")
p := (*My<span></span>Template<span></span>)(unsafe.Pointer(t))
p.name = "Bar" // 關鍵在這裡,突破私有成員
fmt.Println(p, t)
}