Вказівник #
Вказівник, або покажчик - це елемент даних який визначає розташування іншого елементу даних. У програмі ми часто зберігаємо дані різних типів: цілі числа, числа з рухомою комою, рядки та ін. У комп’ютері дані зберігаються за певними адресами пам’яті. Вказівник зберігає адресу пам’яті де розташовані ці дані.
Оголосити змінну типом вказівника ми можемо за допомогою символа зірочки *
перед вказуванням основного типу:
var intPointer *int // тут ми оголошуємо змінну - вказівник на ціле число
var floatPointer *float64 // вказівник на число з рухомою комою
var stringPointer *string // вказівник на рядок
var structPointer *struct{ // вказівник на структуру
// поля структури
}
Таким чином ми оголошуємо зміні з назвами intPointer
, floatPointer
, stringPointer
, structPointer
типом вказівник на якийсь інший тип.
Давайте поглянемо на повний процес створення змінної вказівника на дані.
var p *int
a := 35 // зміна з цілим числом, на яке ми будемо вказувати
p = &a // отримуємо посилання на дані змінної a, тобто їх адресу
За допомогою символу &
ми отримаємо адресу змінної a
. Якщо ми спробуємо надрукувати вміст змінної p
, ми отримаємо приблизно такий вивід:
fmt.Println(p)
// -----------
// Output:
// 0xc000012180
Ця адреса може бути різною і залежить лише від того яка адреса буде вільною та вибрана операційною системою, та ніяк не залежить від самих даних, на які ми робимо вказівник.
0xc000012180
є шістнадцятковим числом. Ви можете помітити це, оскільки воно починається з 0x
. Адреси пам’яті часто зазначаються в шістнадцятковому форматі. Ви все ще можете виразити це у двійковому форматі (з нулями та одиницями), але це нелегко читати.
Порожнє значення типу вказівник #
Порожнє значення типів вказівник завжди дорівнює nil
. Іншими словами, вказівник, який не містить адреси, дорівнює nil
.
Розіменування #
Змінна-вказівник містить адресу іншої змінної. Що робити, якщо ви хочете отримати значення за адресою? Ви можете використовувати оператор розіменування *
Створімо, наприклад, покажчик на рядок та отримаємо рядок назад:
vat p *string
s := "Hello"
p = &s // тут ми взяли адресу нашого рядку
// а тепер отримуємо дані за нашим вказівником:
s2 = *p
Розіменування/посилання
- З оператором
*
слідкуєте за адресою - З оператором
&
берете адресу
Будьте уважні! Оператор розіменування *
— це той самий символ, який використовується для позначення типу вказівника. *card
може позначати тип вказівника, але також розіменовану змінну вказівника. Уважно проаналізуйте контекст використання, і ви легко розрізните їх.
Якщо ви спробуєте розіменувати порожній вказівник, то ви отримаєте помилку panic: runtime error: invalid memory address or nil pointer dereference
.