Ir idioma gran fábrica programación inseguro puntero inseguro
Convertir la estructura de datos aunsafe.Pointer
func Unsafe1() {
var m = map[int]int{
2: 10086,
3: 10087,
}
pointer := unsafe.Pointer(&m)
fmt.Println(*(*map[int]int)(pointer))
}
复制代码
Producción:
mapa[2:10086 3:10087]
Aquí se m
convertirá en unsafe.Pointer, y luego lo volveremos a convertir manualmente ( (*map[int]int)(pointer))
), y luego lo desreferenciaremos para eliminar el contenido que contiene.
Encuentre la especificidad de los tipos de interfaz interface
vacíos
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)
}
复制代码
Cuando ejecute este código, no será tan normal como el código de Unsafe1 , sino un mensaje de error anormal Salida:
dirección de falla inesperada 0x225d error fatal: falla [señal SIGSEGV: código de violación de segmentación = 0x1 addr = 0x225d pc = 0x100d4c0]
goroutine 1 [en ejecución]: runtime.throw({0x10a1a5d?, 0x1741118?}) /Users/gre/Go/go1.18/src/runtime/panic.go:992 +0x71 fp=0xc000092a20 sp=0xc0000929f0 pc=0x102f411 tiempo de ejecución .sigpanic() ...
Esto implica interface
la lógica de conversión de tipo de Interfaz diseño de interfaz eface
En pocas palabras, nuestra estructura se convierte en tipo en el proceso de pasar parámetros, por lo que no tenemos forma de volver a convertir directamente a nuestros datos.
¿Entonces, qué debemos hacer?
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)
}
复制代码
Producción:
mapa[2:10086 3:10087]
Definimos eface
tipos para recibir tipos y tipos de datos, y luego buscamos y data
convertimos los datos que necesitamos.
En términos generales, a los desarrolladores no se les pide que especifiquen el tipo de información de cada dato a decodificar, sino que se implementan reflejando la estructura 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)
}
复制代码
Producción:
mapa[2:10086 3:10087]
Cómo el programa Go analiza la estructura en tiempo de ejecución
//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)
}
}
复制代码
Producción:
mapa[2:10086 3:10087] 2 10086 3 10087
go:linkname
Necesitamos runtime.map
una mapiterinit
función para vincular, que se puede importar y ejecutar en tiempo de compilación.
Puede aprender algunos otros conceptos de reflexión e inseguridad aquí