Skip to content
This repository has been archived by the owner on Dec 5, 2021. It is now read-only.

Latest commit

 

History

History
757 lines (560 loc) · 17.1 KB

03-functions.md

File metadata and controls

757 lines (560 loc) · 17.1 KB

Тест 3. Функции. Ссылочные типы

  1. Что выведет код?

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	s := "abc"
    	modify(s)
    	fmt.Println(s)
    }
    
    func modify(a string) {
    	a[0] = '3'
    }
    • "3bc"
    • "abc"
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • "3bc"
    • "abc"
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Строки иммутабельны. Поэтому код, модифицирующий элемент строки, не пройдет компиляцию

  2. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var s []byte = "abc"
        modify(s)
        fmt.Println(s)
    }
    
    func modify(a []byte) {
        a[0] = '3'
    }
    • "3bc"
    • "abc"
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • "3bc"
    • "abc"
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Строку можно преобразовать в слайс байтов. Но это преобразование должно быть явным - []byte("abc")

    Поскольку это преобразование отсутствует, код не скомпилируется.

  3. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        s := []byte("abc")
        modify(s)
        fmt.Println(string(s))
    }
    
    func modify(a []byte) {
        a[0] = '3'
    }
    • "3bc"
    • "abc"
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • "3bc"
    • "abc"
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    В отличие от string, элементы []byte можно модифицировать. Поскольку []byte является ссылочным типом, то изменения внутри функции modify отобразатся на элементах слайса s.

    Обозначение '3' означает символьную константу. Она может выступать как byte или как rune. В данном случае символьная константа интерпретируется как byte.

  4. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var m map[string]int
        modify(m)
        fmt.Println(m)
    }
    
    func modify(m map[string]int) {
        m["one"] = 1
    }
    • map[]
    • map[one:1]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • map[]
    • map[one:1]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Zero-value для map[string]int - это nil. При попытке записи в элемент nil-словаря произойдет паника panic: assignment to entry in nil map

  5. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var m map[string]int
        modify(m)
        fmt.Println(m)
    }
    
    func modify(m map[string]int) {
        m = map[string]int{"one": 1}
    }
    • map[]
    • map[one:1]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • map[]
    • map[one:1]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Zero-value для map[string]int - это nil. Внутри функции modify мы заменяем m на проинизиализированный словарь.

    Но поскольку m внутри функции modify - это всего лишь копия внешней переменной m, то проинициализированный словарь уничтожится сразу после выхода из функции.

    В результате в переменной m внутри функции main останется nil, который будет выведен как map[]

  6. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        m := map[string]int{}
        modify(m)
        fmt.Println(m)
    }
    
    func modify(m map[string]int) {
        m["one"] = 1
    }
    • map[]
    • map[one:1]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • map[]
    • map[one:1]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    map является ссылочным типом. Поэтому при попытке расширить копию m мы де-факто меняем и оригинальное значение m тоже.

  7. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var b bool
        modify(b)
        fmt.Println(b)
    }
    
    func modify(b bool) {
        b = true
    }
    • false
    • true
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • false
    • true
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    bool не является ссылочным типом. Внутри modify мы изменяем копию аргумента, которая будет уничтожена сразу после выхода.

  8. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var b bool
        modify(&b)
        fmt.Println(b)
    }
    
    func modify(b *bool) {
        b = true
    }
    • false
    • true
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • false
    • true
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    В b внутри modify хранится указатель. А мы пытаемся в эту переменную вместо указателя записать значение.

    Для записи значения по указателю следует использовать следующий синтаксис - *b = true

  9. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var b bool
        modify(&b)
        fmt.Println(b)
    }
    
    func modify(b *bool) {
        *b = true
    }
    • false
    • true
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • false
    • true
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Мы модифицируем значение переменной b из функции main по указателю.

  10. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var b *bool
        modify(b)
        fmt.Println(b)
    }
    
    func modify(b *bool) {
        *b = true
    }
    • false
    • true
    • <nil>
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • false
    • true
    • <nil>
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Zero-value для указателя - это nil. При попытке записать значение в *b, произойдет разыменовывание nil-указателя, что приведет к панике panic: runtime error: invalid memory address or nil pointer dereference

  11. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var b *bool
        modify(b)
        fmt.Println(b)
    }
    
    func modify(b *bool) {
        if b == nil {
            b = make(bool)
        }
    
        *b = true
    }
    • false
    • true
    • <nil>
    • 0xc000018030 (или другой ненулевой указатель)
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • false
    • true
    • <nil>
    • 0xc000018030 (или другой ненулевой указатель)
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Для выделения памяти под указатель нужно использовать функцию new. Функцию make же стоит использовать для выделения памяти под слайсы и map.

  12. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        var b *bool
        modify(b)
        fmt.Println(b)
    }
    
    func modify(b *bool) {
        if b == nil {
            b = new(bool)
        }
    
        *b = true
    }
    • false
    • true
    • <nil>
    • 0xc000018030 (или другой ненулевой указатель)
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • false
    • true
    • <nil>
    • 0xc000018030 (или другой ненулевой указатель)
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Код успешно аллоцирует память под переменную типа bool внутри функциии. Однако мы записываем адрес на новую память в копию аргумента. Копия аргумента уничтожится после выхода из функции. Поэтому в переменной b внутри функции main значение переменной остается неизменным - nil

  13. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := []int{1,2}
        modify(a)
        fmt.Println(a)
    }
    
    func modify(a []int) {
        a[1] = 3
    }
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Мы изменяет второй элемент слайса (индексация ведется с 0).

  14. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := [2]int{1,2}
        modify(a)
        fmt.Println(a)
    }
    
    func modify(a [2]int) {
        a[1] = 3
    }
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Мы изменяем копию массива, которая уничтожается после выхода из функции

  15. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := [2]int{1,2}
        modify(a)
        fmt.Println(a)
    }
    
    func modify(a [2]int) {
        a[2] = 3
    }
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Мы пытаемся изменить элемент за границей массива. Поскольку размер массива известен на стадии компиляции, такая модификация не пройдет компиляцию.

  16. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := []int{1,2}
        modify(a)
        fmt.Println(a)
    }
    
    func modify(a []int) {
        a[2] = 3
    }
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • [1 2]
    • [1 3]
    • [3 2]
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Мы пытаемся изменить элемент за границей слайса.

  17. Что выведет код?

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := []int{1,2}
        modify(a)
        fmt.Println(a)
    }
    
    func modify(a []int) {
        a[-1] = 3
    }
    • [1 2]
    • [1 3]
    • Результат не определен
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • [1 2]
    • [1 3]
    • Результат не определен
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    У слайсов допускаются только неотрицательные индексы. Поэтому обращение по отрицательному индексу не пройдет компиляцию.

  18. Что выведет код?

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println(myFunc())
    }
    
    func myFunc() (result int) {
        result = 1
        return 2
    }
    • 0
    • 1
    • 2
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • 0
    • 1
    • 2
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    Если в функции с именованым возвращаемым значением выполняется return с указанным значением, то в качестве результата используется именно значение из конструкции return

  19. Что выведет код?

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println(myFunc())
    }
    
    func myFunc() (result int) {
        result = 1
    }
    • 0
    • 1
    • Код не скомпилируется
    • Код запаникует
    Ответ с пояснением
    • 0
    • 1
    • Код не скомпилируется
    • Код запаникует

    Объяснение:

    В функции с именованым возвращаемым значением должен явно присутствовать return в конце функции (или в другом месте, где планируется совершить возврат функции). Для того, чтобы заставить код работать, достаточно вставить конструкцию return (без аргументов) в конец тела функции.