func sqlToJson(res *sql.Rows) ([]byte, error) {
// создаем массив названий столбцов таблицы
arrNamesColumns, _ := res.Columns()
// получаем количество столбцов
kolColumns := len(arrNamesColumns)
// создаем отображения которое по ключу (названию столбца) будет хранить срез всех записей данного столбца
resMap := make(map[string][]interface{}, kolColumns)
// создаем срез который будет хранить все поля текущий строки таблицы в массиве байт
tempLineByte := make([][]byte, kolColumns)
// создаем срез который будет хранить ссылки на поля предыдущего среза
// это нужно для метода Scan который принимает interface по ссылке таким образом записывая в него данные
pTempLineByte := make([]interface{}, kolColumns)
for i := 0; i < kolColumns; i++ {
pTempLineByte[i] = &tempLineByte[i]
}
// создаем срез который будет хранить все поля текущий строки в соответствующим типе данных
tempLine := make([]interface{}, kolColumns)
// перебираем все строки тоблицы
for res.Next() {
// метод Scan записывает в срез tempLineByte текущую строку через срез pTempLineByte который хранит ссылки на поля tempLineByte
err := res.Scan(pTempLineByte...)
if err != nil {
return nil, err
}
// перебираем все поля текущей строки
for i := 0; i < kolColumns; i++ {
// преобразовываем байтовое значение в значение соответствующего формата
json.Unmarshal(tempLineByte[i], &tempLine[i])
// если записалось значение nil то в поле была строка
if tempLine[i] == nil {
// добавляем значения в соответствующий ключу срез отображения resMap преобразуя его в строку
resMap[arrNamesColumns[i]] = append(resMap[arrNamesColumns[i]], string(tempLineByte[i]))
} else {
// иначе добавлять в срез соответствующие значения tempLine
resMap[arrNamesColumns[i]] = append(resMap[arrNamesColumns[i]], tempLine[i])
}
}
}
// преобразовываем отображения в json и возвращаем в массиве байт
return json.Marshal(resMap)
// p.s. чтобы получить привычный json нужно просто преобразовать этот массив байт в строку
// также, может понадобится убрать из этой строки символы переноса \n которые могут быть в текстовых полях базы данных, так как с ними json считается неликвидным
}
<input type="radio">
func sendAudio(ip int, fileName string) {
// Открываем файл
file, err := os.Open(fileName)
if err != nil {
log.Fatalln(err)
}
// Закрываем файл по завершению
defer file.Close()
// Буфер для хранения нашего тела запроса в виде байтов
var requestBody bytes.Buffer
// Создаем писателя
multiPartWriter := multipart.NewWriter(&requestBody)
// Инициализируем поле
fileWriter, err := multiPartWriter.CreateFormFile("audio", fileName)
if err != nil {
log.Fatalln(err)
}
// Скопируйте содержимое файла в поле
_, err = io.Copy(fileWriter, file)
if err != nil {
log.Fatalln(err)
}
// Заполняем остальные поля
fieldWriter, err := multiPartWriter.CreateFormField("normal_field")
if err != nil {
log.Fatalln(err)
}
_, err = fieldWriter.Write([]byte("Value"))
if err != nil {
log.Fatalln(err)
}
// Закрываем запись данных
multiPartWriter.Close()
// Создаем объект реквеста
req, err := http.NewRequest("POST", "https://api.telegram.org/bot[ТОКЕН БОТА]/sendAudio?chat_id=[chat_id]", &requestBody)
if err != nil {
log.Fatalln(err)
}
// Получаем и устанавливаем тип контента
req.Header.Set("Content-Type", multiPartWriter.FormDataContentType())
// Отправляем запрос
client := &http.Client{}
_, err = client.Do(req)
if err != nil {
log.Fatalln(err)
}
}