반응형

 

작성일: 2024년 5월 8일

 

 

Go 언어로 코드를 작성하다보면, 다른 사람이 작성한 코드(즉, golang package)를 가져다 쓸 일이 생기는데

아래의 순서로 Golang package를 검색하는 것을 추천한다.

 

1)  Golang 표준 패키지 찾아보기

Golang 표준 패키지 검색 :   이 링크를 클릭 ( https://pkg.go.dev/ )

 

2)  Awesome Go 에서 패키지 찾아보기

"Awesome Go" 에서 관리되는 패키지 목록 검색 :  이 링크를 클릭 ( https://github.com/avelino/awesome-go )

 

 

많은 Go package가 위 2개 저장소에서 제공되니까, 일단 package를 검색해보고 가져다 쓰도록 하자.

위에 없는 package는 구글링해서 쓰면 되겠지만, 패키지의 구현 완성도는 믿을 수 없을 듯 ㅡㅡ;

 

 


 

반응형

 

작성일: 2024년 5월 8일

 

 

설치 작업을 시작하기 전에...

주의 - macOS에 기본 제공되는 VIM을 사용하는 경우 -> Homebrew로 재설치

모든 경우에 해당되는지 모르겠지만, 내 경우 macOS에 기본 제공되는 vim editor를 사용했더니

아래처럼 vim editor 화면에 E319 에러가 떴다.

VIM E319 Error

 

VIM E319 Error

 

아래와 같은 해결 방식이 정석인지는 모르겠지만, 내 경우에는 문제없이 vim과 vim-go 등 vim plugin들이 잘 동작했다.

따라서 macOS를 사용하는 사용자라면, Homebrew를 통해서 vim을 재설치하는 것을 추천한다.

 

$ brew remove vim
$ brew cleanup
$ brew install vim

 

그리고 macOS에 설치된 기본 vim editor보다 homebrew를 통해 설치된 vim editor의 실행 순서를 앞 당기기위 해서 아래와 같이 .zshrc 파일에 2줄을 추가한다.

 

$ cat ~/.zshrc
... 중간 생략 ...
alias vi=/opt/homebrew/Cellar/vim/9.1.0350/bin/vim
alias vim=/opt/homebrew/Cellar/vim/9.1.0350/bin/vim
... 중간 생략 ...

 

 

주의 - vim 버전 확인

$ brew info vim

 

만약, vim 8.0 이상이 아닌 경우라면 vim을 최신 버전으로 재설치

$ brew unlink vim
$ brew uninstall vim
$ brew install vim

 

 


 

 

 

공식 문서를 한번쯤 읽어주는 예절...  (Official Documents)

 

fatih/vimgo 공식 문서 열기

 

 


 

vim-plug 설치

vim-plug는 vim에서 사용할 수 있는 plugin manager로써 plugin을 설치하고 사용할 수 있게 해준다.

$ curl -fLo ~/.vim/autoload/plug.vim \
--create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

 

vim-go 및 기타 plugin 설치

${HOME}/.vimrc 파일에 설치할 plugin을 정의한다.

$ vi ~/.vimrc

... 중간 생략 ...

" ------------------------------------------
" vim-go 설정
" -----------------------------------------
filetype plugin indent on

" vim-Plug Plugin List
call plug#begin('~/.vim/plugged')

" 자동완성을 해주는 Plugin.
" :CoCInstall coc-<lang> 으로 지원되는 Language 설치가 가능
" NOTE: 내 경우는 아래 neoclide/coc.nvim을 설치하지 않았다.
"       왜냐하면, 나는 node.js를 사용하지 않기 때문.
" Plug 'neoclide/coc.nvim', {'branch': 'release'}

" 많이 사용되는 plugin list
Plug 'majutsushi/tagbar'
Plug 'vim-airline/vim-airline'
Plug 'tpope/vim-fugitive'

" vim-go 사용을 위한 Plugin
Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }

" 자동 완성 Plugin 이다.
Plug 'SirVer/ultisnips'
Plug 'maralla/completor.vim'

" Misc utilities
Plug 'milkypostman/vim-togglelist'
Plug 'AndrewRadev/splitjoin.vim'
Plug 'mhinz/vim-startify'

