Перейти к содержимому

Ozon / Озон (полный список, ч. 2)

Актуальность: 3 кв 2024

func main() {
var urls = []string{
"http://ozon.ru ",
"https://ozon.ru ",
"http://google.com ",
"http://somesite.com ",
"http://non-existent.domain.tld ",
"https://ya.ru ",
"http://ya.ru ",
"http://eeee ",
}
}

Задача: Напишите программу, которая: a). Поочередно выполнит http запросы по предложенному списку ссылок algorithms/data-structures

Заголовок раздела «Задача: Напишите программу, которая: a). Поочередно выполнит http запросы по предложенному списку ссылок algorithms/data-structures»
  • в случае получения http-кода ответа на запрос «200 OK» печатаем на экране «адрес url - ok»;
  • в случае получения http-кода ответа на запрос отличного от «200 OK» либо в случае ошибки печатаем на экране «адрес url - not ok». б). Модифицируйте программу таким образом, чтобы использовались каналы для коммуникации основного потока с горутинами. Пример:
  • Запросы по списку выполняются в горутинах;
  • Печать результатов на экран происходит в основном потоке.
  • Модифицируйте программу таким образом, чтобы нигде не использовалась длина слайса урлов. Считайте, что урлы приходят из внешнего источника. Сколько их будет заранее - неизвестно. Сделать идиоматичный вариант, как ваша программа будет узнавать об окончании списка и передавать сигнал об окончании действий далee.
  • Модифицируйте программу таким образом, чтобы при получении 2 первых ответов с «200 OK» остальные запросы штатно прерывались. При этом необходимо напечатать на экране сообщение о завершении запроса.
  • Сделать отрефакторить код. Какие тесты написал бы к этому коду? Написать код теста и интерфейсы, для которых будут генериться моки.
  • Какие вообще есть примитивы синхронизации в Go, как их можно использовать?
  • Как используются закрытые каналы?
  • Что будет если писать или читать в закрытый канал?
  • Как сделать счетчик, агрегирующий информацию из разных горутин?
  • Как использовать контекст?
  • У нас есть база данных с паролями пользователей, пароли захешированы (функция hashPassword), а так же известен набор символов которые могут быть использованы в паролях (переменная alphabet). Наша задача реализовать функцию RecoverPassword так, чтобы она восстанавливала пароль по известному хэшу и TestRecoverPassword завершился успешно
import(
"crypto/md5 "
"testing "
)
var alphabet= []rune{'a', 'b', 'c', 'd', '1', '2', '3'}
func RecoverPassword(h[]byte) string{
// TODO: implement me
return""
}
func TestRecoverPassword(t*testing.T) {
for _, exp:=range[]string{
"a ",
"12 ",
"abc333d ",
} {
t.Run(exp, func(t*testing.T) {
act:=RecoverPassword(hashPassword(exp))
if act!=exp{
t.Error("recovered:", act, "expected:", exp)
}
})
}
}
func hashPassword(in string) []byte{
h:=md5.Sum([]byte(in))
return h[:]
}
  • Как сделать подбор константным по сложности, если мы можем ограничьить длину пароля?
  • Вычислительная сложность подбора пароля?
  • Как атакующий может скомпрометировать криптосистему?
  • Как разработчики сервиса могли бы усложнить подбор паролей?
  • Что выведет на экран эта программа?
func main() {
for i := 0; i < 5; i++ {
go func() {
fmt.Println(i)
}()
}
}
  • Как можно было бы изменить программу чтобы каждая горутина правильно выводила свой индекс?
  • Нужно написать простую библиотеку in-memory cache. Для простоты считаем, что у нас бесконечная память и нам не нужно задумываться об удалении ключей из него. Реализация должна удовлетворять интерфейсу:
