Konstantin
Alexander
мммм
Alexander
а что там строить? INSERT INTO table(field1, field2,...) VALUES (?, ?, ...)
Alexander
?
Konstantin
?
INSERT INTO table(field1, field2,...) VALUES (?, ?, ...), (?,?, ...) ...
Konstantin
И так далее
Alexander
но этот драйвер же так не работает
Alexander
var (
tx, _ = connect.Begin()
stmt, _ = tx.Prepare("INSERT INTO example (country_code, os_id, browser_id, categories, action_day, action_time) VALUES (?, ?, ?, ?, ?, ?)")
)
defer stmt.Close()
for i := 0; i < 100; i++ {
if _, err := stmt.Exec(
"RU",
10+i,
100+i,
clickhouse.Array([]int16{1, 2, 3}),
time.Now(),
time.Now(),
); err != nil {
log.Fatal(err)
}
}
if err := tx.Commit(); err != nil {
log.Fatal(err)
}
Alexander
Konstantin
зачем так делать?
Сам увидел этот код только вчера)
tableName = "pool_" + tableName + "_main"
start := time.Now()
query := "INSERT INTO " + dbName + "." + tableName + " ("
log.Println("Try insert into ", tableName)
for _, v := range fields {
query += v + ","
}
query = query[0:len(query)-1] + ") VALUES " + forPrep[:len(forPrep)-1]
log.Println("Try start transaction")
transaction, errTx := c.Link.Begin()
if errTx != nil {
log.Println("Transaction begin error: ", errTx)
return
}
log.Println("Transaction started")
stmt, err := transaction.Prepare(query)
if err != nil {
log.Println(err)
}
defer stmt.Close()
log.Println("Preparing is complete ", time.Since(start))
t := time.Now()
fldCntr := 0
var valuesPrepared []interface{}
for _, v := range values {
valuesPrepared = append(valuesPrepared, v)
fldCntr++
if fldCntr >= len(fields)-1 {
fldCntr = 0
var concatPrepared []interface{}
ms := time.Since(t).Microseconds()
x := rand.Intn(1000000)
hash := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%v", ms)+fmt.Sprintf("%v", time.Now())+fmt.Sprintf("%v", x))))
concatPrepared = append(concatPrepared, hash)
concatPrepared = append(concatPrepared, valuesPrepared...)
stmt.Exec(concatPrepared...)
valuesPrepared = []interface{}{}
}
}
log.Println("Try commit")
txError := transaction.Commit()
log.Println("Commit done")
if txError != nil {
log.Println("Transaction end error: ", txError)
}
log.Println("End insert")
Bagasl
Сам увидел этот код только вчера)
tableName = "pool_" + tableName + "_main"
start := time.Now()
query := "INSERT INTO " + dbName + "." + tableName + " ("
log.Println("Try insert into ", tableName)
for _, v := range fields {
query += v + ","
}
query = query[0:len(query)-1] + ") VALUES " + forPrep[:len(forPrep)-1]
log.Println("Try start transaction")
transaction, errTx := c.Link.Begin()
if errTx != nil {
log.Println("Transaction begin error: ", errTx)
return
}
log.Println("Transaction started")
stmt, err := transaction.Prepare(query)
if err != nil {
log.Println(err)
}
defer stmt.Close()
log.Println("Preparing is complete ", time.Since(start))
t := time.Now()
fldCntr := 0
var valuesPrepared []interface{}
for _, v := range values {
valuesPrepared = append(valuesPrepared, v)
fldCntr++
if fldCntr >= len(fields)-1 {
fldCntr = 0
var concatPrepared []interface{}
ms := time.Since(t).Microseconds()
x := rand.Intn(1000000)
hash := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%v", ms)+fmt.Sprintf("%v", time.Now())+fmt.Sprintf("%v", x))))
concatPrepared = append(concatPrepared, hash)
concatPrepared = append(concatPrepared, valuesPrepared...)
stmt.Exec(concatPrepared...)
valuesPrepared = []interface{}{}
}
}
log.Println("Try commit")
txError := transaction.Commit()
log.Println("Commit done")
if txError != nil {
log.Println("Transaction end error: ", txError)
}
log.Println("End insert")
Ужасы какие, зачем вообще делать sprintf + sprintf
Alexander
ахаха)
Alexander
да тут как бы понятно чем пахнет
Konstantin
Konstantin
)))
Alexander
мне еще нравится, что мы внутри транзакции делаем недешевые вычисления
Alexander
но опять же, надо сначала профилировать, потом уже оптимизировать. в go прекрасный инструмент для этого
Konstantin
Спасибо! Буду разгребать
Alexander
это лучше переписать:
1. Формируем данные (можно и 10к, не всегда при вставке 1М сильно быстрее)
2. Опционально сортируем по primary key
3. стартуем транзакцию
4. готовим простой стейтмент
5. обходим данные из пункта 1 и по строке вставляем стейтмент
6. коммитим
Alexander
если уже после профайлинга, оптимизации и такого переписывания будет упираться во вставку, то пиши
Konstantin
Konstantin
У кого-нибудь есть проекты свои на github?
Интересует построение структуры проектов
Bagasl
Null
➡️ Связанный список в Golang
https://uproger.com/svyazannyj-spisok-v-golang/
@Golang_google
ZeroX
А нафига они нужны если есть interface{}
Bagasl
Как в функции, так и при возврате из нее
Alexander
Aртем
Как задать прокси для get запросов при парсинге?
Anonymous
указываешь в среде прокси
Anonymous
и все
Alexander
а как в одном процессе несколько разных прокси юзать?
Alexander
тогда
Alexander
что за нереалистичный кейс, когда у тебя одна прокся на все?
Anonymous
хорошо, тогда создаешь переменные
proxy1, err := парсишь тут первый прокси
proxy2, err := парсишь второй прокси
потом указываешь какой тебе нужен
Anonymous
он не говорил, что ему нужна многозадачность
Alexander
Всем привет! Вопросец возник. У меня в бд лежит json разного формата, мне нужно его вывести в ответ на запрос(работаю через gin) но он эскейпает все кавычки и выводить как строку. Как сериализовать эту строку и вывести как json объект?
Anonymous
фронт посылает запрос, а ты с бэка отвечаешь жсоном?
Alexander
Anonymous
json.NewEncoder(w).Encode(YourResponse)
Anonymous
можешь в переменную добавить, тогда не надо будет каждый раз врайтера указывать
Alexander
json.NewEncoder(w).Encode(YourResponse)
r.GET("/request-info/:requestId", func(c *gin.Context) {
requestId := c.Params.ByName("requestId")
requestInfo := getRequestInfo(requestId)
jsonResponse := json.NewEncoder(c.Writer).Encode(requestInfo)
c.JSON(http.StatusOK, jsonResponse)
})
Alexander
так имеешь в виду?
Alexander
У меня такой объект сейчас возвращается:
{
"req_id": "5678947c-deeb-4c39-9b2e-971affc35358",
"req_action": "geteod",
"req_method": "",
"req_path": "",
"req_data": "{\"Action\":\"geteod\",\"apiVersion\":\"v0.6\",\"acceptLanguage\":\"EN\",\"X-Request-ID\":\"5678947c-deeb-4c39-9b2e-971affc35358\"}",
"res_data": "{\"version\":\"v0.6\",\"isOperationDayOpen\":1,\"iabsInfo\":{\"errorCode\":0,\"httpResponseCode\":200}}",
"state": "1",
"created_on": "2020-04-13T11:15:49+05:00",
"x_initiator": "",
"x_channel": ""
}
Anonymous
Alexander
мне нужно поля req_data и res_data сериализовать
Alexander
Anonymous
а почему изначальный вариант не работает?
Alexander
в структуре поля нужно как-то типизировать ? Чтобы не просто стринг были
Anonymous
c.JSON() вроде бы сразу сериализует
Alexander
c.JSON() вроде бы сразу сериализует
Там когда маршализация происходит, он видит эти 2 поля как стринговые, видит в них двойные кавычки и экранирует. Может мне эти поля отдельно надо сериализовать?
Anonymous
Anonymous
такая?
Alexander
да
Anonymous
так тебе нужно указать, json:"name"
Alexander
так тебе нужно указать, json:"name"
type LogData struct {
ReqId string json:"req_id"
ReqAction string json:"req_action"
ReqMethod string json:"req_method"
ReqPath string json:"req_path"
ReqData string json:"req_data"
ResData string json:"res_data"
State string json:"state"
CreatedOn string json:"created_on"
XInitiator string json:"x_initiator"
XChannel string json:"x_channel"
}
Anonymous
а
Anonymous
тогда попробуй
Anonymous
test, err := json.Marshal(ClientData)
c.JSON(200, test)
Alexander
Он в байты переводит. Надо делать string() ?
Alexander
ReqData string json:"req_data"
ResData string json:"res_data" сделай типа interface{} и десериализуй в них
Alexander
потом уже целиком весь объект сериализуй
Alexander
Alexander
вот именно
Anonymous
я так делал
Alexander
это конечно немного накладно, можно просто туда какие-то строки, которые будешь потом заменять
Alexander
https://pkg.go.dev/encoding/json#RawMessage
Alexander
вот, кстати
Alexander
{
"response": {
"req_id": "5678947c-deeb-4c39-9b2e-971affc35358",
"req_action": "geteod",
"req_method": "",
"req_path": "",
"req_data": "IntcIkFjdGlvblwiOlwiZ2V0ZW9kXCIsXCJhcGlWZXJzaW9uXCI6XCJ2MC42XCIsXCJhY2NlcHRMYW5ndWFnZVwiOlwiRU5cIixcIlgtUmVxdWVzdC1JRFwiOlwiNTY3ODk0N2MtZGVlYi00YzM5LTliMmUtOTcxYWZmYzM1MzU4XCJ9Ig==",
"res_data": "IntcInZlcnNpb25cIjpcInYwLjZcIixcImlzT3BlcmF0aW9uRGF5T3BlblwiOjEsXCJpYWJzSW5mb1wiOntcImVycm9yQ29kZVwiOjAsXCJodHRwUmVzcG9uc2VDb2RlXCI6MjAwfX0i",
"state": "1",
"created_on": "2020-04-13T11:15:49+05:00",
"x_initiator": "",
"x_channel": ""
}
}
Alexander
c.JSON(http.StatusOK, gin.H{"response": requestInfo})
Alexander
result.ReqData, _ = json.Marshal(reqData)
result.ResData, _ = json.Marshal(resData)
Anonymous
ну так получилось же
Alexander
не то, но я скинул уже лучше вариант
Anonymous
кстати тебя устраивает такой формат времени?
Alexander
Anonymous
2 поля