" preview plugin
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } " fzf 사용시 꼭 설치;  ~/.fzf 에서 ./install --all 실행해야 함.
Plug 'junegunn/fzf.vim'

" Initialize plugin system
call plug#end()

... 중간 생략 ...

 

 

${HOME}/.vimrc 파일을 저장하고, 아래와 vim 편집기를 실행 후 vim 내부 명령을 수행한다.

$ vim 

... 중간 생략 ...

:PlugInstall

 

수십 초 정도 시간이 흐르면서 plugin을 설치할 것이다. (시간이 많이 걸리니까 다른 일을 하면서 신경을 끄는게 좋다)

vim plugins 설치 화면

 

 

 

 

vim-go 관련 설정 (개인 취향에 따라 설정 값 정하기)

아래 vim-go 관련 설정은 개인 취향에 따라 값을 정하면 된다.

 

$ vim ~/.vimrc

... 중간 생략 ...

" -------------------------------------------------------
" NOTE: *.go 파일을 저장할 때 Auto formatting하고, 
"       관련 go package를 자동으로 .go 소스 코드 파일에 추가해준다.
let g:go_fmt_command = "goimports"
let g:go_list_type = "quickfix"
let g:go_addtags_transform = "camelcase"

let g:go_autodetect_gopath = 1
let g:go_highlight_types = 1
let g:go_highlight_fields = 1
let g:go_highlight_functions = 1
let g:go_highlight_function_calls = 1
let g:go_highlight_extra_types = 1
let g:go_highlight_generate_tags = 1
let g:go_highlight_operators = 1
let g:go_auto_type_info = 1
let g:go_auto_sameids = 1

" NOTE: 문서를 Popup window 형태로 보여주기 (:GoDoc 명령)
let g:go_doc_popup_window = 1 

" NOTE: go source code 작성할 때, 실시간으로 자동 완성할 추천 문장을 보여줌.
let g:completor_filetype_map = {}
let g:completor_filetype_map.go = {'ft': 'lsp', 'cmd': 'gopls - remote=auto'}

" NOTE: quickfix 이동 및 open/close
nnoremap <C-n> :cnext<CR>
nnoremap <C-p> :cprevious<CR>
nnoremap <LocalLeader>q :call ToggleQuickfixList()<CR>

" NOTE: Coverage toggle
nnoremap <LocalLeader>c :GoCoverageToggle<CR>

" NOTE: Go 프로그램을 build, run, test하는 명령에 대한 설정
autocmd FileType go nnoremap <Tab>b :GoBuild<CR>
autocmd FileType go nnoremap <Tab>r :GoRun<CR>
autocmd FileType go nnoremap <Tab><Tab>r :GoRun %<CR>

autocmd FileType go nnoremap <Tab>t :GoTest<CR>
autocmd FileType go nnoremap <Tab><Tab>t :GoTestFunc<CR>
autocmd FileType go nnoremap <Tab>c :GoCoverageToggle<CR>
" -------------------------------------------------------

... 중간 생략 ...

 

 

vim-go 및 관련 plugin 설치 완료

 

 

간단하게 vim-go 동작 유무 확인하기

 

아래와 같이 새 파일 my-main.go 를 편집해보다.

$ vim  my-main.go

 

아래와 같이 기본 소스 코드 틀이 만들어진 .go 파일이 자동으로 생긴다.

vim-go가 자동으로 만들어준 새 소스 코드 파일

 

 

 

 

vim-go 사용법

 

 

많은 분이 잘 정리했으니까, 아래 문서를 보는 것을 추천!

 

A 문서 링크 열기

 

B 문서 링크 열기

 

 

 

 

 


 

반응형
작성일: 2024년 5월 8일

 

Go 언어를 2015~2020년 사이에 사용하고, 그 뒤로 거의 쓰지 않다가 오늘 go-pktgen 소스 코드를 보다가

몇년 사이 golang에 많은 변화가 있다는 것을 알았다.

내가 2015년에 책으로 배운 Go 언어에 대한 지식만으로 프로그래밍하면 큰코 다치겠다 ㅋㅋ

(회사 동료들이 같이 Go 언어를 사용하면, 같이 성장할텐데... 회사 동료들은 C, C++ 찬양론자들이라서... ㅠㅠ)

 

