Вказівник

Вказівник #

Вказівник, або покажчик - це елемент даних який визначає розташування іншого елементу даних. У програмі ми часто зберігаємо дані різних типів: цілі числа, числа з рухомою комою, рядки та ін. У комп’ютері дані зберігаються за певними адресами пам’яті. Вказівник зберігає адресу пам’яті де розташовані ці дані.

Pointer

Оголосити змінну типом вказівника ми можемо за допомогою символа зірочки * перед вказуванням основного типу:

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

Pointer And Data Розіменування/посилання

  • З оператором *слідкуєте за адресою
  • З оператором &берете адресу

Будьте уважні! Оператор розіменування *— це той самий символ, який використовується для позначення типу вказівника. *cardможе позначати тип вказівника, але також розіменовану змінну вказівника. Уважно проаналізуйте контекст використання, і ви легко розрізните їх.

Якщо ви спробуєте розіменувати порожній вказівник, то ви отримаєте помилку panic: runtime error: invalid memory address or nil pointer dereference.