Como usar unsafe.Pointer na programação da linguagem Go em tempo de execução?

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á mconvertido 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 interfacevazios

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 interfacea 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 efacetipos para receber tipos e tipos de dados e, em seguida, buscamos e dataconvertemos 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:linknamePrecisamos de runtime.mapuma mapiterinitfunçã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

  1. reflect (código oficial da biblioteca src/reflect)
  2. reflect2 (referido como a biblioteca json-iterator/go mais rápida para serializar json em go)

Acho que você gosta

Origin juejin.im/post/7087071105835335716
Recomendado
Clasificación