이전 포스팅에 이어 DB 연동 중 Insert만 해보겠습니다.
종료된 mariadb docker 실행.

기존 테이블에 id 컬럼 AUTO_INCREMENT 추가. (이전에 잊었습니다.)
ALTER TABLE Device MODIFY id INT AUTO_INCREMENT;

debug결과, DB결과, 호출
curl -X POST -H "Content-Type: application/json" -d '{"name":"iPhone19","mac":"11:11:11:22:33:aa"}' http://localhost:8000/v1.0/device



중요한건
DB연동시 "defer db.Close()" 를 꼭 한다는 것입니다.
golang에서 함수가 종료되고 나면 GC에서 정리될 때 Close 될까 싶었는데 실제로 되지 않았었습니다.
그 당시 단위 테스트 당시에 바로 발견되어 경험할 수 있어서 다행이었습니다.
4~5년 전 당시 경험이라 지금 버전에서 어떤지 확인해 보면 다를 수 있지만,
정석대로 "defer db.Close()" 추천해 드립니다.
package main
import (
"database/sql"
"encoding/json"
"fmt"
_ "github.com/go-sql-driver/mysql"
"net/http"
"strings"
)
type Device struct {
Id int `json:"id"`
Name string `json:"name"`
Mac string `json:"mac""`
}
func main() {
http.HandleFunc("/v1.0/device", func(res http.ResponseWriter, req *http.Request) {
if req.Method == http.MethodPost {
// DB Insert는 다음에
var device Device
err := json.NewDecoder(req.Body).Decode(&device)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
return
}
// DB insert
fmt.Printf("Name=%s,Mac=%s\n", device.Name, device.Mac)
// 맥은 ":", "-", "." 등 여러가지가 올 수 있지만 예제에서는 ":"만 처리 하겠습니다.
tmpMac := strings.Replace(device.Mac, ":", "", -1)
db, err := sql.Open("mysql", "TheGolangOfFuture:TheGolangOfFuture@tcp(127.0.0.1:3306)/TheGolangOfFuture")
if err != nil {
fmt.Printf(err.Error())
return
}
defer db.Close()
// 아래코드는 사실상 너무나 취약합니다. 예제니깐 방어는 보류 하겠습니다. 농담으로 현업에 이대로 쓰면 사직서 쓰게될 수 있습니다.
query := fmt.Sprintf("INSERT INTO Device (name, mac, mac_bin) VALUES('%s', '%s', unhex('%s'))", device.Name, device.Mac, tmpMac)
fmt.Println(query)
insert, err := db.Query(query)
if err != nil {
fmt.Println(err.Error())
return
}
defer insert.Close()
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"messages": fmt.Sprintf("Post success : %s", device.Mac),
})
} else if req.Method == http.MethodGet {
// DB select는 다음에
} else {
// 나머지 메소드는 거부로
res.WriteHeader(http.StatusMethodNotAllowed)
}
})
http.ListenAndServe(":8000", nil)
}