GoでSQL発行時に渡す変数を可変にする
Web画面に複数のチェックボックスが表示されていて、ユーザが自由に任意の数を選択してsubmitされたりした場合、IN句が可変になったりする場合がある。
どうやって可変長の変数を渡すのだろう?というのが気になった。
で、試行錯誤の末、以下のようにしたら動いた。
まずこんな感じのdocker-compose.yamlを用意してdocker-composeでPostgreSQLを起動しておいて、
services: db: image: postgres:14 container_name: postgresql ports: - 5432:5432 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_INITDB_ARGS: "--no-locale" volumes: - ./pgdata:/var/lib/postgresql/data - ./pginit:/docker-entrypoint-initdb.d
以下のようなコードにしたらうまくいった。ポイントは、any型の配列に渡したい変数を格納するのと、関数呼び出し時にその変数を渡しつつ、変数の後に...と書く、というところ。
package main import ( "database/sql" "log" _ "github.com/lib/pq" ) func main() { conn, err := sql.Open("postgres", "host=127.0.0.1 port=5432 dbname=postgres user=postgres password=postgres sslmode=disable") if err != nil { log.Fatal(err) } defer conn.Close() _, err = conn.Exec(`DROP TABLE IF EXISTS a;`) if err != nil { log.Println(err) return } _, err = conn.Exec(`CREATE TABLE a(id integer, value text)`) if err != nil { log.Fatal(err) } _, err = conn.Exec(`INSERT INTO a VALUES(1, 'あ')`) if err != nil { log.Fatal(err) } _, err = conn.Exec(`INSERT INTO a VALUES(2, 'い')`) if err != nil { log.Fatal(err) } _, err = conn.Exec(`INSERT INTO a VALUES(3, 'う')`) if err != nil { log.Fatal(err) } // any型の配列にする bind := []any{"あ", "い"} // 最後に...をつける rows, err := conn.Query(`SELECT id, value FROM a WHERE value IN ($1, $2)`, bind...) if err != nil { log.Fatal(err) } for rows.Next() { var id int var value string err = rows.Scan(&id, &value) if err != nil { log.Fatal(err) } log.Println(id, value) } }