새로운 Golang Feature도 파악하고, 다시 기억도 좀 살리기 위해 Golang 학습 문서를 봐야겠다

오늘 기준으로 볼만한 온라인 문서를 찾아보니... 아래와 같다.

 

 

Tucker의 Go 언어 프로그래밍 (2021년, 공봉식)

2024년 5월 8일 기준으로 이 책을 eBook으로 구입해서 보고 있는데...

내가 9년 전에 구입해서 봤던 책보다는 3배 정도 설명이 자세하고 친절하다.

9년 전에 구입한 Go 언어 책이 미울 정도이다. (그 책을 읽은 시간이 아깝다 ㅠㅠ)

종이 책(또는 eBook) 중에서는 이 책이 가장 괜찮은 것 같다. (나의 주관적 느낌)

 

Tucker의 Go 언어 프로그래밍 (책 표지)

 

 

아래 화면은 내가 구입한 eBook이고 macOS용 Crema 앱으로 보고 있는 중이다.

컴퓨터학(Compute Science) 전공하고 있는 대학생, 또는 컴퓨터학을 수료한 졸업생이라면 쉽게 읽힐 수 있는 책이다.

왜냐고? 책 중간 중간에 Memory 구조와 Go source code를 설명하는 부분이 자주 등장하는데,

약간이라도 CPU, Memory 구조 및 동작 방식을 알고 보는 것이 재미있다.

예를 들어, 아래 빨간 동그라미로 표시한 부분과 같은 표현이 익숙하고 잘 이해가 되는 분이라면 이 책을 재미있게 읽을 수 있다.

 

Tucker의 Go 언어 프로그래밍 (eBook으로 구입해서 macOS용 Crema로 보고 있음)

참고: 저작권 침해가 될 것 같아서 위와 같이 책 내용을 가렸습니다.

 

Tucker의 Go 언어 프로그래밍 (eBook으로 구입해서 macOS용 Crema로 보고 있음)

 

아무튼 이 책은 적극 추천~~~
(이 책의 저자, 출판사로부터 받은 거 없음. 그냥 개인적 소신임)

 

 

Tucker의 Go 언어 프로그래밍 / 동영상 강의

YouTube 채널, Playlist: https://www.youtube.com/playlist?list=PLy-g2fnSzUTBHwuXkWQ834QHDZwLx6v6j

 

 

 

Effective Go (Go Official Site)

영어 문서: https://go.dev/doc/effective_go 

한국어 문서: https://gosudaweb.gitbooks.io/effective-go-in-korean/content/

 

 

 

 

Facebook 그룹

가끔 Facebook을 통해서 공식 행사를 알려준다. (예를 들어, GopherCon Korea 2024 같은 이벤트)

https://www.facebook.com/groups/golangko

 

 

 

 


 

반응형

Go Language로 특정 Process의 CPU, Memory 사용량을 계산하고 싶다면,

아래의 코드를 Build해서 사용하면 된다.

 

참고: Linux, MacOS, Unix, Windows 모두 동작하는 코드임.

 

 

// Filename: proc_usage.go

package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math"
	"os/exec"
	"path"
	"runtime"
	"strconv"
	"strings"
	"sync"
)

const (
	statTypePS   = "ps"
	statTypeProc = "proc"
)

// SysInfo will record cpu and memory data
type SysInfo struct {
	CPU    float64
	Memory float64
}

// Stat will store CPU time struct
type Stat struct {
	utime  float64
	stime  float64
	cutime float64
	cstime float64
	start  float64
	rss    float64
	uptime float64
}

type fn func(int) (*SysInfo, error)

var fnMap map[string]fn
var platform string
var history map[int]Stat
var historyLock sync.Mutex
var eol string

// Linux platform
var clkTck float64 = 100    // default
var pageSize float64 = 4096 // default

func init() {
	platform = runtime.GOOS
	if eol = "\n"; strings.Index(platform, "win") == 0 {
		platform = "win"
		eol = "\r\n"
	}
	history = make(map[int]Stat)
	fnMap = make(map[string]fn)
	fnMap["darwin"] = wrapper("ps")
	fnMap["sunos"] = wrapper("ps")
	fnMap["freebsd"] = wrapper("ps")
	fnMap["openbsd"] = wrapper("proc")
	fnMap["aix"] = wrapper("ps")
	fnMap["linux"] = wrapper("proc")
	fnMap["netbsd"] = wrapper("proc")
	fnMap["win"] = wrapper("win")

	if platform == "linux" || platform == "netbsd" || platform == "openbsd" {
		initProc()
	}
}

