Все потоки
Поиск
Написать публикацию
Обновить
100.24

Go *

Компилируемый, многопоточный язык программирования

Сначала показывать
Порог рейтинга

Всем привет, прошел уже 1 месяц с того момента как я опубликовал свою первую статью на habr и около 2,5 месяцев с первого дня разработки моей игры. В этом посте я бы хотел рассказать о прогрессе, которого я смог достичь за то время, которое прошло с момента последней публикации.

В обновлении я добавил такое как:

  • Возможность разобрать блоки обратно в материалы

  • Добавил множество строительных блоков и блоков интерьера

  • Переписал процедурный генератор мира и добавил новые структуры

  • Добавил рабочие инструменты и обновил принцип добычи материалов, теперь вам нужно иметь кирку, чтобы добывать камень, вам нужно иметь топор, чтобы добывать древесину

  • Написал систему проигрывания саундтреков

  • Теперь обновления мира из новых версий игры вносятся в старый игровой мир, таким образом все новые структуры будут доступны также и в старом мире

  • Провел оптимизацию рисовку игрового мира

  • Теперь игра доступна не только для Windows, но еще и для Linux

Ещё я учёл свою прошлую ошибку, такую как необходимость вступления в мой дискорд сервер для того, чтобы скачать игру, например. Но я исправился и теперь ознакомиться с управлением, игрой и скачать её можно тут. Если кого-то из читателей этой статьи заинтересовала разработка игр на Gо, то можете вступить в телеграмм сообщество про разработку игр на Go.

Теги:
Всего голосов 4: ↑4 и ↓0+6
Комментарии3

6 июня. Golang meetup в московском офисе Ситидрайва

6 июня ждем вас в московском офисе Ситидрайва на камерный Golang митап!

Инженеры из команды Ситидрайва, VK рекламы и E-com Tech расскажут о сервисах на Golang: только кейсы из практики и личный опыт. В завершение каждого доклада можно будет задать вопросы и пообщаться со спикерами в неформальной обстановке. 

Программа:

18:15-18:30 | Сбор в офисе Ситидрайва, знакомство и Welcome

18:30-19:00 | Доклад «Не Go единым»

Спикер: Вячеслав Морозов — Head of Backend разработки клиентских сервисов в Ситидрайве

19:10-19:40 | Доклад “Использование Kafka с Golang: Оптимизация эффективности обработки сообщений”

Спикер: Симоне Кабрино — Руководитель команды в e-com.tech (ранее samokat.tech), которая разрабатывает Customer Data Platform

19:40-20:10 | Нетворкинг

20:10-20:40 | Доклад «Жизнь в продакшене сервиса на Go»

Спикер: Иван Ремень — Руководитель разработки рекламного ядра в VK рекламе

20:45-21:15 | Доклад «C? Go? Cgo! — Интеграция библиотек на C в проектах на Golang»

Спикер: Иван Сорокин — Руководитель команды разработки, которая отвечает за все финансовые истории внутри приложения Ситидрайва

21:15-22:00 | Нетворкинг

Мы верим в силу совместного обучения и обмена идеями, поэтому создаём открытую и дружественную атмосферу, где каждый может почувствовать себя частью комьюнити. 

Билетов на мероприятие всего 70. Участие бесплатное, но регистрация по ссылке обязательна. Для входа в офис потребуется паспорт или водительское удостоверение.

До встречи!

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Go SDK
Будучи скромным гофером хочу отметить, что решение тех или иных задач - требует понимание базы и идиом языка. Конечно, есть замечательная документация, есть не менее замечательный хаб, но пока самые-самые сердечки это репозитория go, где в центре внимания легендарный пакет runtime и sync.
Вот несколько примеров, как описан sync.Map в коде, комментарии к которому и реализация методов отвечает на многие вопросы

