package main
import (
"fmt"
"unsafe"
)
func main() {
x := 42
// Обычный указатель
ptr := &x
fmt.Printf("Обычный указатель: %T\n", ptr) // *int
// Небезопасный указатель
unsafePtr := unsafe.Pointer(&x)
fmt.Printf("Небезопасный указатель: %T\n", unsafePtr) // unsafe.Pointer
} package main
import (
"fmt"
"unsafe"
)
type Data struct {
A int32
B int64
}
func main() {
d := Data{A: 10, B: 20}
// unsafe.Pointer - универсальный указатель на любой тип
ptr := unsafe.Pointer(&d)
// unsafe.Sizeof - размер типа в байтах
size := unsafe.Sizeof(d)
fmt.Printf("Размер структуры: %d байт\n", size)
// unsafe.Alignof - требование по выравниванию
align := unsafe.Alignof(d)
fmt.Printf("Выравнивание структуры: %d байт\n", align)
// unsafe.Offsetof - смещение поля в структуре
offset := unsafe.Offsetof(d.B)
fmt.Printf("Смещение поля B: %d байт\n", offset)
} package main
import (
"fmt"
"unsafe"
)
func main() {
var x int64 = 42
var f float64 = 3.14
// unsafe.Pointer может хранить адрес любого типа
var ptr unsafe.Pointer
ptr = unsafe.Pointer(&x)
fmt.Printf("Указатель на int64: %p\n", ptr)
ptr = unsafe.Pointer(&f)
fmt.Printf("Указатель на float64: %p\n", ptr)
} package main
import (
"fmt"
"unsafe"
)
func main() {
x := int64(42)
// ✅ Правильно: преобразование туда и обратно в одном выражении
ptr := (*int32)(unsafe.Pointer(&x))
// ❌ Неправильно: хранение uintptr в переменной
// Между этими двумя строками может сработать GC и переместить x!
addr := uintptr(unsafe.Pointer(&x)) // опасно
ptr2 := (*int64)(unsafe.Pointer(addr)) // может указывать не туда
fmt.Println(*ptr2) // может привести к панике или неверным данным
} package main
import (
"fmt"
"unsafe"
)
func main() {
// Преобразование float64 в биты (uint64)
f := 3.14159
bits := *(*uint64)(unsafe.Pointer(&f))
fmt.Printf("float64: %f\n", f)
fmt.Printf("Биты в hex: %#x\n", bits)
fmt.Printf("Биты в bin: %064b\n", bits)
// Обратное преобразование
f2 := *(*float64)(unsafe.Pointer(&bits))
fmt.Printf("Обратно в float64: %f\n", f2)
} package main
import (
"fmt"
"unsafe"
)
// Преобразование string в []byte без копирования
func stringToBytes(s string) []byte {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
// Преобразование []byte в string без копирования
func bytesToString(b []byte) string {
return unsafe.String(&b[0], len(b))
}
func main() {
str := "Hello, World!"
// Обычный способ - копирует данные
bytes1 := []byte(str)
fmt.Printf("С копированием: %s\n", bytes1)
// Через unsafe - не копирует
bytes2 := stringToBytes(str)
fmt.Printf("Без копирования: %s\n", bytes2)
} package main
import (
"fmt"
"unsafe"
)
// Внутреннее представление строки в Go
type StringHeader struct {
Data uintptr // указатель на массив байт
Len int // длина строки
}
func main() {
str := "Hello, World!"
// Получаем доступ к внутренней структуре строки
header := (*StringHeader)(unsafe.Pointer(&str))
fmt.Printf("Строка: %s\n", str)
fmt.Printf("Адрес данных: %#x\n", header.Data)
fmt.Printf("Длина: %d\n", header.Len)
// Можно прочитать байты напрямую по адресу
firstByte := *(*byte)(unsafe.Pointer(header.Data))
fmt.Printf("Первый байт: %c (код: %d)\n", firstByte, firstByte)
} package main
import (
"fmt"
"unsafe"
)
type Point struct {
X int32
Y int32
Z int32
}
func main() {
p := Point{X: 10, Y: 20, Z: 30}
// Получаем указатель на начало структуры
basePtr := uintptr(unsafe.Pointer(&p))
// Вычисляем адреса полей через смещения
xPtr := (*int32)(unsafe.Pointer(basePtr + 0)) // X на смещении 0
yPtr := (*int32)(unsafe.Pointer(basePtr + 4)) // Y на смещении 4
zPtr := (*int32)(unsafe.Pointer(basePtr + 8)) // Z на смещении 8
fmt.Printf("X: %d, Y: %d, Z: %d\n", *xPtr, *yPtr, *zPtr)
// Изменяем через указатели
*yPtr = 100
fmt.Printf("После изменения Y: %+v\n", p)
} package main
import (
"fmt"
"unsafe"
)
type Data struct {
A int8 // 1 байт
B int64 // 8 байт
C int32 // 4 байта
}
func main() {
var d Data
fmt.Printf("Размер Data: %d байт\n", unsafe.Sizeof(d))
fmt.Printf("Смещение A: %d\n", unsafe.Offsetof(d.A))
fmt.Printf("Смещение B: %d\n", unsafe.Offsetof(d.B))
fmt.Printf("Смещение C: %d\n", unsafe.Offsetof(d.C))
// Доступ к полю B через смещение
d.B = 42
bPtr := (*int64)(unsafe.Pointer(
uintptr(unsafe.Pointer(&d)) + unsafe.Offsetof(d.B),
))
fmt.Printf("Значение B через указатель: %d\n", *bPtr)
} Размер Data: 16 байт
Смещение A: 0
Смещение B: 8
Смещение C: 16 package main
import (
"fmt"
"runtime"
"weak"
)
type Resource struct {
ID int
Data string
}
func main() {
// Создаём объект
res := &Resource{ID: 1, Data: "Important data"}
// Создаём слабую ссылку
weakRef := weak.Make(res)
fmt.Println("Объект создан")
fmt.Printf("Через сильную ссылку: %+v\n", res)
fmt.Printf("Через слабую ссылку: %+v\n", weakRef.Value())
// Удаляем сильную ссылку
res = nil
// Принудительно запускаем GC
runtime.GC()
// Слабая ссылка больше не работает
if weakRef.Value() == nil {
fmt.Println("Объект был удалён сборщиком мусора")
}
} type Cache struct {
items map[string]weak.Pointer[*CachedItem]
}