Привет! Сегодня продолжаем серию мини-квизов в нашем блоге. Этот выпуск (предыдущий здесь) будет посвящен языку Go — будем считать, что это разминка в преддверие GopherCon Russia 2018 (кстати, у нас на этой конференции будет стенд, и мы планируем несколько интересных активностей).
Под катом — семь вопросов и пара пасхалок. Ответы на вопросы выложим апдейтом к посту в понедельник, 26.02. Если будете решать — кладите ответы под спойлер, чтобы не портить другим фана.
Enjoy!

1. Что выведет этот код?
package main
import (
    "fmt"
)
func add(arr []int, v int) {
    arr = append(arr, v)
}
func main() {
    arr := make([]int, 0, 100000)
    fmt.Printf("%v %p\n", arr, &arr)
    add(arr, 10)
    fmt.Printf("%v %p\n", arr, &arr)
}Варианты ответов:
- Пустой массив до вызова add, массив из 1 элемента после. Адреса не совпадают.
 - Оба раза пустой массив. Адреса совпадают.
 - Пустой массив до вызова add, массив из 1 элемента после. Адреса совпадают.
 - Оба раза пустой массив. Адреса не совпадают.
 
2. Что выведет этот код?
package main
import "fmt"
func main() {
    numbers := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    s1 := numbers[:5:8]
    fmt.Println(s1)
    s2 := numbers[::4]
    fmt.Println(s2)
}Варианты ответов:
- Массив чисел от 0 до 5, затем массив чисел от 0 до 9
 - Массив чисел от 0 до 4, затем массив чисел от 0 до 9
 - Не скомпилируется
 - Массив чисел от 0 до 4, затем пустой массив.
 
3. Допустим у вас следующая иерархия:
src/
    package_1/
        p1_a.go
        p1_b.go
        package_2/
            p2_a.go
            package_3/
                p3_sh.go
                p3_bash.go
                p3_zsh.goКаждый модуль верхнего уровня импортирует модуль нижнего уровня т.е. package_1 импортирует package_2, а тот в свою очередь package_3. В каждом файле объявлена init-функция след. содержания:
func init () {
    fmt.Println(<название файла, например: p1_a.go>)
}Что будет выведено на экран?
Варианты ответов:
- Ошибка компиляции: More than one file in package declares init function
 - Порядок не определён
 - p1_a.go
p1_b.go
p2_a.go
p3_a.go
p3_bash.go
p3_sh.go
p3_zsh.go - Функции будут вызваны в случайном порядке, но в соответствии с иерархии начиная с нижнего модуля (package_3) и заканчивая верхним (package_1)
 
4. Чему будут равны константы:
const (
    _ = iota
    Avito
    OLX
    LetGo
    Craiglist = iota 
    eBay
)Варианты ответов:
- 1,2,3,4,5
 - Ошибка компиляции: incorrect constant declaration: iota used twice
 - 0, 1, 2, 3, 4
 - 1,2,3,0, 4
 
5. Опытный программист Роб решил добавить модуль для парсинга данных в стандартную библиотеку своего языка. Одним из модулей парсера будет конечный автомат, войдя в поток, Роб набросал следующий код, что произойдёт в момент первой компиляции?
package main
type state func(x int) state
func start(x int) state {
    if x == 0 {
        return middle
    } else {
        return end
    }
}
func middle(_ int) state {
    return end
}
func end(_ int) state {
    return start
}
func main() {
    state := start(0)
    state = state(1)
    state = state(2)
}Варианты ответов:
- Ошибка в коде: произойдёт ошибка во время компиляции "type 'state' used in self declaration"
 - В stdout ничего не выведется, но процесс завершится успешно
 - Runtime ошибка: возникнет бесконечная рекурсия
 
6. Каким будет результат выполнения кода?
package main
import (
    "fmt"
)
func test() (x int) {
    defer func () {
        x++
    } ()
    x = 1
    return x
}
func main() {
    fmt.Println(test())
}- 1
 - 2
 - Compile error
 