func initProc() {
	clkTckStdout, err := exec.Command("getconf", "CLK_TCK").Output()
	if err == nil {
		clkTck = parseFloat(formatStdOut(clkTckStdout, 0)[0])
	}

	pageSizeStdout, err := exec.Command("getconf", "PAGESIZE").Output()
	if err == nil {
		pageSize = parseFloat(formatStdOut(pageSizeStdout, 0)[0])
	}

}

func wrapper(statType string) func(pid int) (*SysInfo, error) {
	return func(pid int) (*SysInfo, error) {
		return stat(pid, statType)
	}
}

func formatStdOut(stdout []byte, userfulIndex int) []string {
	infoArr := strings.Split(string(stdout), eol)[userfulIndex]
	ret := strings.Fields(infoArr)
	return ret
}

func parseFloat(val string) float64 {
	floatVal, _ := strconv.ParseFloat(val, 64)
	return floatVal
}

func statFromPS(pid int) (*SysInfo, error) {
	sysInfo := &SysInfo{}
	args := "-o pcpu,rss -p"
	if platform == "aix" {
		args = "-o pcpu,rssize -p"
	}
	stdout, _ := exec.Command("ps", args, strconv.Itoa(pid)).Output()
	ret := formatStdOut(stdout, 1)
	if len(ret) == 0 {
		return sysInfo, errors.New("Can't find process with this PID: " + strconv.Itoa(pid))
	}
	sysInfo.CPU = parseFloat(ret[0])
	sysInfo.Memory = parseFloat(ret[1]) * 1024
	return sysInfo, nil
}

func statFromProc(pid int) (*SysInfo, error) {
	sysInfo := &SysInfo{}
	uptimeFileBytes, err := ioutil.ReadFile(path.Join("/proc", "uptime"))
	if err != nil {
		return nil, err
	}
	uptime := parseFloat(strings.Split(string(uptimeFileBytes), " ")[0])

	procStatFileBytes, err := ioutil.ReadFile(path.Join("/proc", strconv.Itoa(pid), "stat"))
	if err != nil {
		return nil, err
	}
	splitAfter := strings.SplitAfter(string(procStatFileBytes), ")")

	if len(splitAfter) == 0 || len(splitAfter) == 1 {
		return sysInfo, errors.New("Can't find process with this PID: " + strconv.Itoa(pid))
	}
	infos := strings.Split(splitAfter[1], " ")
	stat := &Stat{
		utime:  parseFloat(infos[12]),
		stime:  parseFloat(infos[13]),
		cutime: parseFloat(infos[14]),
		cstime: parseFloat(infos[15]),
		start:  parseFloat(infos[20]) / clkTck,
		rss:    parseFloat(infos[22]),
		uptime: uptime,
	}

	_stime := 0.0
	_utime := 0.0

	historyLock.Lock()
	defer historyLock.Unlock()

	_history := history[pid]

	if _history.stime != 0 {
		_stime = _history.stime
	}

	if _history.utime != 0 {
		_utime = _history.utime
	}
	total := stat.stime - _stime + stat.utime - _utime
	total = total / clkTck

	seconds := stat.start - uptime
	if _history.uptime != 0 {
		seconds = uptime - _history.uptime
	}

	seconds = math.Abs(seconds)
	if seconds == 0 {
		seconds = 1
	}

	history[pid] = *stat
	sysInfo.CPU = (total / seconds) * 100
	sysInfo.Memory = stat.rss * pageSize
	return sysInfo, nil
}

func stat(pid int, statType string) (*SysInfo, error) {
	switch statType {
	case statTypePS:
		return statFromPS(pid)
	case statTypeProc:
		return statFromProc(pid)
	default:
		return nil, fmt.Errorf("Unsupported OS %s", runtime.GOOS)
	}
}

// GetStat will return current system CPU and memory data
func GetStat(pid int) (*SysInfo, error) {
	sysInfo, err := fnMap[platform](pid)
	return sysInfo, err
}

 

 

 

