Но если ты посмотришь это видео, то будешь знать ответы, и во всеоружии встретишь такие вопросы, если они попадутся
Уверен, будет полезно)
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
var _ myInterface = &myImplementation{}
:type T struct{}
var _ I = T{} // Проверка, что T имплеменирует I.
var _ I = (*T)(nil) // Проверка, что *T имплеменирует I.
Обычно это указывают, чтобы ошибки были выявлены уже во время компиляции.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Держите годный контент)
Тут неплохой список тем, которые с большой вероятностью будут обсуждаться на собеседовании + теория по самому важному
Собственно, теория покрывает такие разделы:
├╼
Скалярные├╼
Массив и слайс├╼
Map├╼
Структура╰╼
Интерфейс├╼
Каналы├╼
Горутины├╼
Sync╰╼
ПаттерныУверен, будет полезно) Успешных собеседований
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Держите репозиторий с вопросами по Golang. Здесь вы найдете вопросы, которые могут быть заданы на собеседовании, с подробными разъяснениями и анализом различных corner cases. Представьте, что это ваши билеты на экзамен - вытягивайте билет и готовьтесь!
Здесь затрагиваются самые важные темы Go, в том числе:
• Slices
• Maps
• Указатели
• Goroutines и Channels
• Работа со строками
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
io.Pipe
для создания туннеля между писателем и читателем.// отправляем пользователю ответ с аттачем
//reader, writer := io.Pipe()
writer := new(bytes.Buffer)
err = main.Doc.Save(writer) // метод Документа из unioffice - принимает io.Writer, сохраняет тип Document в zip.
//writer.Close() // для Pipe
...
reader := bytes.NewReader(writer.Bytes())
...
nbytes, err := io.Copy(w, reader) // w это http.ResponseWriter
При запуске эта программа зависает, поэтому приходится использовать промежуточный буфер, как видно из кода. Что здесь не так с использованием Pipe?
Нужно просто вызов
Writer
обернуть в горутину, иначе все блокируется.go func () {
defer writer.Close()
err = main.Doc.Save(writer) // принимает io.Writer
...
}
}()
Вот и всё
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Sub
из пакета time
.func main() {
// В високосном году 2096 будет 366 дней
t1 := Date(2096, 1, 1)
t2 := Date(2097, 1, 1)
days := t2.Sub(t1).Hours() / 24
fmt.Println(days) // 366
}
func Date(year, month, day int) time.Time {
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
}
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
map
:map[
/dbus-service:map[
org.freedesktop.DBus.Introspectable:map[]
org.freedesktop.DBus.Peer:map[]
org.freedesktop.DBus.Properties:map[]
Basket:map[
Fruit:"Apple"
]
]
При конвертации в
json
значение поле Fruit
"теряется":"/dbus-service":{
"org.freedesktop.DBus.Introspectable":{},
"org.freedesktop.DBus.Peer":{},
"org.freedesktop.DBus.Properties":{},
"Basket":
{
"Fruit":{}
}
}
Для вывода используется это:
fmt.Printf("%v", data)
jsonData, _ := json.Marshal(data)
fmt.Printf("json data: %s", jsonData)
Вопрос на засыпку: почему так происходит с
Fruit
?Marshal
'aлятся у Fruit:"Apple"
."Apple"
— имеет тип данных dbus.Variant
У него нету "публичных" свойств. Неэкспортируемых.
Экспортируемые пишутся с большой буквы.
Неэкспортируемые с маленькой.
Решение: создавать новое дерево
map
'ов с примитивными данными (string
вместо dbus.Variant
) путем рекурсии.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
array := [104 0 101 0 108 0 108 0 111 0 0 0 0 0 0 0]
. Как перевести его в строку, чтобы она была равна видимым его символам (т.е. string(array[:]) == "hello"
)?package main
import "fmt"
var array = []byte{104, 0, 101, 0, 108, 0, 108, 0, 111, 0, 0, 0, 0, 0, 0, 0}
func main() {
new_array := make([]byte, 0, len(array))
for _, b := range array {
if b == 0 {
continue
}
new_array = append(new_array, b)
}
// 5 - ожидаемая длинна
fmt.Println(len(new_array))
// строка без 0x00
fmt.Println(string(new_array))
}
func btos(c []byte) string {
n := 0
for _, b := range c {
if b == 0 {
continue
}
c[n] = b
n++
}
return string(c[:n])
}
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Необходимо реализовать микросервис для работы с балансом пользователей (зачисление средств, списание средств, перевод средств от пользователя к пользователю, а также метод получения баланса пользователя). Сервис должен предоставлять HTTP API и принимать/отдавать запросы/ответы в формате JSON.
1. Сервис должен предоставлять HTTP API с форматом JSON как при отправке запроса, так и при получении результата.
2. Язык разработки: Go.
3. Фреймворки и библиотеки можно использовать любые.
4. Реляционная СУБД: MySQL или PostgreSQL.
5. Использование docker и docker-compose для поднятия и развертывания dev-среды.
6. Весь код должен быть выложен на Github с Readme файлом с инструкцией по запуску и примерами запросов/ответов (можно просто описать в Readme методы, можно через Postman, можно в Readme curl запросы скопировать, и так далее).
7. Если есть потребность в асинхронных сценариях, то использование любых систем очередей - допускается.
8. При возникновении вопросов по ТЗ оставляем принятие решения за кандидатом.
9. Разработка интерфейса в браузере не требуется. Взаимодействие с API предполагается посредством запросов из кода другого сервиса. Для тестирования можно использовать любой удобный инструмент. Например: в терминале через curl или Postman.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
package cache
import (
"sync"
"time"
)
type Cache struct {
*sync.Map
TTL time.Duration
}
func New(ttl time.Duration) *Cache {
return &Cache{
Map: new(sync.Map),
TTL: ttl,
}
}
func (c *Cache) Store(key, value interface{}) {
c.Map.Store(key, value)
// memory leak?
time.AfterFunc(c.TTL, func() {
c.Map.Delete(key)
})
}
time.Timer
и его методам нет ничего про обязательные деструкторы как у time.Ticker
. При этом в коде выше как минимум 2 проблемы:• Создаётся множество таймеров, что увеличивает потребление ОЗУ и создаёт дополнительную нагрузку на планировщик.
• Если положить значение по ключу дважды, сотрётся оно по истечении первого TTL, а не второго.
И то, и другое можно вылечить, если просто запоминать время установки значения и проходиться по всем значением раз в N миллисекунд, удаляя устаревшие.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
jsonFile, err := os.Open("referenceData/ex.json")
if err != nil {
return err
}
defer jsonFile.Close() // первый defer
byteValue, err := ioutil.ReadAll(jsonFile)
if err != nil {
return err
}
err = json.Unmarshal(byteValue, &exToParse)
if err != nil {
return err
}
jsonFile, err = os.Open("referenceData/di.json") // перезапись jsonFile
if err != nil {
return err
}
defer jsonFile.Close() // нужно ли заново объявлять defer jsonFile.Close()?
byteValue, err = ioutil.ReadAll(jsonFile)
if err != nil {
return err
}
err = json.Unmarshal(byteValue, &diToParse)
if err != nil {
return err
}
Сначала инициализируем переменную не через
var
, а сразу передаём значение. Потом сразу пишем defer jsonFile.Close()
. Потом в этот же файл загружаем другой json, и так же пишем defer jsonFile.Close()
.Вопрос — а нужен ли второй
defer
? По идеи в ОЗУ, после перезаписи, jsonFile
один и тоже, с тем же адресом, но только с другим содержанием.defer
, вычисляются в момент использования defer
. Вот простой пример, где это видно:type T int
func (t T) Close() { fmt.Println(int(t)) }
// ...
t := T(1)
defer t.Close()
t = T(2)
defer t.Close()
// 2
// 1
Вообще, не рекомендуется переиспользовать переменные подобным образом, так как это усложняет понимание текста программы.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Язык Go имеет в своем распоряжении полный набор утилит, выполняемых из командной строки. 99% вы про них знаете, но повторение — мать учения)
Если имя пакета не
main
, то после того, как вы выполните go build
, ничего не скомпилируется. Если вы хотите скомпилировать файл .a
в $GOPATH/pkg
, Вам вместо этого нужно выполнить go install
._obj/ // старый каталог object
_test/ // старый каталог test
_testmain.go // старый каталог gotest
test.out // старый каталог test
build.out // старый каталог test
*.[568ao] // объектные файлы
DIR(.exe) // создано go build
DIR.test(.exe) // создано go test -c
MAINFILE(.exe) // создано go build MAINFILE.go
Эта команда, например, используется, чтобы почистить проект от файлов перед тем, как загрузить его на Github. Эти файлы полезны на этапе тестов, но не нужны для контроля версий.
go fmt
сделает всю работу за вас. Просто выполните команду go fmt <Имя файла>.go
в терминале. go install
. Перед использованием этой команды убедитесь, что у вас установлены соответствующие инструменты:BitBucket (Mercurial Git)
GitHub (git)
Google Code (Git, Mercurial, Subversion)
Launchpad (Bazaar)
Остальные утилиты можно глянуть по ссылке
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Golang
— Секция 1, системный минимум
— Секция 2, минимум по Go
— Секция 3, форматы данных
— Секция 4, базы данных
— Секция 5, сети
— Секция 6, брокеры, очереди сообщений
— Секция 7, инфраструктура и архитектура
— Секция 8, алгоритмы
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
К примеру, при вводе строки "Привет мир, hello world, hello мир, привет world" на выходе должен получится такой список список :
привет - 2;
мир - 2;
hello - 2;
world -2;
Как написать такую функцию?
package main
import (
"fmt"
"regexp"
"strings"
)
//Создаём структуру для хранения кол-ва слов и самих слов
type Words struct {
i int // кол-во слов
s string // тут само слово
}
func main() {
str := "Привет мир, hello world, hello мир, привет world, , "
// приводим всё в нижний регистр для устранения проблем с различием слов 'Привет' и 'привет'
str = strings.ToLower(str)
// Разбиваем строку на массив строк по регулярному выражению, ищем либо ',' либо ' ' (пробел)
arr := regexp.MustCompile("[,| ]+").Split(str, -1)
//создаём массив структур для хранения результатов
ret := []Words{}
chk := false
// проходим циклом для сранения есть ли такое слово в массиве ret или нет
k := 0
for i := 0; i < len(arr); i++ {
chk = false
for k = 0; k < len(ret); k++ {
if arr[i] == ret[k].s {
// если слово уже есть увеличивем счётчик и слово пропускаем
ret[k].i += 1
chk = true
}
}
// если chk true то слово уже есть и ничего делать ненадо
if !chk {
// проверяем что в строке есть буквы и если они есть добавляем её в массив с результатами
if regexp.MustCompile("[a-zа-яё]+").MatchString(arr[i]) {
tmp := Words{i: 1, s: arr[i]}
ret = append(ret, tmp)
}
}
}
// выводим результат
for l := 0; l < len(ret); l++ {
fmt.Printf("%v - %v\n", (ret[l].s), (ret[l].i))
}
}
P.S.: проверка
if regexp.MustCompile("[a-zа-яё]+").MatchString(arr[i])
нужна для того чтобы в результаты не пролез мусор в виде пробелов если пользователь введёт что-то типа:"Привет мир, hello world, hello мир, привет world, , "
хотя это можно сделать и красивее.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🚩 Товарищи разработчики!
В честь дня международной солидарности трудящихся информируем вас о возможности получить подарок при покупке обучающего курса Слёрм с 1 по 7 мая 2024 года.
🎈«Kubernetes для разработчиков», старт 27 мая.
+ Видеокурс «Docker» в подарок
- Ваш завод растет и принято решение переносить сервисы на K8s?
- Недоумеваете как работает контейнеризация и что такое оркестрация?
- Не можете достичь взаимного понимания с DevOpsами?
Применяйте промокод MAYSLURM при оплате обучения, забирайте бесплатный курс, осваивайте новые инструменты и двигайте технологический прогресс!
Мир! Труд! Май! Слёрм!
Реклама ООО «Слёрм» ИНН 3652901451
В честь дня международной солидарности трудящихся информируем вас о возможности получить подарок при покупке обучающего курса Слёрм с 1 по 7 мая 2024 года.
🎈«Kubernetes для разработчиков», старт 27 мая.
+ Видеокурс «Docker» в подарок
- Ваш завод растет и принято решение переносить сервисы на K8s?
- Недоумеваете как работает контейнеризация и что такое оркестрация?
- Не можете достичь взаимного понимания с DevOpsами?
Применяйте промокод MAYSLURM при оплате обучения, забирайте бесплатный курс, осваивайте новые инструменты и двигайте технологический прогресс!
Мир! Труд! Май! Слёрм!
Реклама ООО «Слёрм» ИНН 3652901451