Hyperledger Fabric의 Chaincode를 개발할 상황이 생기면서 Go언어를 사용할 일이 생겼다.
한 번쯤 배우고 싶었던 언어이고 필요성이 생긴 만큼 간단한 API 서버 개발을 통해 Go언어에 익숙해지기 위해서 간단한 API 서버를 개발해봤다.
package model
type Message struct {
ID string `json:"id"`
Msg string `json:"msg"`
}
DB에 저장하기 위한 데이터 형태를 선언한 부분이다. 데이터는 ID 값과 메시지 값을 저장할 수 있게 선언했다.
package db
import (
"database/sql"
"fmt"
model "example.com/practice/model"
_ "github.com/lib/pq"
)
const (
host = "localhost"
port = 5432
user = "postgres"
password = "postgres"
dbname = "postgres"
)
func connect() *sql.DB {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
dbcon, err := sql.Open("postgres", psqlInfo)
if err != nil || dbcon.Ping() != nil {
panic(err.Error())
}
return dbcon
}
func GetMessage(id string) []model.Message {
db := connect()
selectDynStmt := `SELECT id, msg FROM Message where "id"=$1`
rows, err := db.Query(selectDynStmt, id)
messages := []model.Message{}
checkError(err)
defer db.Close()
defer rows.Close()
for rows.Next() {
var msg model.Message
if err := rows.Scan(&msg.ID, &msg.Msg); err != nil {
panic(err)
}
messages = append(messages, msg)
}
return messages
}
func SaveMessage(msg model.Message) sql.Result {
db := connect()
if db.Ping() != nil {
panic(db.Ping().Error())
}
insertDynStmt := `insert into Message ("id", "msg") values($1, $2)`
result, err := db.Exec(insertDynStmt, msg.ID, msg.Msg)
checkError(err)
defer db.Close()
return result
}
func UpdateMessage(msg model.Message) sql.Result {
db := connect()
if db.Ping() != nil {
panic(db.Ping().Error())
}
updateDynStmt := `update Message set "msg"=$1 where "id"=$2`
result, err := db.Exec(updateDynStmt, msg.Msg, msg.ID)
checkError(err)
defer db.Close()
return result
}
func DeleteMessage(id string) sql.Result {
db := connect()
if db.Ping() != nil {
panic(db.Ping().Error())
}
deleteDynStmt := `delete from Message where "id"=$1`
result, err := db.Exec(deleteDynStmt, id)
checkError(err)
defer db.Close()
return result
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
PostgreSQL과 연결하고 간단한 CRUD 작업을 하는 부분입니다.
package router
import (
"log"
"net/http"
db "example.com/practice/db"
model "example.com/practice/model"
"github.com/gin-gonic/gin"
)
func StartRouter() {
router := gin.Default()
router.GET("/message/:id", func(c *gin.Context) {
id := c.Param("id")
result := db.GetMessage(id)
c.IndentedJSON(http.StatusOK, result)
})
router.POST("/message", func(c *gin.Context) {
var newMessage model.Message
if err := c.BindJSON(&newMessage); err != nil {
log.Fatal("BIND JSON ERROR")
return
}
result := db.SaveMessage(newMessage)
c.IndentedJSON(http.StatusCreated, result)
})
router.PUT("/message", func(c *gin.Context) {
var updateMessage model.Message
if err := c.BindJSON(&updateMessage); err != nil {
log.Fatal("BIND JSON ERROR")
return
}
result := db.UpdateMessage(updateMessage)
c.IndentedJSON(http.StatusAccepted, result)
})
router.DELETE("/message", func(c *gin.Context) {
var deleteMessage model.Message
if err := c.BindJSON(&deleteMessage); err != nil {
log.Fatal("BIND JSON ERROR")
return
}
result := db.DeleteMessage(deleteMessage.ID)
c.IndentedJSON(http.StatusAccepted, result)
})
router.Run("localhost:8080")
}
간단한 REST API를 routing 하는 부분입니다.