Треки
/
Go
Go
/
Салабус
/
Нульові значення
Ну

Нульові значення у Go

1 вправа

Про концепцію Нульові значення

У Go кожна змінна має значення. Оголошення змінної без присвоєння значення встановлює для неї нульове значення її типу.

Базові типи, зокрема bool, числові типи та string, мають фіксоване нульове значення:

Тип Нульове значення
bool false
int, int8, int64, etc. 0
float32, float64 0
complex64, complex128 0+0i
string ""

Типи, які посилаються на базові дані, зокрема вказівники, функції, інтерфейси, зрізи, канали та мапи, мають нульове значення nil. Однак масиви та структури ніколи не дорівнюють nil, бо вони зберігають дані безпосередньо, а не посилання на них. Кожен елемент масиву й кожне поле структури ініціалізується нульовим значенням свого типу. Наприклад, var a [3]int створює масив [0, 0, 0].

Оголошення нульових значень

var без початкового значення дає нульове значення для будь-якого типу:

var myBool bool   // false
var mySlice []int // nil
var p Person      // Person{Name: "", Age: 0}

Для структур альтернативою є складений літерал T{}:

myPerson := Person{} // equivalent to var myPerson Person

new(T) повертає вказівник на нульове значення будь-якого типу. Найчастіше його використовують зі структурами, хоча він працює й для базових типів:

p := new(Person) // *Person, pointing to Person{Name: "", Age: 0}
s := new(string) // *string, pointing to ""
i := new(int)    // *int, pointing to 0

Чому нульові значення важливі

У Go нульове значення є природним і корисним початковим станом.

bool типово має значення false, що може слугувати прапорцем:

var done bool // action not done yet
done = true   // action now done

Ціле число типово має значення 0, що може слугувати лічильником:

var count int
count++ // 1
count++ // 2

У структурах кожне поле починається з нульового значення свого типу. Stack з єдиним полем []string уже є робочим порожнім стеком після оголошення. Оскільки append під час виклику на зрізі зі значенням nil виділяє новий базовий масив, конструктор не потрібен:

type Stack struct {
    items []string
}

func (s *Stack) Push(v string) {
    s.items = append(s.items, v)
}

func (s *Stack) IsEmpty() bool {
    return len(s.items) == 0
}

var s Stack
fmt.Println(s.IsEmpty()) // true
s.Push("a") // append allocates a new backing array
fmt.Println(s.IsEmpty()) // false

Робота з nil

Більшість типів із нульовим значенням nil потребують ініціалізації перед використанням, інакше вони спричиняють паніку. Винятком є зріз nil: його можна перебирати, додавати до нього елементи та безпечно передавати до len і cap.

Мапу слід ініціалізувати перед збереженням значення:

var m map[string]int
m["key"] = 1 // panic

Мапу зазвичай ініціалізують двома різними способами:

m1 := make(map[string]int)
m2 := map[string]int{}
m1["key"] = 1 // ok
m2["key"] = 1 // ok

Перевірмо вказівник на nil перед використанням:

var p *int

if p == nil {
    fmt.Println("no value assigned")
    return
}

fmt.Println(*p) // p is not nil

Базові типи завжди містять конкретне значення, тому порівняння їх із nil є помилкою компіляції:

var myString string

if myString == nil {
    // compile error: mismatched types
}
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Нульові значення