Установка golang 1.8

По дефолту в убунту-подобных системах до сих пор ставится golang 1.6.
Для установки рекомендую воспользоваться следующим PPA:
sudo add-apt-repository ppa:longsleep/golang-backports 
sudo apt-get update 
sudo apt-get install golang-go

Panic, recover в golang

Несмотря на наличие мануала непросто досконально понять, как работают конструкции panic и recover.

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

Обработать panic может помочь ф-ция recover. Ф-ция сама по себе бессмысленна и использоваться должна в следующем фрагменте кода:
defer func() {
    if r := recover(); r != nil {
        // любые действия при возникновении ошибки
    }
}()


Как видим recover вызывается внутри отложенной (defer) конструкции.
Код defer вызывается при завершении ф-ции, в которой он описан. При чем вызовется он в любом случае: в случае рядового завершения ф-ции; при панике паники; в случае завершения всей программы после SIGKILL.

Recover похож на catch, но всё же не дотягивает до него, т.к. после catch можно продолжить выполнение ф-ции как угодно, например вернуть какое-то другое значение (вызвать return). Recover же даёт возможность выполнить некоторое действие, но повлиять на возвращаемое ф-цией значение уже не может, т.к. он выполняется recover в контексте defer.

Интересно, что ф-ция, внутри которой сработал defer-recover, вернёт дефолтное значение своего типа. Например, если ф-ция bool, то false. Если int, то 0. Если указатель, то nil.

Пример ниже показывает то, что ф-ция типа *string после recover вернёт nil, как бы не хотелось получить указатель на 456.
s:= func() *string {
    defer func() {
        if r := recover(); r != nil {
            d := "456"
            return &d
        }
    }()
    panic("error");
    d := "123"
    return &d
}()

log.Printf("%+v\n", s) // выведет nil

Странности c отловом исключений по Throwable интерфейсу в PHP

Если выполнить отлов исключения на интерфейс Throwable, то класс исключения обязательно должен быть импортирован, в противном случае пойманное исключение будет null.

//no import

try {
// some code throwing FooBarException
} catch (\Throwable $e) {
   var_dump($e); // null
}


// import
use FooBarException;

try {
// some code throwing FooBarException
} catch (\Throwable $e) {
   var_dump($e); // FooBarException
}

Парсинг json в golang

Для парсинга cуществует стандартный модуль json и конкретно ф-ция Unmarshal.
func Unmarshal(data []byte, v interface{}) error


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

Интересна ситуация, когда надо распарсить структуру с числовыми полями, эти поля могут быть опциональны. В этом случае поля структуры сохранят свои дефолтные значения, т.е. 0.

var s struct{ Id int }
// Парсим пустой json в структуру с числовым полем
json.Unmarshal([]byte(`{}`), &s)

// Выведет 0, на самом деле, как мы видели, 0 не передавался
log.PrintLn(s.Id)


Как отличить ситуацию, когда поля вовсе не было от ситуации с реально переданным нулём?
Как один из вариантов может быть парсинг в указатель, т.к. в случае отсутствия ключа, поле структуры-указатель примет значение nil, а при переданном ключе там будет указатель на число.

var s struct{ Id *int }
// Парсим пустой json в структуру с числовым полем
json.Unmarshal([]byte(`{}`), &s)

if s.Id == nil {
   // Ничего не передавалось
}


Для ускорения массовой генерации json для структур можно использовать модуль ffjson, повторяющий интерфейс модуля json.
ffjson на этапе компиляции генерирует код парсинга каждой структуры и использует этот код в реалтайме, обходясь без более долгоработающего модуля reflect. Плюсы модуля — в 2-3 раза более быстрая генерация. Минусы — больший бинарник.

Выборка всех записей с плагином doctrine softdeleteable

После подключения модуля softdeleteable к вашей doctrine, в абсолютно все пути формирования запросов будет подставлен добавлен фильтр IS NULL для полей, помеченных этим модулем.

Отключить фильтр можно отдельно для entity или в целом для entity manager, воспольновавшись советами из документации http://atlantic18.github.io/DoctrineExtensions/doc/softdeleteable.html:

// This will disable the SoftDeleteable filter, 
// so entities which were "soft-deleted" will appear in results
$em->getFilters()->disable('soft-deleteable');