// Filename: main.go

package main

import (
    "os"
    "fmt"
    "time"
    "strconv"
)

func main() {
    myPid, _ := strconv.Atoi(os.Args[1])

    for i:= 0; i < 100; i++ {
        sysInfo, _ := GetStat(myPid)
        fmt.Println("CPU Usage     :", sysInfo.CPU)
        fmt.Println("Mem Usage(RSS):", sysInfo.Memory)
        time.Sleep(5 * time.Second)
    }
}

 

위와 같이 Go source code를 모두 작성했다면, 아래처럼 build하고 실행하면 된다.

 

$ go mod init andrew.space/proc_usage
go: creating new go.mod: module andrew.space/proc_usage
go: to add module requirements and sums:
	go mod tidy
    
$ go mod tidy

$ go build

$ ./proc_usage 4314
CPU Usage     : 52.92167225853122
Mem Usage(RSS): 2.018664448e+09
CPU Usage     : 39.800000000000004
Mem Usage(RSS): 2.018664448e+09
CPU Usage     : 47.30538922366738
Mem Usage(RSS): 2.018664448e+09
...
...

 

top 명령으로 본 것과 결과가 동일했다.

반응형

gcc 컴파일 명령어를 사용할 때는 -D 옵션을 이용해서 Source Code 밖에서 상수를 지정할 수 있었다.

그런데, Go Language에도 이런 똑같은 기능이 있을까?

 

답: Go에도 GCC와 똑같은 기능이 있다!!!

 

아래 예제처럼 하면 된다. ^^

 


 

매번 go build 명령을 입력하기 귀찮으니까, 아래처럼 go build 스크립트를 만들자.

$ cat  my_go_build.sh

#!/bin/bash

export MY_APP_VERSION=0.1.0

go build -ldflags "-X main.appVersion=${MY_APP_VERSION} -X 'main.buildDate=$(date +%F) $(date +%T)' -X 'main.devNote=New Feature ABC is added'"

$

 

 

go source code를 작성하자. (아래는 예시를 위해서 간단하게 만든 것이니까, 참고만 할것 !!!)

$ cat main.go

package main

import (
        "fmt"
)

func main() {
    getAppVersion()

	// My Main Routine ...
    fmt.Printf("My Main Routing ...\n")
}

$

 

 `go build -ldflags "-X ... -X ... -X ..."` 이런 식으로 입력한 외부 상수를 go source code 내부에서 참조(reference)할 수 있도록 아래와 같이 변수를 선언하고, 사용하자 !!!

package main

import (
        "fmt"
)

var (
    appVersion string
    buildDate string
    devNote string
)

func getAppVersion() {
    fmt.Printf("App Name   : almighty\n")
    fmt.Printf("Version    : %s\n", appVersion)
    fmt.Printf("Build Date : %s\n", buildDate)
    fmt.Printf("Dev Note   : %s\n", devNote)
}

 

 

위와 같이 go source code가 작성되었다면, 아래와 같이 build하고 실행 바이너리 파일을 실행해보자.

 

$ my_go_build.sh

$ my_example_app

App Name   : almighty
Version    : 0.1.0
Build Date : 2022-07-05 16:18:12
Dev Note   : New Feature ABC is added
My Main Routing ...

$
반응형

 

참고:
Go Module과 Package를 사용하는 방법이 Go Version에 따라 다를 수 있다.
아래 예제는 Go 1.17을 이용한 예제이고, 아마 Go 1.11 이상을 사용하는 경우라면 아래 설명이 잘 맞을 것이다.

 

여담:
나는 본업이 Go Language를 사용해서 개발하는 개발자가 아니다보니, 2~3년에 한번 잠깐 GoLang을 이용해서 개발하려고 하면 Go Package와 Module 때문에 시간을 허비하게 된다.
그래서 오늘은 기왕 스터디한 것을 2~3년 뒤에 또 GoLang을 사용할 일이 있을 경우, 쉽게 PackageModule 개념을 습득하기 위해 예제를 통해서 메모를 할까 한다.

 


 

Go PKG를 다루기 위해서는 크게 3가지 방식이 있다.

 

방식 A

  $GOPATH 경로를 설정하고, 이 $GOPATH 경로 안에서만 Package를 사용하는 방법. (암묵적 Module 사용하기)

 

