Go language big factory programação inseguro ponteiro inseguro
Converta a estrutura de dados paraunsafe.Pointer
func Unsafe1() {
var m = map[int]int{
2: 10086,
3: 10087,
}
pointer := unsafe.Pointer(&m)
fmt.Println(*(*map[int]int)(pointer))
}
复制代码
Saída:
mapa[2:10086 3:10087]
Aqui ele será m
convertido para unsafe.Pointer e, em seguida, iremos convertê-lo manualmente de volta ( (*map[int]int)(pointer))
) e, em seguida, desreferenciá-lo para retirar o conteúdo de dentro.
Encontre a especificidade dos tipos de interface interface
vazios
func Unsafe2() {
var m = map[int]int{
2: 10086,
3: 10087,
}
var i = func(v any) {//ps:笔者这里用1.18的版本,用了关键字`any`替换
pointer := unsafe.Pointer(&v)
fmt.Println(*(*map[int]int)(pointer))
}
i(&m)
}
复制代码
Ao executar este código, ele não será tão normal quanto o código do Unsafe1 , mas uma mensagem de erro anormal Saída:
endereço de falha inesperado 0x225d erro fatal: falha [sinal SIGSEGV: código de violação de segmentação=0x1 addr=0x225d pc=0x100d4c0]
goroutine 1 [running]: runtime.throw({0x10a1a5d?, 0x1741118?) /Users/gre/Go/go1.18/src/runtime/panic.go:992 +0x71 fp=0xc000092a20 sp=0xc0000929f0 pc=0x102f411 runtime .sigpanic() ...
Isso envolve interface
a lógica de conversão de tipo do design de interface de interface eface
Simplificando, nossa estrutura é convertida em tipo no processo de passagem de parâmetros, portanto, não temos como converter diretamente de volta para nossos dados.
Então o que deveríamos fazer?
func Unsafe3() {
var m = map[int]int{
2: 10086,
3: 10087,
}
var i = func(v any) {
type eface struct {
rtype unsafe.Pointer
data unsafe.Pointer
}
pointer := (*eface)(unsafe.Pointer(&v))
fmt.Println(*(*map[int]int)(pointer.data))
}
i(&m)
}
复制代码
Saída:
mapa[2:10086 3:10087]
Definimos eface
tipos para receber tipos e tipos de dados e, em seguida, buscamos e data
convertemos os dados de que precisamos.
De um modo geral, os desenvolvedores não são solicitados a especificar as informações de tipo de cada dado para decodificar, mas são implementados refletindo a estrutura original.
func Unsafe4() {
var m = map[int]int{
2: 10086,
3: 10087,
}
var (
pointer = unsafe.Pointer(&m)
value1 = reflect.ValueOf(&m)
ptrRType = *(*unsafe.Pointer)(unsafe.Pointer(&value1))
)
var packTAny = func(rtype unsafe.Pointer, data unsafe.Pointer) any {
type eface struct {
rtype unsafe.Pointer
data unsafe.Pointer
}
var i interface{}
e := (*eface)(unsafe.Pointer(&i))
e.rtype = rtype
e.data = data
return i
}
face := packTAny(ptrRType, pointer)
m2 := (face).(*map[int]int)
fmt.Println(*m2)
}
复制代码
Saída:
mapa[2:10086 3:10087]
Como o programa Go analisa a estrutura em tempo de execução
//go:noescape
//go:linkname mapiterinit reflect.mapiterinit
func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer, it *hiter)
//go:noescape
//go:linkname mapiternext reflect.mapiternext
func mapiternext(it *hiter)
func Unsafe5() {
var m = map[int]int{
2: 10086,
3: 10087,
}
var (
value = *(*unsafe.Pointer)(unsafe.Pointer(&m))
value1 = reflect.ValueOf(m)
ptrRType = *(*unsafe.Pointer)(unsafe.Pointer(&value1))
it hiter
)
mapiterinit(ptrRType, value, &it)
for {
key := it.key
elem := it.value
if key == nil {
return
}
fmt.Println(*((*int64)(key)))
fmt.Println(*((*int64)(elem)))
mapiternext(&it)
}
}
复制代码
Saída:
mapa[2:10086 3:10087] 2 10086 3 10087
go:linkname
Precisamos de runtime.map
uma mapiterinit
função para vincular, que pode ser importada e executada em tempo de compilação.
Você pode aprender alguns outros conceitos de refletir e inseguro aqui