// Enable / Disable filter filter, for specified entity (default is enabled for all)
$filter = $em->getFilters()->enable('soft-deleteable');
$filter->disableForEntity('Entity\Article');
$filter->enableForEntity('Entity\Article');


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

Bluetooth наушники bluedio hurricane turbine и linux mint

Приобрел на алиэкспрессе сабжевые наушники за 2 т.р., приехали через 2.5 недели.
Наушники неплохие — хорошая громкость, активное шумоподавление, мощная батарея, режим гарнитуры, встроенный FM и mp3 плеер с карты sd.

С наушниками конечно же не могло всё получиться с первого раза. Для начала, режим спаривания включается если подержать кнопку включения секунды 3 до звука и затем ещё секунду. Про дополнительную секунду узнал из видео про распаковку данного девайса.

Далее после подключения устройства, мой linux mint никак не хотел считать его именно наушниками (а не гарнитурой) и передавать звук хорошего качества. Пришлось немного поколдовать.

Удаляем дефолтный bluetooth manager:
sudo apt-get purge pulseaudio-module-bluetooth bluetooth bluez-* bluez


Ставим касмтомный менеджер blueman

sudo apt-get install blueman bluez pulseaudio-module-bluetooth --install-suggests


Далее придётся выполнить команду ниже. Команда должна выдать число в терминал. Если выдает ошибку — после перезапуска должно стать ок.

pactl load-module module-bluetooth-discover


Именно эта команда ответственна за то, что наушники можно будет перевести в режим высокого качества звука. К сожалению, эту команду придётся запускать при каждом запуске ОС или вписать в автозагрузку.

Миграция PHP 5.6 к PHP 7

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

т.е.

class A {
    public function b($c, $d) {
    }
}

class E extends A {
    public function b($c) {
    }
}


В методе наследника пропал 1 параметр. В PHP 7 такая ситуация будет приводить к ошибке при загрузке файла с потомком.
Печально, но в code inspector даже с включенным уровнем анализа нет возможности отыскать такие ситуации в коде. Удалось найти с помощью скрипта, который автолоадил все классы в системе.

Установка node.js linux

По неясным причинам в ОС семейства linux нельзя просто так взять и установить node.js одной командой.


sudo apt-get install nodejs

данная команда приведёт к установке бинарника nodejs.
Однако большинство утилит, работающих с node, захотят бинарник с имененом node.

Некоторое время по незнанию я делал
sudo ln -s /usr/bin/nodejs /usr/bin/node
Позже оказалось, что данную ф-цию реализует пакет nodejs-legacy.

Итого, установка ноды, готовой к работе выглядит так:

sudo apt-get install nodejs nodejs-legacy

Casio WK-3500, linux, современные реалии

Году в 2002м я приобрел сабжевый синтезатор. Ну как я, купила его мне моя мама, я был студентом первых курсов и ничего не зарабатывал на тот момент.
Инструмент хорош и поныне, но соединение с ПК даже на тот момент выглядело устаревшим.



3 варианта «передачи данных в синтезатор»

  1. некое гнездо для смарт-карт, которых даже как-то не застал в продаже. Это не те смарткарты, что сейчас ходят в обиходе, те смарткарты я даже нагуглить не смог.
  2. floppy
  3. «порт джойстика»

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

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

Потребовалось немного смекалки и решение было найдено — внешний usb floppy.

Был приобретен в магазине Юлмарт по цене в районе 300-500 рублей.

К сожалению, так просто дисковод не заводился на моём linux mint.
Пришлось немного поколдовать в консоли, решение нашлось по ссылке, оно оказалось в вызове команды mount.

Скопировав файлы из интернета и передав их в инструмент, столкнулся со следующей проблемой: синтезатор читает только файлы в формате midi0, в инете же все midi судя по всему, в формате midi1.

Чтение заумных статей про конверторы midi0 -> midi1 для linux не дало ни одного реально работающего решения. И решение нашлось в виде dos(!) утилиты midi1to0.exe, для которой пришлось установить dosbox.

Т.о. передача файлов на синтезатор сейчас выглядит так:
  • скачиваем midi в инете
  • запускаем
    dosbox midi1to0.exe song1.mid song0.mid
  • Подключаем флоппи, монтируем его как написано тут
  • перекидываем song0.mid на floppy
  • дискету вставляем в синтезатор