Преобразование между указателями
Преобразование между указателями разных типов в Go выполняется
с помощью типа unsafe.Pointer. Это специальный тип,
который позволяет обойти систему типов Go и выполнять
преобразования между указателями на разные типы данных.
unsafe.Pointer может быть преобразован в указатель
любого типа и обратно, но использование этого механизма
требует особой осторожности, так как он может привести
к неожиданному поведению программы.
Синтаксис
unsafe.Pointer(&var)
Пример
Давайте преобразуем указатель на int в указатель
на float64 с помощью unsafe.Pointer:
package main
import (
"fmt"
"unsafe"
)
func main() {
num := 42
intPtr := &num
floatPtr := (*float64)(unsafe.Pointer(intPtr))
fmt.Printf("int: %d, float: %f\n", num, *floatPtr)
}
Результат выполнения кода:
"int: 42, float: 0.000000"
В результате мы получили указатель на float64,
который указывает на ту же область памяти, что и
исходный указатель на int. Однако значение
интерпретируется по-другому, поэтому результат
может быть неожиданным.
Пример
Давайте преобразуем указатель на int в указатель
на int64 и обратно:
package main
import (
"fmt"
"unsafe"
)
func main() {
num := 100
intPtr := &num
int64Ptr := (*int64)(unsafe.Pointer(intPtr))
fmt.Printf("int64: %d\n", *int64Ptr)
newIntPtr := (*int)(unsafe.Pointer(int64Ptr))
fmt.Printf("int: %d\n", *newIntPtr)
}
Результат выполнения кода:
"int64: 100"
"int: 100"
При преобразовании указателя на int в указатель
на int64 мы получаем доступ к тем же данным,
но интерпретируемым как 64-битное целое число.
Обратное преобразование восстанавливает исходный тип.
Пример
Давайте используем unsafe.Pointer для работы
со структурой разных типов:
package main
import (
"fmt"
"unsafe"
)
type User struct {
ID int
Name string
}
type Raw struct {
ID int
Name string
}
func main() {
user := User{ID: 1, Name: "John"}
userPtr := &user
rawPtr := (*Raw)(unsafe.Pointer(userPtr))
fmt.Printf("Raw: %+v\n", *rawPtr)
}
Результат выполнения кода:
"Raw: {ID:1 Name:John}"
Мы можем преобразовывать указатели на структуры с одинаковым расположением полей в памяти, даже если имена типов различаются.
Смотрите также
-
функцию
преобразование строки в байтовый слайс,
которая преобразует строку в байтовый слайс -
функцию
преобразование строки в руны,
которая преобразует строку в слайс рун -
функцию
неявное преобразование типов,
которая выполняется автоматически -
функцию
преобразование именованных типов,
которая выполняется между пользовательскими типами