Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Привет, ребята!
Делюсь опытом, урок #1.
Язык для примеров - Golang.
*---------------------------------------------------------------------------------*
Контекстный словарик:
Легальный код, код — авторский код, без внешнего вмешательства;
Переменная — именованная область памяти, доступная для редактирования (изменения) легальным кодом данной программы;
Константа — не редактируемая легальным кодом именованная область памяти;
Объект, имя — общее указание на Переменные и Константы.
*---------------------------------------------------------------------------------*
Итак, правила:
*---------------------------------------------------------------------------------*
+ имя состоит из нескольких слов слитно и начинается с маленькой буквы. Каждое последующее слово этого имени с большой:
var (
sendResultBytes []byte
)
*---------------------------------------------------------------------------------*
+ имя должно максимально ёмко обозначить назначение и смысл объекта настолько, чтобы не пришлось комментировать дополнительно, на сколько это получится с сохранением читаемости кода, а в конце имени указываю тип этого объекта:
send — отправить сообщение
Result — собираемый в одной переменной результат вычислений / сбора данных
Bytes — тип переменной = []byte / байтовый срез / слайс
// Определяем константы:
const (
apiUx byte = 1
apiUxPrintLogText byte = 1
)
var (
textHelloWorld []byte = []bytes("Hello world!")
)
// Выделяем новый участок памяти под формирование строки:
sendResultBytes = nil
// Первыми идут API-команды:
sendResultBytes = append(sendResultBytes, apiUi, apiUiPrintLogText)
// Добавляем само сообщение для вывода в логирующий терминал:
sendResultBytes = append(sendResultBytes, textHelloWorld...)
// Отправляем в канал рассылки:
chSendMsgToFront <- sendResultBytes
*---------------------------------------------------------------------------------*
+ у объектов — перечней/списков должны быть общие признаки в именах:
errorPage404
errorUnknown
errorNameLenMustBe256max
errorNameLenMustBe8min
*---------------------------------------------------------------------------------*
+ если нужно присвоить конкретное значение переменной, то удобнее использовать указание на константу:
// можно сделать так:
bufferLoginLength = 256
bufferPassLength = 256
// удобнее сделать так:
const (
maxBufferLength = 256
)
bufferLoginLength = maxBufferLength
bufferPassLength = maxBufferLength
Во втором варианте не придётся по всему коду бегать искать все места упоминания размерности в 256, достаточно будет изменить константу.
Это правило касается даже тех случаев, когда значение будет равно «1».
И количество констант, равных «1», может быть несколько, но с разными именами.
*---------------------------------------------------------------------------------*
+ наличие и использование констант помогает осознавать, что при чтении значения из неё не придётся блокировать мьютекс, так как не будет возникать ситуации с одновременным обращением на чтение и запись из разных потоков выполнения кода.
*---------------------------------------------------------------------------------*
+ начинать имя с маленькой буквы нужно для того, чтобы отличать переменные родительского класса от дочернего, так же добавляем внутренний мьютекс структуре и используем табуляцию для красоты и читаемости:
// назначаем структуру родительского типа:
type broadcastList struct {
Mu sync.Mutex
Address string
Name string
UniqID uint64
}
// назначаем переменную родительского типа:
parrentBroadcast := new(broadcastList)
// Блокируем мьютекс с Tab-отступом для удобства визуального восприятия кода:
parrentBroadcast.Mu.Lock()
// присваиваем значения переменным дочернего типа:
parrentBroadcast.Address = "@Mars planet"
parrentBroadcast.Name = "Elon Musk"
parrentBroadcast.UniqID = 1
// Освобождаем мьютекс:
parrentBroadcast.Mu.Unlock()
*---------------------------------------------------------------------------------*
+ для тяжёлых / долгих операций над распределёнными значениями, выгоднее задействовать дополнительные переменные, если дело не касается критичности в актуальности значений и расход дополнительной памяти не приведёт к переполнению.
Например, для вывода в терминал может использоваться тяжёлая конструкция log.Printf, которая в данном примере не имеет критичности к точности распределённых данных на момент вывода, и её не обязательно исполнять в режиме блокировки:
mu.Lock()
a := unixTimeScaleUint64
mu.Unlock()
log.Printf("8755 unix = %d", a)
Таким образом, распределённая переменная unixTimeScaleUint64 как можно раньше становится доступной для других потоков, в то время когда копия её значения используется для вывода в терминал долгой инструкцией.
Обратите внимание на цифру 8755, указывающую на номер строки текстового кода — это дополнительное удобство для трассировки программы в режиме программирования/отладки, чтобы было понятно в какой момент срабатывает вывод в терминал.
*---------------------------------------------------------------------------------*
+ Для быстрого возврата к месту последнего редактирования кода (в рамках текущей сессии), удобно использовать комбинацию сочетаний клавиш CTRL+Z и сразу CTRL+Y.
*---------------------------------------------------------------------------------*
+ Для каждой группы переменных, удобнее использовать отдельный именованный мьютекс.
*---------------------------------------------------------------------------------*
+ Если что упустил из виду ещё, то дополнять буду в последующих уроках.
Спасибо за внимание!
Сергей Попов (Socket Language)