type Cache interface {
Set(k, v string)
Get(k string) (v string, ok bool)
}
  • Можно ли найти решение лучше?
  • В каких случаях это будет работать медленно?
  • Как шардировать данные?
  • Сколько шардов нужно делать?
  • Можно ли сделать еще более быстрый кэш, если у нас мало ключей и мы заранее знаем, что они идут от «1» до «10000» и других ключей не бывает?
  • Это почти реальный пример из одного из наших сервисов. Этот код - обертка над кэшем, который соотвественно пишет и читает данные из кэша. Нe смотря на то, что внедрение данного кэша должно было облегчить основное ранилище, однако это не произошло. Почему?
type Storage struct {
cache *lru.Cache
}
func (s *Storage) Set(wh *warehouse.Warehouse) {
s.cache.Put(wh.Id, *wh)
}
func (s *Storage) Get(id types.WarehouseId) *warehouse.Warehouse {
item, ok := s.cache.Get(id)
if ok {
if wh, ok := item.(*warehouse.Warehouse); ok {
return wh
}
}
return nil
}
  • Написать код функции, которая делает merge N каналов. Весь входной поток перенаправляется в один канал.
func merge(cs...<-chan int) <-chan int{
...
}
  • Что выведет данная программа? Она отработает корректно?
func main() {
ch := make(chan int)
go func() {
for i := 0; i < 5; i++ {
ch <- i
}
}()
for n := range ch {
fmt.Println(n)
}
}
  • Напишите функцию которая бы возвращала ошибку не импортируя для этого никаких пакетов:
func main() {
println(handle())
}
func handle() error {
// ...
}
  • Что это такое pprof и зачем нужно?
  • Как можно снять профили?
  • Что такое семплирующий профайлер?
  • Есть ли оверхед от использования pprof ’a?
  • Что такое trace и чем он отличается от других профилей?
  • Что видно на флеймграфе?
  • Что выведет данный код?
m := map[string]int{"a ": 1, "b ": 2, "c ": 3}
for a, b := range m {
fmt.Println(a, b)
}
  • В каких случаях данный код даст ошибку?
a := map[B]int{}
a[d] = 0
e, ok := a[d]
  • Какие типы в Go являются incomparable?
  • Что такое интерфейс в Go? Как он устроен?
