最近、会社でGolangを使用したマイクロサービスの開発をやってました。
その際に、ちょっと詰まった部分があったのでメモがてら。
GolangでgorpというORMパッケージを使用してSQLでin
句を使用したい人の話。
そもそもGolangのGorpって何?
golangで使用できるORMパッケージ
https://github.com/go-gorp/gorp
SQLの文を直書きできて、構造体へのマッピングを行ってくれる。
個人的にSQLは直書きのままの方が嬉しいのでなかなか良いパッケージ。
だけど...?
結論だけ先に書いておく
結構無理矢理...
単純にいうとinterfaceを第3引数に渡せよってことなんだけど。
args := make([]interface{}, len(fileIds))
quarks := make([]string, len(fileIds))
for i, fileId := range fileIds {
args[i] = fileId
quarks[i] = "?"
}
var apps []*App
_, err := dbMap.Select(&apps, fmt.Sprintf("SELECT * FROM app WHERE file_id in (%s) ORDER BY id DESC", strings.Join(quarks, ",")), args...)
if err != nil {
return nil, err
}
参考:Golang SqlExecutor.Select Examples
公式のドキュメント読もう
最初PHP脳だったのでsliceを,
で展開して引数に渡せばいけると思ってたの...///
普通にドキュメント見たら。gorpではinterface渡せって書いてあった。
ちょっとプレースホルダーへの値の渡し方が特殊だったのでドキュメントちゃんと読もうや問題。
公式:https://gowalker.org/github.com/go-gorp/gorp#DbMap
同じように悩んでる人もいた
https://kabochapo.hateblo.jp/entry/2017/09/17/195805
type DbMap struct {
// Db handle to use with this map
Db *sql.DB
// Dialect implementation to use with this map
Dialect Dialect
TypeConverter TypeConverter
// ExpandSlices when enabled will convert slice arguments in mappers into flat
// values. It will modify the query, adding more placeholders, and the mapper,
// adding each item of the slice as a new unique entry in the mapper. For
// example, given the scenario bellow:
//
// dbmap.Select(&output, "SELECT 1 FROM example WHERE id IN (:IDs)", map[string]interface{}{
// "IDs": []int64{1, 2, 3},
// })
//
// The executed query would be:
//
// SELECT 1 FROM example WHERE id IN (:IDs0,:IDs1,:IDs2)
//
// With the mapper:
//
// map[string]interface{}{
// "IDs": []int64{1, 2, 3},
// "IDs0": int64(1),
// "IDs1": int64(2),
// "IDs2": int64(3),
// }
//
// It is also flexible for custom slice types. The value just need to
// implement stringer or numberer interfaces.
//
// type CustomValue string
//
// const (
// CustomValueHey CustomValue = "hey"
// CustomValueOh CustomValue = "oh"
// )
//
// type CustomValues []CustomValue
//
// func (c CustomValues) ToStringSlice() []string {
// values := make([]string, len(c))
// for i := range c {
// values[i] = string(c[i])
// }
// return values
// }
//
// func query() {
// // ...
// result, err := dbmap.Select(&output, "SELECT 1 FROM example WHERE value IN (:Values)", map[string]interface{}{
// "Values": CustomValues([]CustomValue{CustomValueHey}),
// })
// // ...
// }
ExpandSliceArgs bool
// contains filtered or unexported fields
}
Golang書ける人おいでよ
思った以上に書くことなかったので宣伝。
Golangを書けてマイクロサービスの開発をゴリゴリやっていきたいって人はうちの会社向いてると思うので是非カジュアル面談だけでも来てくださいまし!(Qiita Jobsで募集しています。)
プロジェクトでGolangを積極的に採用中でござんす。
👇👇👇👇👇バックエンドエンジニア募集中〜👇👇👇👇👇
https://jobs.qiita.com/employers/255/postings/1169