방식 B    <-- 가장 많은 개발자가 선호하는 방식이 아닐까 생각한다.

  Module을 명시적으로 선언(go mod init x.y.z)하고, 내가 원하는 폴더 어디에서든 Go Source Code를 작성하는 방법.

 

방식 C

  go ven를 이용해서 현재 디렉토리 하위에서 모든 Package를 사용하는 방법.

 

각 Package 사용 방식에 대해서 아래에서 세부적으로 다룬다.

 

 

$GOPATH 경로를 선언하여 Package를 사용하는 방식

설명보다는 예제 코드를 보는 것이 좋을 듯~~~

 

$  vi  ~/.bash_profile
...
export GOPATH=$(go env GOPATH)
...

$  .  ~/.bash_profile
$  echo  $GOPATH
/Users/sejong/go

$  cd  $GOPATH
##
## 이제부터는 $GOPATH/src 디렉토리 밑에서만 코드를 작성해야 한다.
##
$  mkdir  -p src/myexample
$  cd  src/myexample
$  mkdir  myPkgAlpha
$  cd  myPkgAlpha
$  vi  example.go

package myPkgAlpha

import "fmt"

# 주의: 패키지 외부에서 참조할 수 있도록 함수 이름은 대문자로 시작해야 한다.

func MyExamplePrint() {
  fmt.Println("My Alpha PKG")
}

$  cd  ..
$  vi  main.go

package main

import (
  "fmt"
  "myexample/myPkgAlpha"
)

func main() {
  fmt.Println("This is main package.")
  myPkgAlpha.MyExamplePrint()
}

$  go  mod  init  myexample
$  go  mod  tidy
$  go  build

$  ./myexample
This is main package.
My Alpha PKG

$  tree
.
├── go.mod
├── main.go
├── myPkgAlpha
│   └── example.go
└── myexample
$

 

 

 

 

$GOPATH 경로가 아닌, 나만의 별도의 Project 폴더에서 Go Module 사용하는 방식

Go module을 사용하면 $GOPATH 경로가 아닌 아무 곳(디렉토리)에서 Go Source Code를 작성할 수 있는 자유가 생긴다.

긴 설명은 생략하고, 아래 예제처럼 Go Package와 Module을 사용하면 된다.

 

##
##  새로운 프로젝트를 위한 폴더를 만들자~
##
$  mkdir  go-mod-pkg-example
$  cd  go-mod-pkg-example

##
##  Go Package를 만들자.  (myPkgAA)
##  주의사항: package 이름과 folder 이름을 동일하게 작성해야 한다.
##
$  mkdir  myPkgAA
$  cd  myPkgAA

##
## 아래와 같이 myPkgAA 패키지에 대한 코드를 작성한다.
##
$  vi  example.go

package myPkgAA

const (
    COMPANY  = "Sejong Inc"
    LOCATION = "Seoul Korea"
)

##
##  Package가 1개만 있으면 심심하니까, 하나 더 만들자. (mypkg_bb)
##

$  cd  ..
$  mkdir  mypkg_bb
$  cd  mypkg_bb

##
## 아래와 같이 mypkg_bb 패키지에 대한 코드를 작성한다.
##
$  vi  example.go

package mypkg_bb

import (
    "fmt"
)

// NOTE: 함수 이름은 대문자로 시작해야 한다.
func DoSomething(company string, location string) {
    fmt.Println("[In mypkg_bb]")
    fmt.Println("  Company  :", company)
    fmt.Println("  Location :", location)
}


##
##  위에서 작성한 Package를 사용하는 Go Module Code를 작성하자.
##

$  go  mod  init  myexample.cncf/sejong/myexample
$  vi  main.go

// NOTE: package 이름을 main 으로 한다.
package main

// NOTE: 이 module의 이름이 "myexample.cncf/sejong/myexample" 이었기 때문에
//       myPkgAA 패키지를 import하려면 아래처럼 경로를 작성해야 한다.
import (
    "myexample.cncf/sejong/myexample/myPkgAA"
    "myexample.cncf/sejong/myexample/mypkg_bb"
)

func main() {
    mypkg_bb.DoSomething(myPkgAA.COMPANY, myPkgAA.LOCATION)
}

