GO

go 캐릭터
귀엽당 고랭고랭고랭래애래애애앵

Go 개발환경

GOPATH 지정

Go 작업파일이 위치할 경로를 GOPATH로 지정해준다. 이 $GOPATH 아래에는 다음과 같은 3개의 폴더가 위치한다.

  • bin : binary 실행파일
  • src : go 소스파일
  • pkg : 패키지 파일

GO Moudule

Go에서의 Module은 Go package들의 의존성을 관리하는 Go 패키지 관리 시스템이다.
기존에 GO 개발 시, GOROOT 외부에서 GOPATH를 설정하여 개발하였던 방식의 불편함이 사라졌다. GOPATH를 사용하지 않아 동시에 여러 Go 프로젝트 개발이 편리해 졌다.

우선 $GOPATH 외부에 디렉토리를 만든다. 이후 해당 디렉토리의 최상위 디렉토리에서 다음과 같이 실행한다.

go mod init github.com/깃헙아이디/저장소이름
go build

이제 해당 디렉토리에 go.mod 라는 파일이 생성되고, 이 파일에 import된 패키지들의 정보가 업데이트 될 것이다.

추가

# import되지 않은 디펜던시를 제거해준다. 
go mod tidy



Echo 프레임워크 활용하여 간단한 http 서버 작성해보기

main.go 파일

package main

import (
    "net/http"

    "github.com/labstack/echo"
        
)

func main() {
        e := echo.New()
        e.GET("/ping", func( c echo.Context) error{
                return c.String(http.StatusOK, "pong!")
        })
        e.Logger.Fatal(e.Start(":1323"))
}

실행하기

❯ go run main.go
go: finding module for package github.com/labstack/echo
go: found github.com/labstack/echo in github.com/labstack/echo v3.3.10+incompatible

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:1322

기능별로 분리하기

package main

import (
        "net/http"

        "github.com/labstack/echo"
)

type router struct {
}

//Handler
func handler(c echo.Context) error {
        return c.String(http.StatusOK, "pong!\n")
}

func main() {
        //Echo instance 생성
        e := echo.New()

        //Route
        e.GET("/ping", handler)

        //Start server
        e.Logger.Fatal(e.Start(":1322"))
}

Echo 인스턴스를 생성 후,
“/ping” 이라는 매개변수가 url뒤에 들어오면 라우터가 요청에 맞는 handler 함수를 연결한다. 이후 핸들러 함수가 요청을 처리하는 구조이다.
이 라우터-핸들러 기능을 조금 더 확장해서 url 요청에 따라 각각의 요청을 수행해 주는 코드로 수정했다.

router 기능확장

package main

import (
	"net/http"
	"strconv"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

type (
	user struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	}
)

var (
	users = map[int]*user{}
	seq   = 1
)

func createUser(c echo.Context) error {
	u := &user{
		ID: seq,
	}
	if err := c.Bind(u); err != nil {
		return err
	}
	users[u.ID] = u
	seq++
	return c.JSON(http.StatusCreated, u)
}

func getUser(c echo.Context) error {
	id, _ := strconv.Atoi(c.Param("id"))
	return c.JSON(http.StatusOK, users[id])
}

func updateUser(c echo.Context) error {
	u := new(user)
	if err := c.Bind(u); err != nil {
		return err
	}
	id, _ := strconv.Atoi(c.Param("id"))
	users[id].Name = u.Name
	return c.JSON(http.StatusOK, users[id])
}

func deleteUser(c echo.Context) error {
	id, _ := strconv.Atoi(c.Param("id"))
	delete(users, id)
	return c.NoContent(http.StatusNoContent)
}

func getAllUsers(c echo.Context) error {
	return c.JSON(http.StatusOK, users)
}

func main() {
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	// Routes
	e.GET("/users", getAllUsers)
	e.POST("/users", createUser)
	e.GET("/users/:id", getUser)
	e.PUT("/users/:id", updateUser)
	e.DELETE("/users/:id", deleteUser)

	// Start server
	e.Logger.Fatal(e.Start(":1323"))
}

확인

❯ curl localhost:1323/users/1
null

❯ curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{"name":"Hyobin Lee"}' \
  localhost:1323/users
{"id":1,"name":"Hyobin Lee"}

❯ curl localhost:1323/users/1
{"id":1,"name":"Hyobin Lee"}

❯ curl localhost:1323/users
{"1":{"id":1,"name":"Hyobin Lee"}}