Pull to refresh
16
0
Pavel Korotkiy @outdead

Пользователь

Send message
Я читаю этого автора, но приведенную вами статью почему-то упустил из виду, спасибо, что приложили ее.

Переведенная статья Била Кенеди первая из цикла и, сама по себе, на полноту не претендует. Я планирую перевести все 4 статьи и опубликовать их здесь с перекрестными ссылками. К вопросу полноты можно будет вернуться после этого.

Секунда огорчения
Если не продолжат понижать карму за переводы
Несомненно, вы правы. Но сразу эти изменения никто не смотрел, поэтому увидели их уже после возврата управления. В свете представленного выше кода утверждение автора, в общем-то, корректно.
Еще можно почитать статью go tool trace от Will Sewell. Этот материал немного свежее.
Кстати, в комментариях оригинальной статьи этот вопрос также задавался. Vincent Blanchon, автор статьи, ответил на него примерно так:
Во втором примере мы больше не создаем структуры в стеке/куче. Мы только отслеживаем стоимость использования указателя/копии в качестве параметра. При использовании указателя Go просто делиться адресом на структуру. При копировании копируется вся структура для использования в качестве параметра, что медленнее.

Она там же, где и в оригинальной статье, в выводах.

Подключился через VPN и действительно. Поправлю в статье, но ссылку на видео, пожалуй, тоже оставлю. Спасибо!
Если я вас правильно понял, то в вашем варианте получается, что сам конфиг выглядит примерно так:
Config
type Config struct {
	Bind   string
	logger *logger.Logger
	tls    *tls.Config
}

func (c *Config) SetLogger(log *logger.Logger) *Config {
	c.logger = log
	return c
}

func (c *Config) SetTLS(t *tls.Config) *Config {
	c.tls = t
	return c
}

А сервер так:
Server
type Server struct {
	cfg    Config
	logger *log.Logger
	http   *http.Server
}

func NewServer(cfg *Config) *Server {
	srv := &http.Server{
		Addr:         cfg.Bind,
		TLSConfig:    cfg.tls,
	}

	return &Server{
		cfg:    *cfg,
		logger: cfg.logger,
		http:   srv,
	}
}

С cfg.tls все получилось хорошо, а вот с logger уже не все так просто. Его нужно либо использовать через вызов s.cfg.logger либо выносить из конфига в Server и держать сразу в двух местах. И оба варианта мне не очень нравятся. Также не очень понятно как в NewServer создавать значения по умолчанию без перебора конфига на nil значения. В остальном ваш метод выглядит приятно, спасибо за подсказку.
Именно так оно порой и выглядит.

Возможно я делаю что-то неправильно, но обычно я совмещаю подходы со структурой конфигурации и функциональными параметрами. Часто конфиги лежат в каком нибудь yaml или json файле и их действительно удобно получать в структуру. А что-то вроде сквозных логгеров со своими настройками или конфигурацией, требующей предварительной обработки, довольно комфортно передаются функционально. Мне кажется, что это выгладит не так уж и монструозно:

log := logger.New()
cfg, err := parseConfigFromSomewhere()
// handle error

module.NewServer(
	cfg,
	module.SetLogger(log),
	module.TLS(&TLSConfig{}),
)
А с gofmt то что не так?
Никто и не говорит, что потоки — это плохо. Но если возникает необходимость вести параллельные вычисления совершенно разных типов данных в рамках одного логического куска, то это свидетельствует о том, что выстрел в ногу уже произошел и вполне уже можно выстрелить себе в голову пытаясь покрыть костылями существующую архитектуру.

А там, где многопоточность действительно оправдана, вполне подойдет переброс запроса в соседний сервис, который для этого будет специально написан на чем-то более дружелюбном к потокам.
И отвалиться по таймауту web-сервера и не отдать пользователю ни результат агрегации, ни картинку.

Я категорически рад, что в php нет нативной многопоточности, что уменьшает во мне искушение совмещать несовместимые задачи в одном запросе.
Очевидные вещи, которые действительно повышают производительность как кода так и разработчика. Почему-то сразу же вспомнился первый пункт этой публикации
Спасибо, что еще раз напомнили об этом.

Information

Rating
Does not participate
Registered
Activity