728x90

golang 에서 mysql 드라이버를 사용하기위해 라이브러리를 사용합니다.

 

http://github.com/go-sql-driver/mysql

 

GitHub - go-sql-driver/mysql: Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package

Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package - GitHub - go-sql-driver/mysql: Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package

github.com

 

고객 정보를 조회하는 간단한 예제를 만들어 보겠습니다.

 

먼저 고객에 대한 구조체 와  고객 정보가 담긴 Repository 인터페이스를 만듭니다.

 

package domain

type Customer struct {
	Id          string
	Name        string
	City        string
	Zipcode     string
	DateofBirth string
	Status      string
}

type CustomerRepository interface {
	FindAll() ([]Customer, error)
}

 

CustomerRepository 라는 인터페이스 대신 mock 객체를 만들어 test 테스트를 할수도 있습니다.

 

Golang 에서는 class 와 상속은 없지만 덕타이핑이 가능하도록 리시버 라는 기능을 제공합니다.

 

package domain

import (
	"database/sql"
	"log"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

type CustomerRepositoryDb struct {
	client *sql.DB
}

func (d CustomerRepositoryDb) FindAll() ([]Customer, error) {

	findAllSql := "select customer_id, name, city, zipcode, date_of_birth, status from customers"

	rows, err := d.client.Query(findAllSql)
	if err != nil {
		log.Println("Error while querying customer table " + err.Error())
		return nil, err
	}

	customers := make([]Customer, 0)
	for rows.Next() {
		var c Customer
		err := rows.Scan(&c.Id, &c.Name, &c.City, &c.Zipcode, &c.DateofBirth, &c.Status)
		if err != nil {
			log.Println("Error while scanning customer " + err.Error())
			return nil, err
		}
		customers = append(customers, c)
	}
	return customers, nil
}

func NewCustomerRepositoryDb() CustomerRepositoryDb {
	client, err := sql.Open("mysql", "user_id:user_password@tcp(localhost:3306)/database_name")
	if err != nil {
		panic(err)
	}
	// See "Important settings" section.
	client.SetConnMaxLifetime(time.Minute * 3)
	client.SetMaxOpenConns(10)
	client.SetMaxIdleConns(10)
	return CustomerRepositoryDb{client}
}

 

go lang에 익숙하지 않으신분들은 구조체 타입을 변수로 선언하여 rows.Next() 를 통해 한줄씩 Scan 하는 방식에 대해서 낯설수도 있을거 같네요 ㅎ

 

go lang 은 또 예외문을 따로 명시 할수 없어서 에러 처리가 중요합니다.

 

app/handlers.go

package app

import (
	"bangking/service"
	"encoding/json"
	"net/http"
)

type Customer struct {
	Name    string `json:"full_name"`
	City    string `json:"city"`
	Zipcode string `json:"zip_code"`
}

type CustomerHandlers struct {
	service service.CustomerService
}

func (ch *CustomerHandlers) getAllCustomer(writer http.ResponseWriter, request *http.Request) {
	customers, _ := ch.service.GetAllCustomer()

	// fprint 와 비슷한 함수
	// writer 를 전달하고 encode 함수를 호출하고 모든 고객을 json 형식으로 인코딩 하도록 요청
	// 그러나 헤더로 이동하여 콘텐츠 유형을 보면 일반 텍스트로 표시 됩니다.
	// 따라서 이 응답은 JSON 처럼 보이지만 실제로는 JSON 이 아니므로 올바른 내용을 설정해야 합니다.

	writer.Header().Add("Content-Type", "application/json")
	json.NewEncoder(writer).Encode(customers)
}

 

핸들러에서 모든 고객을 가져오는 리시버를 구현합니다.

 

 

app/app.go

package app

import (
	"bangking/domain"
	"bangking/service"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

func Start() {
	router := mux.NewRouter()
	// wiring
	//ch := CustomerHandlers{service.NewCustomerService(domain.NewCustomerRepositoryStub())}
	ch := CustomerHandlers{service.NewCustomerService(domain.NewCustomerRepositoryDb())}

	// define routes
	router.HandleFunc("/customers", ch.getAllCustomer).Methods(http.MethodGet)

	// starting server
	// Listen And serve 는 요류를 반환하고 이를 log Fatal 로 래핑해야 합니다.
	// 서버를 시작하는 동안 오류가 발생했는지 알수 있습니다.
	log.Fatal(http.ListenAndServe("localhost:8080", router))
}

메인 App에서 핸들러를 등록하고 router 를 통해 GET 메서드로 등록합니다.

 

 

main.go

package main

import "bangking/app"

func main() {
	app.Start()
}

 

 

database 에 더미 데이터를 채워넣었습니다.

 

 

insomnia 를 통해 호출한 결과

 

데이터가 잘 조회 되었네요 !!

 

golang 에 입문한지 1주일 정도 되어가는데 평소에 파이썬과 c++ 를 가장 좋아했다보니 그 둘을 섞어 놓은 듯한 기분이 들면서 재밌는 언어라는 생각이 드네요 아직은 golang 을 쓰는 기업들이 많이 없지만 더 발전 했으면 좋겠습니다 !! ㅎ

728x90