funcgetConnection() *sql.DB { // 연결 형태 -> 사용자명:비번@프로토콜(주소:포트)/데이터베이스명 db, err := sql.Open("mysql", "root@tcp(localhost:3306)/test") if err != nil || db.Ping() != nil { // 핑을 통해 네트워크 연결 및 DB 사용 가능한지 체크 panic(err) } db.SetConnMaxLifetime(time.Minute * 3) // 유휴 연결 시간 설정 (5분 미만으로 잡는 게 좋다고 함) db.SetMaxOpenConns(10) // 최대 연결 수 설정 db.SetMaxIdleConns(10) // 최대 유휴 연결 수 설정 return db }
// 여러 행이 있는 select 쿼리의 경우 funcfindByAll() []User { conn := getConnection() // 연결 객체 defer conn.Close() // 함수 종료 시 db 연결을 강제 끊는 것으로 연결 객체는 수명이 있고 많은 고루틴에 공유되도록 설계 되어 있다고 하니 굳이 종료를 할 필요는 없는듯.. rows, err := conn.Query("SELECT id, name FROM sample") if err != nil { panic(err) } defer rows.Close() // 함수 종료 시 닫아서 추가 열거를 방지 users := []User{} user := User{} for rows.Next() { err := rows.Scan(&user.id, &user.name) // 쿼리문에서 가져오는 필드 수와 받는 수가 동일 해야 오류가 안 난다. if err != nil { panic(err) } if user.id == 1 { user.name = "delryn" } users = append(users, user) } err = rows.Err() // 행을 반복하고 나서 오류 한번 더 확인 if err != nil { panic(err) } return users }
// 단일 행의 select 쿼리의 경우 funcfindByOne(id uint)User { conn := getConnection() defer conn.Close() user := User{} err := conn.QueryRow("SELECT id, name FROM sample WHERE id = ?", id).Scan(&user.id, &user.name) // 마찬가지로 필드 수와 받는 필드 수가 동일해야 함 if err != nil { panic(err) } return user }
// insert 쿼리 - 트랜잭션 funcsave(name string)int64 { conn := getConnection() defer conn.Close() tx, err := conn.Begin() // 트랜잭션 시작 if err != nil { tx.Rollback() panic(err) } query := fmt.Sprint("INSERT INTO sample(`name`) VALUES ('", name, "')") res, err := tx.Exec(query) // 쿼리 실행 if err != nil { tx.Rollback() // 에러난 경우 롤백 panic(err) } lastId, err := res.LastInsertId() // 쓸 일은 없을 꺼 같은데 걍 마지막 insert id 가지고 옴 if err != nil { tx.Rollback() panic(err) } tx.Commit() // 정상 실행되었으면 커밋 return lastId }
// update 쿼리의 경우도 동일하게 트랜잭션으로 시작, 실행 함수는 exec로 동일 funcupdate(id int64, name string) { conn := getConnection() defer conn.Close() tx, err := conn.Begin() if err != nil { tx.Rollback() panic(err) } query := fmt.Sprint("UPDATE sample SET name = '", name, "' WHERE id = ", id) _, err = tx.Exec(query) if err != nil { tx.Rollback() panic(err) } else { tx.Commit() } }
// 삭제 쿼리도 뭐 똑같음... funcdelete(id int64) { conn := getConnection() defer conn.Close() tx, err := conn.Begin() if err != nil { tx.Rollback() panic(err) } query := fmt.Sprint("DELETE FROM sample WHERE id = ", id) _, err = tx.Exec(query) if err != nil { tx.Rollback() panic(err) } tx.Commit() }