//...
// Load, LoadAndDelete, LoadOrStore, Swap, CompareAndSwap, and CompareAndDelete
// are read operations; Delete, LoadAndDelete, Store, and Swap are write operations;
// LoadOrStore is a write operation when it returns loaded set to false;
// CompareAndSwap is a write operation when it returns swapped set to true;
// and CompareAndDelete is a write operation when it returns deleted set to true.
type Map struct {
//...
// Range may be O(N) with the number of elements in the map even if f returns
// false after a constant number of calls.
func (m *Map) Range(f func(key, value any) bool) {
	// We need to be able to iterate over all of the keys that were already
	// present at the start of the call to Range.
	// If read.amended is false, then read.m satisfies that property without
	// requiring us to hold m.mu for a long time.
	read := m.loadReadOnly()
	if read.amended {
		// m.dirty contains keys not in read.m. Fortunately, Range is already O(N)
		// (assuming the caller does not break out early)...
    ...

Всем приятного копания базы и профессионального роста.

Теги:
Всего голосов 3: ↑3 и ↓0+4
Комментарии0

В go 1.22 провели изящный рефакторинг части когда по увеличение емкости среза на x1.25 относительно порога значения емкости в 256.
Не большой тест на arm M1 Pro:

const threshold = 256 
//v 1.21
func BenchmarkName121(b *testing.B) {  
  var newcap = threshold  
  var newLen = 100_000_000_000  
  for 0 < newcap && newcap < newLen {   
    newcap += (newcap + 3*threshold) / 4 
  }  
  if newcap <= 0 {   
    newcap = newLen  
  }
}

//v 1.22
func BenchmarkName122(b *testing.B) {
  var newcap = threshold 
  var newLen = 100_000_000_000  
  for {    
    newcap += (newcap + 3*threshold) >> 2    
    if uint(newcap) >= uint(newLen) {   
      break   
    }  
  }
}

В 8 из 10 прогонов результат одинаковый, в оставшихся - 121 показывает лучший результат
В 8 из 10 прогонов результат одинаковый, в оставшихся - 121 показывает лучший результат

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии1

Питонисты! В 19:00 начинаем транслировать Selectel Python Meetup.

Присоединяйтесь к митапу, задавайте вопросы спикерам и общайтесь в чате с коллегами, работающими с сетевыми технологиями.

Смотрите трансляцию прямо в этом посте или переходите на YouTube.

Теги:
Всего голосов 8: ↑8 и ↓0+8
Комментарии0

28 марта в 19:00 мы проведем Selectel Python Meetup для разработчиков, техлидов и тимлидов разработки. Соберем экспертов из Selectel, Банка Точка и Yandex.Cloud. Обсудим «еще один» быстрый фреймворк, плюсы и минусы чистой архитектуры, опыт перехода с Python на Go.

Темы докладов:

  • «Черная овечка на фоне FastAPI»,

  • «Слоистая архитектура в Python-приложениях: гибкость кода vs оптимизация»,

  • «Перешел с Python на Go. Лучше стало?».

Регистрируйтесь на митап — будем ждать вас в онлайн-трансляции или в офисе Selectel.

Регистрация →

Теги:
Всего голосов 7: ↑7 и ↓0+7
Комментарии0

На GitHub под лицензией Apache License 2.0 опубликован проект под названием Nuke v1.1.0. Это реализация арены памяти для Go с бенчмарками и даже реализацией параллельной арены.

Арена памяти — это метод управления памятью, при котором сразу выделяется большой блок памяти, а его части используются для удовлетворения запросов выделения от программы. В контексте языка со сборкой мусора, такого как Go, использование арен памяти может дать несколько преимуществ:

  • повышение производительности: распределяя память большими блоками, арены памяти сокращают накладные расходы, связанные с частыми вызовами системного распределителя памяти;

  • Улучшенная локальность кэша. Арены памяти также могут улучшить локальность кэша, размещая тесно связанные объекты в одном блоке памяти;

  • эффективность сборки мусора. Использование арен памяти может снизить рабочую нагрузку на сборщик мусора за счёт уменьшения количества объектов, которые необходимо отслеживать и собирать, что приводит к меньшему времени паузы и более предсказуемой производительности.

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

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Проклятие дженериков 💀

Дженерики могут показаться очень простой темой.
Например, вот так в Java выглядят классные и простые методы интерфейса List:

interface List<E> extends Collection<E> {
	boolean add(E e);
	E set(int index, E element);
}

Но у обобщений много нюансов: вложенность, вариантность, границы и т.д. Это сильно усложняет их использование.
Вот не менее классный, но совсем непростой flatMap интерфейса Stream🙈:

interface Stream<T> extends BaseStream<T, Stream<T>> {
	<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
}

Также, реализация дженериков - всегда трейдоф. Мы либо получаем большой исполняемый файл, из-за того, что приходится генерировать код для разных типов. Либо получаем дополнительную нагрузку в рантайме, из-за различных проверок.

Из-за таких сложностей, в языке Go (философия которого - простота и минимализм) дженерики появились аж через 12 лет после релиза языка. А первый коммент про то что нужны дженерики появился меньше чем через 24 часа🙃

Во многих популярных языках дженерики появились не с первой версии, но рано или поздно, разработчики были вынуждены их ввести:

  • С++ вышел в 1979, дженерики - 1986

  • Java - 1996, дженерики - 2004

  • C# - 2001, дженерики - 2005

  • Go - 2009, дженерики - 2021

Теги:
Всего голосов 5: ↑3 и ↓2+1
Комментарии8

Поделитесь с командой создателей Go своими отзывами о разработке с помощью этого языка программирования.

Опрос для разработчиков Go 2024 открыт, и мы хотим услышать ваше мнение!

С 2016 года данные опросов разработчиков Go помогают нам определять ключевые модели использования, понимать проблемы разработчиков, узнавать предпочтения в отношении инструментов и отслеживать новые тенденции в сообществе. Ваши отзывы очень важны для формирования будущего Go, поэтому, пожалуйста, уделите 10–15 минут, чтобы заполнить опрос до 11 февраля 2024 года. Примите участие в опросе прямо сейчас!

Чем больше разработчиков примет участие, тем лучше мы сможем понять потребности сообщества Go. Вы можете помочь распространить информацию, поделившись этим опросом в своих социальных сетях, со своими коллегами и в любых других соответствующих сообществах.

Теги:
Рейтинг0
Комментарии0

Хитрый способ в PostgreSQL перебрать всю таблицу медленно и аккуратно, но эффективно, используя указатель ссылающийся на конкретный tuple - ctid.

	var endBlock int
	row := db.QueryRow(ctx, `select relpages from pg_class where oid = 'table1'::regclass::oid`)
	err = row.Scan(&endBlock)
	if err != nil {
		return
	}

	startBlock := 0
	blocksPerIteration := 50
	maxTuplesPerBlock := 150

	for {
		var rows pgx.Rows
		rows, err = db.Query(ctx, `
				select id
				from table1
				where ctid = any (
					array(
    					select format('(%s, %s)', a, b)::tid
    					from generate_series($1::int, $2::int) a(a)
							cross join generate_series(0, $3) b(b)
					))
					and value = '100000'`,
			startBlock,
			startBlock+blocksPerIteration,
			maxTuplesPerBlock,
		)
		if err != nil {
			return
		}
		var id int
		for rows.Next() {
			err = rows.Scan(&id)
			if err != nil {
				return
			}

			slog.Info("found row", "id", id)
		}
		rows.Close()

		startBlock += blocksPerIteration
		if startBlock > endBlock {
			break
		}
		time.Sleep(100 * time.Millisecond)
	}

Нюансы:

  • из-за того что тип tid не оптимизирует операции больше/меньше, приходится использовать ctid = any (...)

  • для определения maxTuplesPerBlock можно использовать запрос

select 8096 / min(x)
from (
    select pg_column_size(table1) x
    from table1 tablesample system(1)
) d
  • можно делать не только select , но и update и delete, но помнить что строки могут и перемещаются как внутри блока, так и между ними

Теги:
Рейтинг0
Комментарии2

Небольшой пример как копировать данные между базами данных используя go, pgx, и copy.

Предположим что у нас есть два коннекта к базе (одной или нескольким, это не важно). Далее используя io.Pipe() создаём Reader и Writer, и используя CopyTo() и CopyFrom() переносим данные.

  r, w := io.Pipe()

  go func() {
      _, err := db1.PgConn().CopyTo(ctx, w, `copy table1 to stdout binary`)
      if err != nil {
          slog.Error("error", "err", err)
          return
      }
      _ = w.Close()
  }()

  _, err = db2.PgConn().CopyFrom(ctx, r, `copy table1 from stdin binary`)
  _ = r.Close()

Вся прелесть тут в том что используем наиболее быстрый способ с точки зрения PostgreSQL.

Используя copy (select * from where ... order by ... limit ...) to stdout можем регулировать нагрузку на чтение, следить за прогрессом и управлять копированием данных.

В качестве Reader может выступать что угодно, хоть файл csv, хоть другая СУБД, но тогда данные придётся дополнительно конвертировать в формат понимаемый PostgreSQL - csv или tsv, и использовать copy ... from stdin (format csv).

Нюанс: copy ... from stdin binary , binary обязывает использовать одинаковые типы данных, нельзя будет integer колонку перенести в колонку smallint, если такое требуется, то параметр binary надо опустить.

Весь код туть. И ещё немного кода для вдохновения.

Теги:
Рейтинг0
Комментарии0

Вклад авторов