Оптимизации включают использование map со значениями указателей, парсинг температур вручную и создание специальной хэш-таблицы.
Самое то для понимания, как работают высоконагруженные приложения, и как можно проводить их профилирование.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Залетайте на нашу прямую трансялцию и задавайе вопросы: https://www.youtube.com/watch?v=VHMW9M8rwQQ
Gonews
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Golang собеседования для тех, кто хочет научиться решать алгоритмы
🔥 https://yangx.top/+RAiQoS5k4Bg4NGYy – огромное количество уроков, библиотек и примеров с кодом в канале для Go разработчиков.
📌 https://yangx.top/addlist/MUtJEeJSxeY2YTFi – тут я собрал гигантскую папку маст-хэв для Golang программистов.
Вы сможете посмотреть…
📌 https://yangx.top/addlist/MUtJEeJSxeY2YTFi – тут я собрал гигантскую папку маст-хэв для Golang программистов.
Вы сможете посмотреть…
Статья о человеке, которому Go помогает справляться с диабетом.
Если вкратце, то парень использует Go и распределённую систему микросервисов, чтобы отслеживать уровень инсулина и сахара в крови и т.д.
Параллельно в статье рассказывается про такие инструменты как Prometheus, Grafana, PagerDuty, так что можно узнать много полезного.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
В Go можно писать в файлы без использования буферов, что означает, что каждая операция записи в файл приводит к записи на диск. Это поведение отличается от многих других языков программирования, где операции ввода-вывода буферизуются по дефолту для улучшения производительности.
Если вы хотите использовать буферизованный ввод-вывод, вы должны явно использовать пакет
bufio
для создания буферизованных объектов чтения и записи.В случае записи без использования буфера, каждый вызов
WriteString
приводит к непосредственной записи данных в файл, а с использованием буфера данные сначала записываются в него, и только после происходит запись данных в файл. Это может значительно улучшить производительность, особенно при большом количестве операций записи, поскольку уменьшает количество системных вызовов.В общем, использование буферизованного ввода-вывода может быть более эффективным по сравнению с небуферизованным.
При работе с большими файлами и необходимости минимизировать использование памяти, может быть целесообразно рассмотреть использование
bufio.Scanner
, который также использует буферизацию, но с более низким потреблением памяти.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Loop:
for {
select {
case val, ok :=<- someChan:
if !ok {
// канал закрыт
break Loop
}
// получены данные, работа с val
default:
// канал пуст, что-то делать
}
}
Здесь,
ok
будет истиной только для открытого канала. Но при закрытии по каналу будут приходить пустые сообщения постоянно и ok
будет ложью.Однако вышеприведённая конструкция оптимальна только если нужно выполнять действие в
default
-ветке. Т.е. что-то делать, когда сообщений нет. Есть более простая и понятная конструкцияfor val := range someChan {
// получено сообщение
}
// канал закрыт
В этом случае канал читается, используя
for-range
. Когда канал будет закрыт и из него будет прочитано последнее сообщение, произойдёт выход из цикла.Запись в закрытый канал вызывает панику.
Дизайн приложения должен быть таким, что сторона создающая канал, его же и закрывает и пишет в него то же она. Более того, в этих случая рекомендуется, что б функция возвращала канал только для чтения
func run () <-chan string {
c := make(chan string)
// [...]
}
Конечно можно в отложенном вызове вызвать
recover()
, чтобы подавить панику. Но это в корне неправильно. @golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Среди заданных вопросов много интересных, типо:
— можно ли с Go и HTMX делать fullstack-приложения
— в чём отличие между namespace в других ЯП и package в Go
— как обстоят дела с Dependency Injection в Go
— и ещё несколько других
Отличное видео, помогает узнать об актуальных задачах, которые решаются с помощью Go и не только
Рекомендую)
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
rune
и byte
— в чём разница?rune
- это 32-х битный тип, представляющий юникодные символы в кодировке UTF-32 aka UCS-4.byte
- это универсальный 8-битный тип.rune
используется для работы с не-ASCII символами в строках. Есть встроенное приведение []rune
для типа string
, которое парсит строку из UTF-8
(представление с переменной длиной байтов) в представление с фиксированной длиной байтов.[]byte(str)
и []rune(str)
разительна. Строка Привет, мир!
:Байты: [208 159 209 128 208 184 208 178 208 181 209 130 44 32 208 188 208 184 209 128 33]
Руны: [1055 1088 1080 1074 1077 1090 44 32 1084 1080 1088 33]
[]rune(string)
эквивалентно вот такой функции:func ToRunes(bytes []byte) []rune {
result := []rune{}
for i := 0; i < len(bytes); {
r, size := utf8.DecodeRune(bytes[i:])
result = append(result, r)
i += size
}
return result
}
Привет, мир!
в руны и обратно@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
func HandleRequest(client http.Client, request *http.Request)
(*http.Response, error) {
response, err := client.Do(request)
defer response.Body.Close()
if err != nil {
return nil, err
}
}
А теперь вопрос: почему это должно работать, ведь тело всё равно закрыто, не зависимо до проверки или после?
Известно, что полное отсутствие строки
defer response.Body.Close()
приводит к гарантированным проблемам, но как протестировать вышеупомянутую уязвимость?defer response.Body.Close()
означает, что response.Body.Close()
должно быть выполнено в точке выхода из функции. Ни о каком закрытии тела до проверки ошибки речь не идёт.Проблема здесь в другом — в случае ошибки
response
может быть nil
, и выполнение отложенной инструкции в ветке if err != nil {... return ...}
в таком случае приведет к панике из-за обращения к нулевому указателю.panic: runtime error: invalid memory address or nil pointer dereference
А вот собственно и код:
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
)
func main() {
client := http.Client{}
url, _ := url.Parse("https://no.such.host")
request := &http.Request{
Method: "GET",
URL: url,
}
response, err := client.Do(request)
defer response.Body.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Request failed: %s\n", err.Error())
}
io.Copy(os.Stdout, response.Body)
}
Как-то так
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Здесь описывается абсолютно всё, что поможет подготовиться к собеседованию, и даже больше
Вопросы с собеседований связанные с Golang
├── Общие вопросы
├── Хеш-мапы
├── Интерфейсы
├── Пакеты
├── Типы данных
├── Defer
├── Примитивы синхронизации
├── Планировщик
├── Строки
├── Массивы и слайсы
├── Дженерики
├── Горутины
├── Конструкции
├── Гонка данных
├── Структуры
├── Контекст
├── Ошибки / Panic
└── Указатели
Вопросы с собеседований связанные с Linux
├── Файловая система
└── Сигналы, процессы
Вопросы по инфраструктуре
└── Базы данных (реляционные)
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Есть функция
strings.Contains
, но она проверяет есть ли строка в строке, не массив. Есть ли функция для этого, или надо писать свою?slices.IndexFunc
// искать индекс элемента target
idx := slices.IndexFunc(someSlice, func (elt E) { return elt == target })
if idx >= 0 { /* найден */ }
Но это реально тривиальная функция:
func IndexFunc[E any](s []E, f func(E) bool) int {
for i := range s {
if f(s[i]) {
return i
}
}
return -1
}
Если же массив отсортирован, то есть функция поиска делением пополам
slices.BinarySearch
- ищет для типов, для которых определено сравнение <
. В общем случае есть поиск по отсортированному слайсу с компаратором slices.BinarySearchFunc
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Например, тип
byte
из модуля "строки" — это алиас uint8
. Алиас объявляется через ключевое слово type
:type NumCount int
func main() {
nc := NumCount(len([]int{1, 2, 3}))
fmt.Println(nc) // 3
}
type errorCode string
func main() {
ec := errorCode("internal")
fmt.Println(ec) // internal
fmt.Println(string(ec)) // internal
}
type counter int
// передается указатель, чтобы можно было изменить состояние счетчика "c"
func (c *counter) inc() {
*c++
}
func main() {
c := counter(0)
(&c).inc() // передается указатель на счетчик &c, так как функция "inc()" работает с указателями
(&c).inc()
fmt.Println(c) // 2
}
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4
struct {
T1 // field name is T1
*T2 // field name is T2
P.T3 // field name is T3
*P.T4 // field name is T4
x, y int // field names are x and y
}
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | AnonymousField) [ Tag ] .
AnonymousField = [ "*" ] TypeName .
Tag = string_lit .
Эти строки имеют отношение к граматикам, которые использует компилятор? Для чего эта информаия прописана в документации?
_
. Как его можно использовать?// A struct with 6 fields.
struct {
x, y int
u float32
_ float32 // padding
A *[]int
F func()
}
Что ж, давайте разберёмся со всеми вопросами:
type commonWidget struct {
width, height int
}
func (w *commonWidget) setHeight(height int) { w.height = height }
func (w *commonWidget) setWidth(width int) { w.width = width }
type button struct {
commonWidget
text string
}
type input struct {
commonWidget
type_ string
}
Здесь тип
commonWidget
описывает общие для всех виджетов поля и методы. Путём включения, типы button
и input
получают как нужные поля, так и методы, с ними работающие.gc
и gccgo
. Благодаря тому, что есть спецификация, когда два этих компилятора чем-то различаются, можно понять, кто "не прав". В свою очередь, различия в имплементации компиляторов часто указывают на неполноту спецификации.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Wikipedia
Composition over inheritance
software design pattern
url
строки из punicode в unicode.Т.е. задача:
xn--go -uedfq
——> Go топ
. И наоборотidna
, сперва ставим пакет локально:go get golang.org/x/net/idna
Не забываем настроить переменную среды
%GOPATH
. После этого мы сможем спокойно импортировать пакет в проект:package main
import (
"fmt"
"golang.org/x/net/idna"
)
var p *idna.Profile
func main() {
p = idna.New()
fmt.Println(p.ToUnicode("xn--go -uedfq"))
}
// Go топ
Вот такие дела
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM