ПРОДВИНУТЬСЯ
Что такое unsafe.Pointer или uintptr?
unsafe.Pointer
, uintptr
кажутся многим разработчикам Go полной черной магией. И надо признать, они действительно волшебные, позвольте мне показать вам пример…
unsafe.Pointer
, uintptr
кажутся многим разработчикам Go полной черной магией. Мы часто просто используем их как специальные заклинания для пакетов, не понимая, как они работают «под капотом».
И надо признать, они действительно волшебные, позвольте мне показать вам пример того, как я могу использовать небезопасные указатели, чтобы омолодить человека.
type Person struct { Name string age int } func main() { person := Person{Name: "John", age: 30} // Cast name to unsafe pointer namePtr := unsafe.Pointer(&person.Name) nameSize := unsafe.Sizeof(person.Name) p := (*int)(unsafe.Add(namePtr, nameSize)) *p = 10 fmt.Println(person) // {John 10} }
Проделав некоторые небезопасные математические вычисления с указателями, я могу изменить частное поле age
через общедоступное поле Name
. Этот подход совершенно неинтуитивен, но он работает, меняя возраст Джона с 30 на 10.
Понимание того, как безопасно использовать небезопасные указатели, позволяет создавать мощные функциональные возможности.
Первый взгляд на небезопасную упаковку
Помимо unsafe.Pointer
, этот пакет предоставляет нам несколько функций, предоставляющих низкоуровневую информацию, позволяющую нам лучше понять внутреннюю структуру типа.
небезопасно.Alignof
Выравнивание — это концепция, пришедшая из низкоуровневого программирования. Она возвращает необходимое выравнивание типа, а расположение памяти может влиять на производительность нашего приложения.
Например, int32
имеет выравнивание в 4 байта. Выравнивание структуры зависит от поля с наибольшим выравниванием:
type Person struct { Name string age int } func main() { var i int32 = 1 var s [3]int8 = [3]int8{1, 2, 3} var p Person = Person{"Bob", 20} fmt.Println("aligno(int32) =", unsafe.Alignof(i)) fmt.Println("alignof([]int8) =", unsafe.Alignof(s)) fmt.Println("alignof(Person) =", unsafe.Alignof(p)) } // aligno(int32) = 4 // alignof([3]int8) = 1 // alignof(Person) = 8