SQLite3란?
SQLite는 MySQL나 PostgreSQL와 같은 데이터베이스 관리 시스템이지만, 서버가 아니라 응용 프로그램에 넣어 사용하는 비교적 가벼운 데이터베이스이다.
일반적인 RDBMS(관계형 데이터베이스)에 비해 대규모 작업에는 적합하지 않지만, 중소 규모라면 속도에 손색이 없다. 또 API는 단순히 라이브러리를 호출하는 것만 있으며, 데이터를 저장하는 데 하나의 파일만을 사용하는 것이 특징이다. -위키 백과-
즉 MySQL이나 MsSQL, Oracle DB 는 데이터 베이스를 설치하고 운영되는 서버가 있어야 한다.
하지만 SQLite는 간단하게 파일로만 동작한다.
tdm-gcc 설치하기
Go언어 에서 SQLite를 사용할 경우 go-sqlite3 라는 외부 패키지를 사용한다.
이때 Go언어에서 C Go 기능을 사용하는데, C언어의 라이브러리를 사용한다는 의미 이다.
하지만 문제는 표준 C언어를 컴파일 할 수 있어야 한는데 표준 C언어를 컴파일 하기 위해선 표준 컴파일러가 있어야 한다.
표준 컴파일러 중 Go언어 에서는 gcc를 사용한다.
하지만 MS window에서는 리눅스 기반인 gcc를 지원하지 않는다.
그러나 MS window에서도 gcc가 돌아 갈 수 있는 환경을 만들어 주는 것이 MinGW 라고 한다.
그러므로 MS window상에서 리눅스 표준 컴파일러 사용하기 위해선 MinGW를 이용하여 환경을 만든 후 gcc를 사용해야 한다.
https://jmeubank.github.io/tdm-gcc/download/
위의 주소로 접속 후 다운로드 및 설치
minGW 실행
go-sqlite3설치
go get github.com/mattn/go-sqlite3
SQLite3 사용하기
ex) model.go
package model
import (
"time"
)
type Todo struct {
ID int `json:"id"`
Name string `json:"name"`
Completed bool `json:"completed"`
CreatedAt time.Time `json:"created_at"`
}
// 인터페이스 생성
type dbHandler interface {
getTodos() []*Todo
addTodo(name string) *Todo
removeTodo(id int) bool
completeTodo(id int, complete bool) bool
}
// 인터페이스의 인터페이스를 가지고 있음
var handler dbHandler
func init() {
// handler = newMemoryHandler()
handler = newSqliteHandler()
}
func GetTodos() []*Todo {
return handler.getTodos()
}
func AddTodo(name string) *Todo {
return handler.addTodo(name)
}
func RemoveTodo(id int) bool {
return handler.removeTodo(id)
}
func CompleteTodo(id int, complete bool) bool {
return handler.completeTodo(id, complete)
}
ex) memoryHandler.go
package model
import "time"
// 기존의 메모리 맵을 별도 스트럭터로 만듦
type memoryHandler struct {
todoMap map[int]*Todo
}
// memoryHandler의 메서드
func (m *memoryHandler) getTodos() []*Todo {
list := []*Todo{}
for _, v := range m.todoMap {
// map의 인덱스 만큼 반복
// 키는 받지않고 value만 받음
list = append(list, v)
// list에 v값을 어팬드
}
return list
}
func (m *memoryHandler) addTodo(name string) *Todo {
id := len(m.todoMap) + 1 // map의 갯수만큼 id
todo := &Todo{id, name, false, time.Now()} // 포인터형 구조체 Todo를 생성
m.todoMap[id] = todo // todo의 데이터를 맵에 넣음
return todo
}
func (m *memoryHandler) removeTodo(id int) bool {
if _, ok := m.todoMap[id]; ok {
delete(m.todoMap, id)
return true
}
return false
}
func (m *memoryHandler) completeTodo(id int, complete bool) bool {
if todo, ok := m.todoMap[id]; ok { // 맵에 있는지 확인
todo.Completed = complete // 맵에 있는경우 변경
return true
}
return false
}
func newMemoryHandler() dbHandler {
m := &memoryHandler{}
m.todoMap = make(map[int]*Todo)
return m
}
ex) sqliteHandler.go
package model
import (
"database/sql"
"os"
_ "github.com/mattn/go-sqlite3"
)
type sqliteHandler struct {
db *sql.DB
}
func (s *sqliteHandler) getTodos() []*Todo {
return nil
}
func (s *sqliteHandler) addTodo(name string) *Todo {
return nil
}
func (s *sqliteHandler) removeTodo(id int) bool {
return false
}
func (s *sqliteHandler) completeTodo(id int, complete bool) bool {
return false
}
// 데이터 베이스를 열면 사라지기전에 닫아줘야함
func (s *sqliteHandler) close() {
s.db.Close()
}
func newSqliteHandler() dbHandler {
os.Remove("./test.db")
database, err := sql.Open("sqlite3", "./test.db")
if err != nil {
panic(err)
}
statement, _ := database.Prepare(
`CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
completed BOOLEAN,
createdAt DATETIME
)`) // 테이블을 만드는 쿼리문
statement.Exec()
return &sqliteHandler{db: database}
}