## 솔직히, 위 예제 패키지(로컬 패키지)만 이용하는 경우에는 아래 tidy 명령을 필요 없다.
## 그러나 main.go 파일에서 외부 pkg를 import 한 것도 포함했다면,
## 아래처럼 tidy 명령을 수행해야 한다.
$  go  mod  tidy

$  go  build

$  ./myexample
[In mypkg_bb]
  Company  : Sejong Inc
  Location : Seoul Korea
  
$  tree
.
├── go.mod
├── main.go
├── myPkgAA
│   └── example.go
├── myexample
└── mypkg_bb
    └── example.go

$

 

 

Vendor  방식의 패키지 관리

 

vendor 디렉토리에 특정 버전의 외부 패키지들을 저장 시킨 뒤 빌드에 참여시킴으로써 버전 일관성 문제를 해결 할 수 있다.

그리고 다운로드 불가한 외부 패키지를 어떻게든 한번만 구할 수만 있다면 다운로드 불가 문제도 피할 수 있다.

Container Image처럼 내가 작성한 Go Module 소스 코드가 있는 폴더에 의존성이 있는 모든 Package를 vendor/ 폴더 디렉토리에 다운로드 받는 다는 것이 가장 큰 특징이다.

 

자세한 내용은 아래 Go Module Vendoring 문서를 참고할 것 !!!

 

https://go.dev/ref/mod#go-mod-vendor

 

Go Modules Reference - The Go Programming Language

 

go.dev

 

## 코드를 작성한 상태에서 아래 명령을 실행~

$  mkdir MyExampleApp
$  vi main.go 
...
...

$  go mod vendor

$  ls
main.go   vendor/

 

 

 

 

반응형

 

REST API Server

Go 기본 Package만 사용해서 REST API Server 만들기

일단, 아래 블로그가 예제 코드를 복사해서 실습하기 좋게되어 있다.

https://woony-sik.tistory.com/12

 

Golang REST API 만들기

오늘은 Golang으로 간단한 REST API를 만드는 방법을 쓸까 한다. 바로 시작하자 우선은 Directory를 하나 만들고 시작 mkdir rest go module 등록 go mod init noah.io/ark/rest main.go 생성 touch main.go Direc..

woony-sik.tistory.com

 

 

gorilla package의 mux를 이용해서 REST API Server 만들기

이 블로그는 자동 Test하는 Code까지 포함되어 있다.

따라서 상용 Software PKG 개발할 때, 참고하면 좋다.

 

https://velog.io/@soosungp33/Golang%EC%9C%BC%EB%A1%9C-%EC%9B%B9%EC%84%9C%EB%B2%84-%EB%A7%8C%EB%93%A4%EA%B8%B04

 

 

Golang으로 웹서버 만들기(4)

RESTful API - GET과 POST 다뤄보기

velog.io

 

 

 

REST API Client

go-resty 라는 'REST client library'를 이용하면, 쉽게 REST API Client App을 개발할 수 있다.

아래 GitHub에 Case by Case로 Example이 있기 때문에 장황한 설명보다는 아래 Web Docs에 있는 Example Code를 보고 이해하고 따라해보는 것이 좋을 듯하다.

https://github.com/go-resty/resty
 

GitHub - go-resty/resty: Simple HTTP and REST client library for Go

Simple HTTP and REST client library for Go. Contribute to go-resty/resty development by creating an account on GitHub.

github.com

 

go-resty를 소개한 블로그이다. 쉽게 설명했으니까 한번 읽어보면 좋을 것이다.

go-resty를 사용하면, JSON Type의 Request / Response 를 Marshal, Unmarshal할 필요가 없다.

 

https://wookiist.dev/104
 

[Go/Golang] Go의 HTTP & REST Client 라이브러리 - Resty

Go의 HTTP & REST Client 라이브러리 - Resty API Client 이전 포스팅에서 다뤘던 Echo는 Go의 Web Framework입니다. Echo로 구현한 프로그램은 API Server 등으로 동작할 수 있고, 큰 어려움 없이 Web Server로..

wookiist.dev

 

 

 

 

 

기타 Reference 하면 좋을 Blog

 

https://doitnow-man.tistory.com/259

 

[Go Lang] 4. 실전 - http server + swagger 만들기

