Покажчики корисні з кількох причин. Покажчики дозволяють контролювати розташування пам'яті (впливає на ефективність кеш-пам'яті процесора). У Go ми можемо визначити структуру, де всі члени перебувають у суміжній пам'яті:
type Point struct {
x, y int
}
type LineSegment struct {
source, destination Point
}
У цьому випадку Point
структури вбудовані в LineSegment
структуру. Але не завжди можна вбудувати дані безпосередньо. Якщо ви хочете підтримувати такі структури, як двійкові дерева або зв’язаний список, тоді вам потрібно підтримувати якийсь вказівник.
type TreeNode {
value int
left *TreeNode
right *TreeNode
}
Java, Python і т.д. не мають цієї проблеми, оскільки вона не дозволяє вбудовувати складені типи, тому немає необхідності синтаксично розрізняти вбудовування та вказівку.
Проблеми зі структурами Swift / C # вирішені за допомогою покажчиків Go
Можливою альтернативою для того, щоб зробити те саме, є розмежування struct
та class
як це роблять C # та Swift. Але це має обмеження. Хоча зазвичай можна вказати, що функція приймає структуру як inout
параметр, щоб уникнути копіювання структури, це не дозволяє зберігати посилання (покажчики) на структури. Це означає, що ви ніколи не можете розглядати структуру як еталонний тип, коли вважаєте це корисним, наприклад, для створення розподільника пулу (див. Нижче).
Спеціальний розподільник пам'яті
Використовуючи покажчики, ви також можете створити власний розподільник пулу (це дуже спрощено, видалено безліч перевірок, щоб просто показати принцип):
type TreeNode {
value int
left *TreeNode
right *TreeNode
nextFreeNode *TreeNode; // For memory allocation
}
var pool [1024]TreeNode
var firstFreeNode *TreeNode = &pool[0]
func poolAlloc() *TreeNode {
node := firstFreeNode
firstFreeNode = firstFreeNode.nextFreeNode
return node
}
func freeNode(node *TreeNode) {
node.nextFreeNode = firstFreeNode
firstFreeNode = node
}
Поміняйте місцями два значення
Вказівники також дозволяють реалізувати swap
. Тобто обмін значеннями двох змінних:
func swap(a *int, b *int) {
temp := *a
*a = *b
*b = temp
}
Висновок
Java ніколи не могла повністю замінити C ++ для системного програмування в таких місцях, як Google, частково тому, що продуктивність не може бути налаштована на однакові показники через відсутність можливості контролю розташування та використання пам'яті (помилки кешу суттєво впливають на продуктивність). Go має на меті замінити C ++ у багатьох областях, тому потребує підтримки вказівників.