Задать вопрос
  • Можно ли написать более лаконичный код?

    @ghostiam
    На Go писатель, серверов пинатель.
    Нормально, но нет предела совершенству)

    Пропущенна проверка на ошибки после `err = json.Unmarshal(raw, &packet)`
    так же, код можно упростить, если вложить структуру `RawDataSensorsItems` в `ResultRow`
    Получим:
    type ResultRow struct {
      StreamId int    `json:"stream_id"`
      DateTime string `json:"date_time"`
      RawDataSensorsItems
    }
    
    type RawDataSensorsItems struct {
      AKey    string `json:"a_key"`
      BKey    int    `json:"b_key"`
      SensorA *int    `json:"sensor_a"`
      SensorB *int    `json:"sensor_b"`
      SensorC *int    `json:"sensor_c"`
      SensorD *int    `json:"sensor_d"`
      SensorE *int    `json:"sensor_e"`
      SensorF *int    `json:"sensor_f"`
    }


    Из за чего упроститься код внутри цикла:
    result = append(
            result,
            ResultRow{
                    StreamId: row.StreamId,
                    DateTime: row.DateTime,
                    RawDataSensorsItems: rowS,
            })
    )


    так же, можно использовать не простой `for j := range row.Sensors` по индексам, а сразу со значениями `for _, rowS := range row.Sensors` (игнорируем с помощью `_` индекс, а в `rowS` сразу записываем значение из массива)
    Если так переписать, то получим:
    for _, row := range packet {
        for _, rowS := range row.Sensors {
            result = append(
                    result,
                    ResultRow{
                            StreamId: row.StreamId,
                            DateTime: row.DateTime,
                            RawDataSensorsItems: rowS,
                    })
        }
    }


    Полный код
    package main
    
    import (
    	"encoding/json"
    	"io/ioutil"
    )
    
    func main() {
    	raw, err := ioutil.ReadFile("./data/raw.json")
    	PanicIfErr(err)
    
    	var packet DataPacket
    	var result ResultPacket
    
    	err = json.Unmarshal(raw, &packet)
    	PanicIfErr(err)
    
    	for _, row := range packet {
    		for _, rowS := range row.Sensors {
    			result = append(
    				result,
    				ResultRow{
    					StreamId:            row.StreamId,
    					DateTime:            row.DateTime,
    					RawDataSensorsItems: rowS,
    				})
    		}
    	}
    
    	content, err := json.Marshal(result)
    	PanicIfErr(err)
    
    	err = ioutil.WriteFile("./data/output.json", content, 0644)
    	PanicIfErr(err)
    }
    
    func PanicIfErr(err error) {
    	if err != nil {
    		panic(err)
    	}
    }
    
    type ResultPacket []ResultRow
    
    type ResultRow struct {
    	StreamId int    `json:"stream_id"`
    	DateTime string `json:"date_time"`
    	RawDataSensorsItems
    }
    
    type RawDataSensorsItems struct {
    	AKey    string `json:"a_key"`
    	BKey    int    `json:"b_key"`
    	SensorA *int   `json:"sensor_a"`
    	SensorB *int   `json:"sensor_b"`
    	SensorC *int   `json:"sensor_c"`
    	SensorD *int   `json:"sensor_d"`
    	SensorE *int   `json:"sensor_e"`
    	SensorF *int   `json:"sensor_f"`
    }
    
    type RawDataRow struct {
    	StreamId int                   `json:"stream_id"`
    	DateTime string                `json:"date_time"`
    	Sensors  []RawDataSensorsItems `json:"sensors"`
    }
    
    type DataPacket []RawDataRow
    Ответ написан
    3 комментария
  • Как работает localStorage?

    @ghostiam
    На Go писатель, серверов пинатель.
    LocalStorage доступен только на клиенте, то есть не отправляется с каждым запросом на сервер(придётся писать доп. логику).
    Cookies так же доступен на клиенте, но и отправляется с каждым запросом на сервер.

    Но! Cookies более безопасен, из за того, что имеется флаг "HttpOnly", который запрещает считывать куку скриптами с клиента, что предотвращает утечку информации из за XSS.
    Ответ написан
  • Безопасно ли использовать AJAX для проверки данных авторизации?

    @ghostiam
    На Go писатель, серверов пинатель.
    AJAX это такой же запрос(и на столько же безопасен), как и отправка формы.
    Но в любом случае, хорошо бы иметь HTTPS соединение.
    Ответ написан
    3 комментария
  • Организация ролей?

    @ghostiam
    На Go писатель, серверов пинатель.
    думаю, можно использовать таблицы users (id, ...) и roles (id, ...), сделать между ними связь "многие ко многим" с помощью доп таблицы users_roles (user_id, role_id).
    Ответ написан
    3 комментария
  • Как лучше передать файл >100Гб клиент-сервер?

    @ghostiam
    На Go писатель, серверов пинатель.
    Сам лично несколько дней назад передавал >100Gb данных на сервер через rsync.
    Для поддержки докачки при обрыва связи у rsync есть флаги "--partial --append-verify"
    Ответ написан
    Комментировать
  • Как они автоматически генерируют эти картинки?

    @ghostiam
    На Go писатель, серверов пинатель.
    Ответ написан
    Комментировать
  • Есть ли в GO filter map reduce some every?

    @ghostiam
    На Go писатель, серверов пинатель.
    В го нет "магии" и есть статическая типизация.
    Всю "магию" нужно писать в лоб.
    Переписал ваш пример на го, но это будет работать если тип у поля value всегда будет int, но если там будут разные типы, придётся использовать interface, что не очень хорошо.
    Го не подойдёт, если данные не типизированы(появится морока с конвертацией, а так же снизится производительность, в сравнении с типизированным подходом).

    https://play.golang.org/p/eGfphNwZqRR
    Код
    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	type KV struct {
    		Name  string
    		Value int
    	}
    
    	data := []KV{
    		{
    			Name:  "width",
    			Value: 100,
    		},
    		{
    			Name:  "height",
    			Value: 300,
    		},
    	}
    
    	result := make(map[string]int)
    
    	// reduce
    	for _, v := range data {
    		result[v.Name] = v.Value
    	}
    
    	fmt.Printf("%#v", result) // map[string]int{"width":100, "height":300}
    }


    Пример с интерфейсом и разными типами:
    https://play.golang.org/p/OXUVv58YZoa
    Код
    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	type KV struct {
    		Name  string
    		Value interface{}
    	}
    
    	data := []KV{
    		{
    			Name:  "width",
    			Value: 100,
    		},
    		{
    			Name:  "height",
    			Value: 300,
    		},
    		{
    			Name:  "image",
    			Value: "cat.jpg",
    		},
    	}
    
    	result := make(map[string]interface{})
    
    	for _, v := range data {
    		result[v.Name] = v.Value
    	}
    
    	fmt.Printf("%#v", result) // map[string]interface {}{"width":100, "height":300, "image":"cat.jpg"}
    }
    Ответ написан
    Комментировать
  • Белый ли IP-адрес?

    @ghostiam
    На Go писатель, серверов пинатель.
    Судя по описанию у вас не публичный "белый", а частный "серый".
    Белый IP может меняться(статичный IP не меняется), но должен быть доступен из сети интернет, то есть, IP с которого вы выходите в интернет (который показывают сервисы на подобии 2ip) и должен быть присвоен на роутере как WAN IP.

    https://help.keenetic.com/hc/ru/articles/213965789...
    Ответ написан
    Комментировать
  • Как динамически выделить array [var]type?

    @ghostiam
    На Go писатель, серверов пинатель.
    Слайсы используют те же массивы под капотом.

    Используя:
    length := 7
    slice := make([]int, length)

    выделяется слайс, да, но он ровно той длины которая была задана, прямо как массив. https://play.golang.org/p/vAQqLI-msfi
    Ответ написан
    Комментировать
  • Как в golang с помощью tgbotapi переслать отправителю его же сообщение?

    @ghostiam
    На Go писатель, серверов пинатель.
    Старый ответ

    как и с сообщениями, у созданных объектов есть свойство ReplyToMessageID в которое нужно записать ID сообщения из update.Message.MessageID
    audioUpload := tgbotapi.NewAudioUpload(update.Message.Chat.ID, ...)
    audioUpload.ReplyMarkup = update.Message.MessageID
    _, err := bot.Send(audioUpload)


    Если возникает вопрос, как вообще отправить файл, то нужно передать структуру tgbotapi.FileBytes или tgbotapi.FileReader вторым параметром в функцию и заполнить её.
    Для примера, отправляем файл с диска:
    file, err := os.Open("audio.mp3")
    		if err != nil {
    			panic(err)
    		}
    		defer file.Close()
    
    		audioUpload := tgbotapi.NewAudioUpload(update.Message.Chat.ID, tgbotapi.FileReader{
    			Name:   "audio.mp3",
    			Reader: file,
    			Size:   -1, // If Size is -1, it will read the entire Reader into memory to calculate a Size.
    		})
    		audioUpload.ReplyToMessageID = update.Message.MessageID
    		_, err := bot.Send(audioUpload)
    		if err != nil {
    			panic(err)
    		}



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

    В данном примере реализована отправка только текста и картинок. Чтобы добавить обработку других типов сообщений, нужно добавить новый `case` в `switch` в функции `OnMessage`:
    Код
    package main
    
    import (
    	"log"
    
    	"github.com/davecgh/go-spew/spew"
    	"github.com/go-telegram-bot-api/telegram-bot-api"
    )
    
    func main() {
    	// подключаемся к боту с помощью токена
    	bot, err := tgbotapi.NewBotAPI("ТОКЕН")
    	if err != nil {
    		log.Panic(err)
    	}
    
    	bot.Debug = true
    	log.Printf("Authorized on account %s", bot.Self.UserName)
    
    	// инициализируем канал, куда будут прилетать обновления от API
    	u := tgbotapi.NewUpdate(0)
    	u.Timeout = 60
    
    	updates, err := bot.GetUpdatesChan(u)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// читаем обновления из канала
    	for update := range updates {
    		switch {
    		case update.Message != nil: // Если было прислано сообщение, то обрабатываем, так как могут приходить не только сообщения.
    			OnMessage(bot, update.Message)
    		}
    	}
    }
    
    func OnMessage(bot *tgbotapi.BotAPI, message *tgbotapi.Message) {
    	// Пользователь, который написал боту
    	userName := message.From.UserName
    
    	// ID чата/диалога.
    	// Может быть идентификатором как чата с пользователем
    	// (тогда он равен UserID) так и публичного чата/канала
    	chatID := message.Chat.ID
    
    	log.Printf("[%s] %d", userName, chatID)
    
    	spew.Dump(message) // выводим то что пришло (Для отладки!!!)
    
    	var msg tgbotapi.Chattable
    	switch {
    	case message.Text != "": // Текстовое ли сообщение?
    		msg = tgbotapi.NewMessage(chatID, message.Text)
    
    	case message.Photo != nil: // Это фото?
    		photoArray := *message.Photo
    		photoLastIndex := len(photoArray) - 1
    		photo := photoArray[photoLastIndex] // Получаем последний элемент массива (самую большую картинку)
    		msg = tgbotapi.NewPhotoShare(chatID, photo.FileID)
    
    	default:                                                 // Если не одно условие не сработало
    		msg = tgbotapi.NewMessage(chatID, "Не реализовано") // Отправляется на тот тип сообщения, который ещё не реализован выше ^
    	}
    
    	// и отправляем его
    	_, err := bot.Send(msg)
    	if err != nil {
    		log.Println(err)
    	}
    }
    Ответ написан
    3 комментария
  • Почему на сайте ссылки в теге?

    @ghostiam
    На Go писатель, серверов пинатель.
  • Как передать в параметры запроса вложенный массив?

    @ghostiam
    На Go писатель, серверов пинатель.
    client := http.DefaultClient
    
    	form := url.Values{
    		"LoginForm[username]": []string{"user"},
    		"LoginForm[password]": []string{"pass"},
    	}
    
    	response, err := client.Post("http://httpbin.org/post", "application/x-www-form-urlencoded", strings.NewReader(form.Encode()))
    	if err != nil {
    		panic(err)
    	}
    	defer response.Body.Close()
    
    	b, err := ioutil.ReadAll(response.Body)
    	if err != nil {
    		panic(err)
    	}
    
    	println(string(b))
    Ответ написан
    4 комментария
  • Как выложить проект на username.github.io?

    @ghostiam
    На Go писатель, серверов пинатель.
    Старый вариант
    Как вариант, могу предложить следующее.
    Создать новый репозиторий и первым коммитом сделать пустой коммит, для того чтобы можно было в разных ветках хранить разные файлы:
    git init && git commit --allow-empty -m "Initial commit"

    дальше в ветку dev коммитите исходники, а в ветку master файлы из директории dist


    UPD. 27.11.2019
    Спустя почти год после ответа на этот вопрос, наткнулся на очень интересный способ с использованием git submodules.
    https://gohugo.io/hosting-and-deployment/hosting-o...

    Суть способа:
    Делаем директорию dist сабмодулем, который ведёт к вашему репозиторию-сайту (сам код сайта храниться в отдельном репозитории)
    git submodule add -b master git@github.com:<USERNAME>/<USERNAME>.github.io.git dist


    После этого сайт заливать/обновлять так:
    # Build the project.
    yarn build
    # npm run build
    
    # Go To dist folder
    cd dist
    
    # Add changes to git.
    git add .
    
    # Commit changes.
    git commit -m "rebuilding site $(date)"
    
    # Push source and build repos.
    git push origin master
    Ответ написан
    5 комментариев
  • Существует ли top/exporter для TCP protocol operations(Состояния сеанса TCP) в разрезе процесов?

    @ghostiam
    На Go писатель, серверов пинатель.
    iftop
    nethogs
    netstat -tup
    Ответ написан
    Комментировать
  • Как с помощью ардуино положить данные на удаленный сервер по URL?

    @ghostiam
    На Go писатель, серверов пинатель.
    Вы пытаетесь подключиться к серверу по домену, но соединение нельзя установить на домен, можно только на IP.
    Для решения этой проблемы, существуют сервисы DNS которые преобразуют доменное имя в IP адрес.
    Вам нужно или найти библиотеку для работы с DNS или написать запросы вручную.
    Ответ написан
    Комментировать
  • Как вывести данные с базы, если id пользователя нет в другой таблице?

    @ghostiam
    На Go писатель, серверов пинатель.
    SELECT *
    FROM table1 AS t1
    WHERE t1.text_id NOT IN (
       SELECT t2.text_id 
       FROM table2 AS t2
       WHERE t2.user_id = 42
    )

    замените 42 на реальный ID пользователя
    Ответ написан
    5 комментариев
  • Можно ли получить данные из двух таблиц, где данные второй таблицы зависят от первой?

    @ghostiam
    На Go писатель, серверов пинатель.
    SELECT *
    FROM table1 AS t1
    LEFT JOIN table2 AS t2 ON t1.id=t2.id
    Ответ написан
    2 комментария
  • Не могу написать регулярку?

    @ghostiam
    На Go писатель, серверов пинатель.
    Такая?
    [a-zA-Z]+_[a-zA-Z]+
    https://regex101.com/r/cO8lqs/6540

    Сгенерированный код:
    $re = '/[a-zA-Z]+_[a-zA-Z]+/';
    $str = 'Name_Surname
    qwwer_asdasd';
    
    preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
    
    // Print the entire match result
    var_dump($matches);
    Ответ написан
    8 комментариев
  • Ошибка в Mysql. Что делать?

    @ghostiam
    На Go писатель, серверов пинатель.
    обратные кавычки используются для имён таблиц\столбцов в бд, для текста вам нужны простые одинарные кавычки:
    SELECT `avatar` FROM `users` WHERE `nickname` = 'test';
    Ответ написан
    Комментировать
  • Почему при заходе на сайт https://core.telegram.org возникает ошибка: "Ошибка при установлении защищённого соединения"?

    @ghostiam
    На Go писатель, серверов пинатель.
    IP 5.3.3.17 российский, если верить сервису https://ipinfo.io/5.3.3.17
    значит, у вас подменили DNS ответ и заменили в нём настоящий IP.
    В таком случае не поможет и VPN, так как у вас уже подменили IP.

    Вам нужно или заменить DNS провайдера, например на 1.1.1.1 (CloudFlare) или 8.8.8.8 (Google), или, если ваш провайдер перехватывает и подменяет любые DNS ответы, то использовать уже DNSSec.

    Вот ответ от DNS у меня:
    $ dig core.telegram.org
    ...
    
    ;; ANSWER SECTION:
    core.telegram.org.	600	IN	A	149.154.167.99
    
    ...
    Ответ написан
    Комментировать