목표 web framework를 사용하여 간단한 web api server를 만들어 보겠습니다. 배포는 추후 포스트에서 다루겠습니다. 개발 환경 - ubnutu 18.04 - go version go1.16.3 linux/amd64 (업그레이드 방법: golang.org..

doitnow-man.tistory.com

 

 

블로그 작성자: sejong.jeonjo@gmail.com

 

 

반응형

 

 

작성일: 2024년 4월 11일

 

 

Go 언어를 사용해서 CLI를 개발할 일이 생겼는데, 기존 C언어로 개발하던 개발 습성 때문인지 CLI를 개발할 생각하니까 귀찮고 짜증부터 났다.

Java처럼 CLI를 쉽게 개발할 수 있는 Go Package가 있지 않을까 싶어서 구글링을 해보니, 역시나 GoLang은 개발 도구나 Library package가 훌륭하다는 것을 또 한번 느끼게 되었다.

 

일단 딱 눈에 들어온 것은 Cobra library였다.

https://pkg.go.dev/github.com/spf13/cobra#section-readme

 

cobra package - github.com/spf13/cobra - pkg.go.dev

SetOutput sets the destination for usage and error messages. If output is nil, os.Stderr is used. Deprecated: Use SetOut and/or SetErr instead

pkg.go.dev

 

Cobra is a library providing a simple interface to create powerful modern CLI interfaces similar to git & go tools.
Cobra is also an application that will generate your application scaffolding to rapidly develop a Cobra-based application.

 

위 Cobra Web Docs 문서에서 소개하는 것처럼 Cobra는 library이면서, application scaffoling을 만들어주는 개발 도구이다.

그래서 단순하게 library reference만 읽고 사용법을 익히는 것이 아니라 Cobra 도구를 이용해서 scaffolding을 만들고, 그 scaffolding 안에서 나의 logic을 추가해야 한다.

Cobra의 개발 절차만 잘 따라하면, 시간을 팍팍 줄여가면서 CLI를 붕어빵 찍어내듯이 만들 수 있을 것 같은 느낌적인 느낌이 들었다.

그럼 그 개발 절차를 자세히 들여다 보면 이렇다.

 

 

https://www.youtube.com/watch?v=so3VZwdWcBg&t=4s 

 

 

 

 

 

 

Reference

https://yjwang.tistory.com/137

 

[Go-lang] Cobra를 사용해서 cli 프로그램 개발

cobra 사용해서 cli tool을 개발해보고자 한다. 아무래도 Infra 작업을 하다보면 cli tool이 있으면 편하겠다는 생각을 하곤하는데 생각한 김에 만들어보고자합니다. cobra 프로젝트는 kubectl에서도 사용

yjwang.tistory.com

 

 

https://www.sktenterprise.com/bizInsight/blogDetail/dev/2755

 

[Golang] Cobra를 이용한 CLI 유틸리티 만들기 | 개발자 Story | SKT Enterprise

현대사회에서 대부분의 유저들은 휴대폰이나 컴퓨터 화면을 통해 쉽고 편한 GUI(Graphic User Interface)를 선호합니다. 그러나 GUI로는 채우기 힘든 여전히 CLI(Command Line Interface)를 선호하는 분야도 많

www.sktenterprise.com

 

https://nangman14.tistory.com/97

 

Go로 커맨드를 실행할 수 있는 CLI를 구현해보자 (With Cobra)

CLI(Command Line Interface)란 터미널을 통해 사용자와 컴퓨터가 상호작용하는 인터페이스를 말합니다. CLI는 그래픽을 통해 직관적으로 사용할 수 있는 GUI(Graphic User Interface)와 달리 명령줄로만 입력을

nangman14.tistory.com

 

 

 

 

기타: 다른 방식의 CLI 개발 예제

 

https://dev.to/tidalmigrations/interactive-cli-prompts-in-go-3bj9

 

Interactive CLI prompts in Go

Tidal Migrations 💓 CLI applications Do you like CLI applications? We love them! At Tidal...

dev.to

 

 

https://github.com/manifoldco/promptui

 

GitHub - manifoldco/promptui: Interactive prompt for command-line applications

Interactive prompt for command-line applications. Contribute to manifoldco/promptui development by creating an account on GitHub.

github.com

 

+ Recent posts