type Foo struct{}
func (f *Foo) A() {}
func (f *Foo) B() {}
func (f *Foo) C() {}
type AB interface {
A()
B()
}
type BC interface {
B()
C()
}
func main() {
var f AB = &Foo{}
y := f.(BC) // сработает ли такой type-assertion?
y.A() // a этот вызов?
_ = y
}
  • Что такое «пустой интерфейс»(interface{})?
  • Когда допустимо применять пустой интерфейс?
  • Каковы основные отличия применения интерфейса в Go от интерфейсов классического ООП-языка (Java, C#, etc)?
  • Чем горутины отличаются от потоков?
  • Что можно сказать про стек горутины и стек потока?
  • Cколько можно создать горутин?
  • Что такое GOMAXPROCS?
  • Что такое defer? Что выведет следующий код?
type X struct {
V int
}
func (x X) S() {
fmt.Println(x.V)
}
func main() {
x := X{123}
defer x.S()
x.V = 456
}
  • Что изменится, если изменить код?
...
func main() {
x:=X{123}
defer func(){ x.S() }()
x.V= 456
}
...
  • Что выведет данный код?
func main() {
values := []int{1, 2, 3, 4, 5}
for _, val := range values {
go func() {
fmt.Println(val)
}()
}
time.Sleep(100 * time.Millisecond)
}
  • Что такое замыкание? Приведите пример использования замыкания.
  • Что такое mutex и зачем он нужен?
  • Что такое каналы? Зачем нужны? Какие они бывают?
  • К чему приведут операции чтения/записи над закрытым каналом?
  • К чему приведут операции чтения/записи над nil каналом
  • Какой еще способ блокировки навсегда?
  • Что такое select и как он работает
  • Другие примитивы синхронизации
  • Как канал устроен внутри?
  • Какие знаешь паттерны конкурентного программирования, использующие каналы
  • Можно ли передать переменную в несколько горутин?
  • Пример - что будет?
x := make(map[int]int, 1)
go func() { x[1] = 2 }()
go func() { x[1] = 7 }()
go func() { x[1] = 10 }()
time.Sleep(100 * time.Millisecond)
fmt.Println("x[1] =", x[1])
  • Продемонстрировать решение без sync.Mutex/sync.RWMutex
  • Какие знаешь средства для предотвращения RC?
  • Какие mutex бывают и чем отличаются для чего нужны?
  • Что такое слайс? Как он устроен?
  • На что влияет параметр вместимости слайса cap?
  • Как происходит выделение памяти при росте слайса через append? К каким негативным последствиям может неправильное понимание будущего размера слайса в момент его создания?
  • Когда сборщик мусора удалит массив под слайсом?
  • Какие особенности получения нового среза от ранее существующего слайса вы знаете?
  • Чем опасно создание через make слайса с явно указанными len & cap?
  • Что из себя представляет строка в Go?
  • Чем отличается байт от руны в Go?
  • Есть база с такой схемой данных
// user
id | firstname | lastname | birth
1 | Ivan | Petrov | 1996-05-01
2 | Anna | Petrova | 1999-06-01
3 | Anna | Petrova | 1990-10-02
// purchase
id | price | user_id | date
1 | 5500 | 1 | 2021-02-15
1 | 5700 | 1 | 2021-01-15
2 | 4000 | 1 | 2021-02-14
3 | 8000 | 2 | 2021-03-01
4 | 400 | 2 | 2021-03-02
// ban_list
user_id | date_from
1 | 2021-03-08
  • Вывести уникальные комбинации пользователя и id товара для всех покупок, совершенных пользователями до того, как их забанили. Отсортировать сначала по имени пользователя, потом по SKU algorithms/sorting-search
  • Найти пользователей, которые совершили покупок на сумму больше 5000р. Вывести их имена в формате id пользователя | имя | фамилия | сумма покупок sql/general
  • Написать функцию, проверяющую является ли слайс монотонным? Монотонная функция - функция одной переменной, определенная на некотором подмножестве действительных чисел, которая либо везде (на области своего определения) не убывает, либо везде не возрастает. go/slices-arrays
{1,7} - true
{1,1} - true
{3,3,1} - true
{9,5,1} - true
{23,5,23} - false
  • Дан слайс целых чисел. Напишите функцию remove, удаляющую все нули go/slices-arrays
remove([]) ->[]
remove([0]) ->[]
remove([1,0,0,2]) ->[1,2]
  • Требуется реализовать функцию zip, которая соединяет элементы двух слайсов в слайс пар go/slices-arrays
func main() {
s1, s2 := []int{1, 2, 3}, []int{4, 5, 6, 7, 8}
fmt.Println(zip(s1, s2)) // [[1 4] [2 5] [3 6]]
}
func zip(s1 []int, s2 []int) [][]int {
// ...
}
  • Реализовать версию функции zip которая сможет соединять произвольное количество слайсов go/slices-arrays
  • Требуется реализовать функцию uniqRandn, которая генерирует слайс длины n уникальных, рандомных чисел. go/slices-arrays
func main() {
fmt.Println(uniqRandn(10))
}
func uniqRandn(n int) []int {
// ...
}
  • Что выведет программа? Почему? go/puzzles
func main() {
timeStart := time.Now()
_, _ = <-worker(), <-worker()
println(int(time.Since(timeStart).Seconds()))
}
func worker() chan int {
ch := make(chan int)
go func() {
time.Sleep(3 * time.Second)
ch <- 1
}()
return ch
}
  • Что выведет программа? go/puzzles
s := "test "
println(s[0]) // ?
s[0] = "R "
println(s) // ?
  • Что выведет программа? go/puzzles
func a() {
x := []int{}
x = append(x, 0)
x = append(x, 1)
x = append(x, 2)
y := append(x, 3)
z := append(x, 4)
fmt.Println(y, z) // ?
}
func main() {
a()
}