카테고리 없음
golang REST API / go언어 REST API 서버 #4 DB연동 Select / METHOD GET
미래의 고
2023. 3. 18. 22:21
다음과 같은 구조로 계속 포스팅을 하려 합니다.
POST /device -> Device 아이템 추가 (포스팅 완료) / curl -X POST -H "Content-Type: application/json" -d '{"name":"iPhone19","mac":"ff:11:11:22:33:11"}' http://localhost:8000/v1.0/device
GET /device -> Device 아이템 리스트 조회 (진행중) / curl -X GET -H "Content-Type: application/json" -d '{}' http://localhost:8000/v1.0/device
GET /device/{pk} -> Device 아이템 조회
PUT /device/{pk} -> Device 아이템 수정
DELETE /device/{pk} -> Device 아이템 삭제
현재까지 다음과 같이 데이터가 있습니다. IDEA에서 테이블 확인한 결과입니다.
이전에, 터미널에서 보면 binary가 깨져 보이죠? IDEA에서는 헥사로 잘 보입니다.
하지만 이번 포스팅엔 binary와 아무런 상관없습니다.
IDEA에서 Database Browser 보다가 갑자기 생각나서 찍어봤습니다.

mariaDB에서 바이너리를 text로 디코드 해서 보려면 hex 함수를 쓰면 됩니다.

이제 저 데이터중에 '아이템 리스트 조회'를 포스팅 해보겠습니다.

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"`
}
const (
httpPort = ":8000"
driverName = "mysql"
dataSourceName = "TheGolangOfFuture:TheGolangOfFuture@tcp(127.0.0.1:3306)/TheGolangOfFuture"
)
func device(res http.ResponseWriter, req *http.Request) {
db, err := sql.Open(driverName, dataSourceName)
if err != nil {
fmt.Printf(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
defer db.Close()
if req.Method == http.MethodPost {
var device Device
err := json.NewDecoder(req.Body).Decode(&device)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
return
}
fmt.Printf("[POST] Name=%s,Mac=%s\n", device.Name, device.Mac) // DB insert
tmpMac := strings.Replace(device.Mac, ":", "", -1) // 맥은 ":", "-", "." 등 여러가지가 올 수 있지만 예제에서는 ":"만 처리 하겠습니다.
query := fmt.Sprintf("INSERT INTO Device (name, mac, mac_bin) VALUES('%s', '%s', unhex('%s'))", device.Name, device.Mac, tmpMac) // 이코드는 사실상 너무나 취약합니다.
insert, err := db.Query(query)
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
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 {
// 페이징은 생략하겠습니다.
// 1개 Item Get은 다음 포스팅에
rs, err := db.Query("SELECT id, name FROM Device")
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
defer rs.Close()
var result []Device
for rs.Next() {
var d Device
err := rs.Scan(&d.Id, &d.Name)
if err != nil {
fmt.Println(err.Error())
res.WriteHeader(http.StatusInternalServerError)
return
}
result = append(result, d)
}
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
json.NewEncoder(res).Encode(map[string]interface{}{
"success": true,
"data": result,
})
} else {
res.WriteHeader(http.StatusMethodNotAllowed) // 나머지 메소드는 허용안함
}
}
func main() {
fmt.Println("Start WEB", httpPort)
http.HandleFunc("/v1.0/device", device)
http.ListenAndServe(httpPort, nil)
}