7. Молодой китайский программист Jian Yang решил освоить Go для своего нового гео-стартапа. Начав с обычного Hello World, он решил слегка его модифицировать, дабы освоить конструкцию range… Каким будет результат выполнения кода?
package main
import (
    "fmt"
)
func main() {
    var rc, bc int
    str := "Hello ??"
    for _ = range str {
        rc++
    }
    for _ = range []byte(str){
        bc++
    }
    fmt.Println(rc, bc)
}Варианты ответов:
- 8 8
 - 8 12
 - 8 14
 - 8 16
 
Желаем хорошего дня и ждём ваших ответов в комментариях. Следующий выпуск Avito Quiz планируем сделать по PHP.
          
 
SONANT
2 Не скомпилируется
3 Функции будут вызваны в случайном порядке, но в соответствии с иерархии начиная с нижнего модуля (package_3) и заканчивая верхним (package_1)
4 1,2,3,4,5
5 В stdout ничего не выведется, но процесс завершится успешно
6 2
7 8 12
dmbreaker
Можно было просто ссылку на play.golang.org скинуть :)
Попортил фан
youROCK
Я, конечно же, (почти) всё уже проверил сам на play.golang.org, но вот мои оригинальные ответы:
2. Не скомпилируется (но я думал, что по причине того, что capacity не может быть меньше длины, а не потому что длина обязательна)
3. Функции будут вызваны в случайном порядке, но в соответствии с иерархии начиная с нижнего модуля (package_3) и заканчивая верхним (package_1)
4. 1,2,3,0,1 — кстати говоря, такого варианта у вас нет, видимо опечатка
5. В stdout ничего не выведется, но процесс завершится успешно — но за такой код я бы наказывал
6. 2
7. 8 14 — строго говоря, программисты на Го вряд ли должны знать ширину китайских иероглифов в UTF-8. Тут скорее важно, что сами ответы будут разные при итерации по символам и по байтам.
mirrr
2) никогда не использовал тройную запись, могу только предположить, что размерность 4 будет меньше длинны здесь: [::4]
3) конечно, иерархия должна присутствовать, иначе мы рискуем использовать подпакет, который не инициализирован.
4) iota сбрасывается каждый блок const, а он тут один.
5) в stdout, собственно, ничего и не выводим. Но это ж не причина для паники)
6) тут и объяснять ничего не надо, достаточно заменить return x на return, для тех, кто не заметил именованные возвратные значения
7) да кто их знает, сколько байт один иероглиф займет?)
Stronix
Но, кстати, мы можем таки получить доступ к данным:
mirrr
А если так?)
play.golang.org/p/VUwd0G21182
Stronix
С нулевой ёмкостью шах и мат, да) (если не использовать unsafe)
dronnix
Спасибо, вот вам в благодарность тоже задачка:
claygod
Чтобы ваш код работал так, как возможно, предполагается (ну на первый взгляд), надо после инициализации цикла добавить i:=i, а ещё лучше вот так:
RidgeA
Думаю в этом и фишка, что код работает не так как кажется на первый взгляд…
youROCK
Как раз он работает именно так, как кажется на первый взгляд — печатает 3 раза одно и то же число :). Другой вопрос, что наверное в цикле defer вызывать – не лучшая идея :).
youROCK
А ещё лучше просто вот так:
Потому что аргументы для вызова функции вычисляются на момент вызова defer
niamster
Вопрос знатокам Go по именным возвращаемым значениям, вы можете мне указать где в спецификации описывается следующее поведение:
Спасибо
Stronix
Отложенные ф-ции выполняются после возвращения из основной, т.е. сначала будет выполнено
return 2(x = 2), а затем x++.niamster
Спасибо за ответ. Я имел в виду где описывается поведение `return 2` == `x = 2; return x`?
Stronix
golang.org/ref/spec#Return_statements