<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Golang :: 태그 :: 모두의프린터</title><link>https://modu-print.com/tags/golang/</link><description/><generator>Hugo</generator><language>ko-KR</language><lastBuildDate>Mon, 21 Aug 2023 10:17:16 +0900</lastBuildDate><atom:link href="https://modu-print.com/tags/golang/index.xml" rel="self" type="application/rss+xml"/><item><title>Vscode에서 Goland로 전환 후기</title><link>https://modu-print.com/posts/10237/</link><pubDate>Mon, 21 Aug 2023 10:15:54 +0900</pubDate><guid>https://modu-print.com/posts/10237/</guid><description>매우 오랜 시간 MS의 Visual Studio Code를 이용해서 Go언어 개발을 해 왔습니다만.. Vscode 에서 go언어를 지원하기 이전에는 서브라임텍스트 라던가 gVim등 정말 많은 편집기들을 전전 긍긍 했고 한때는 Notepad++ 로 Go언어 개발을 하던 시절도 있었습니다.&#10;Vscode 에서 go언어를 지원하기 시작하고 디버깅도 가능해지고 각종 go 언어 관련 부가적인 기능들을 지원하기 시작하면서 부터는 주로 Vscode 로 개발을 해 왔습니다.</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 모달 다이얼로그(Modal Dialog) 추가</title><link>https://modu-print.com/posts/1794/</link><pubDate>Thu, 29 Jun 2023 15:32:00 +0900</pubDate><guid>https://modu-print.com/posts/1794/</guid><description>지금까지 walkmgr 에 추가된 기능들로도 어지간한 윈도 네이티브 GUI 프로그래밍은 가능 했습니다만. 보편적인 GUI 프로그래밍에서 가장 크게 부족한 기능중 하나가 모달 다이얼로그(Modal Dialog) 기능이었습니다.&#10;흔히 다이얼로그(Dialog)라고 하자면 대화창 또는 대화상자라고 칭하곤 하지요..&#10;일반적으로는 사용자의 의사를 묻거나 사용자의 어떤 선택이 필요한 경우 사용자 선택에 따른 로직의 분기가 필요하다던가 하는 경우에 사용됩니다.&#10;가장 쉽게 접하는것은 MessageBox 같은 함수겠지요. 자바스크립트를 기준하자면 alert 이나 confirm 같은 함수로 생성되는 대화창을 들 수 있겠습니다.</description></item><item><title>HTTP GET 헤더추가 + gzip 처리</title><link>https://modu-print.com/posts/3386/</link><pubDate>Wed, 17 May 2023 09:36:00 +0900</pubDate><guid>https://modu-print.com/posts/3386/</guid><description>웹 관련 개발을 하게되면 HTTP GET 방식으로 단순 데이터를 수신해야 하는 경우가 있습니다. 이런 경우 Response 데이터의 크기가 큰 경우에 서버측에서 데이터를 gzip 으로 압축해서 전송하는 경우도 종종 있습니다. 트래픽 비용을 cpu 연산으로 커버 치는 샘이겠지요..&#10;이런식의 처리가 가능하려면 Reqeust Header 상에도 accept-encoding 같은 정보에 gzip 을 지원 한다는 명시를 해주지 않을 경우 서버측에선 에러를 리턴하게 됩니다.&#10;상대가 gzip 압축을 처리하지 못한다는데 굳이 gzip 으로 압축된 응답을 할 이유 자체가 없기 때문이겠지요 ..</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 트리뷰(TreeView) 추가 2편</title><link>https://modu-print.com/posts/2148/</link><pubDate>Fri, 10 Feb 2023 09:20:00 +0900</pubDate><guid>https://modu-print.com/posts/2148/</guid><description>앞서 기본적인 트리뷰 생성법에 대해서는 아래 링크를 참고하시구요.&#10;[Go언어 윈도 GUI] walkmgr에 트리뷰(TreeView) 추가 1편 몇가지 예제를 가지고 추가 사용법을 알려드리도록 하겠습니다.&#10;트리뷰에서 선택된 아이템의 이름을 변경하는 예제입니다. 현재 선택된 아이템의 객체를 얻는 방법과 명칭을 변경하는 방법입니다.</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 트리뷰(TreeView) 추가 1편</title><link>https://modu-print.com/posts/2145/</link><pubDate>Thu, 09 Feb 2023 12:50:00 +0900</pubDate><guid>https://modu-print.com/posts/2145/</guid><description>이번에 모두의 PDF에 책갈피 기능을 추가하면서 PDF의 책갈피 기능이 Parent, Children 을 이용한 무한 계층구조 인지라 이런 형태를 다루는데 가장 적합한 UI요소는 아무래도 트리뷰(TreeView)라서 관련 기능을 walkmgr 에 추가해 봅니다.&#10;MFC나 윈도 API를 다루던 시절에도 사실 트리뷰는 진짜 쓰기 싫어라 하던 놈중 하나인데요 가능하면 리스트컨트롤로 대충 땜빵해서 쓰곤 했는데 .. 계층구조를 리스트 컨트롤로 다루는건 매우 비효율적인지라 미루고 미루다 추가해 봅니다.&#10;이런놈을 보통 트리뷰라고 하지요.. 우리가 가장 흔히 접하는 경우를 보자면</description></item><item><title>[Go언어 윈도 GUI] walkmgr 메뉴(Menu) 예제</title><link>https://modu-print.com/posts/2139/</link><pubDate>Sat, 24 Dec 2022 14:39:00 +0900</pubDate><guid>https://modu-print.com/posts/2139/</guid><description>GitHub - pirogom/walkmgr_example: walkmgr example project walkmgr example project . Contribute to pirogom/walkmgr_example development by creating an account on GitHub. walkmgr 에 메뉴관련 기능과 예제는 한참 전에 추가를 해두긴 했습니다만.. 메뉴와 관련된 글은 작성을 제대로 안한것 같아서 예제도 조금더 보강을 하고 관련 글을 작성해봅니다. 관련 예제는 위의 링크 참고 하시면 됩니다.&#10;윈도 프로그래밍을 하다보면 진짜 유용하고 친숙하게 사용하는게 메뉴입니다. UI나 그런거 귀찮으면 ㅎㅎ 그냥 메뉴에 다 때려넣어도 ;;;</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 툴바(ToolBar) 추가</title><link>https://modu-print.com/posts/2142/</link><pubDate>Mon, 19 Dec 2022 13:08:00 +0900</pubDate><guid>https://modu-print.com/posts/2142/</guid><description>윈도 GUI 프로그래밍시 메뉴와 함께 있으면 유용한 기능중 하나가 툴바(ToolBar)입니다.&#10;흔히 이런 것들로 보통 타이틀바나 메뉴 바로 아래즈음에 아이콘들로 주르륵~ 하니 놓여지는 .. 열기, 자르기, 저장 같은 기능들을 모아두는 것들을 툴바라고들 하지요..&#10;제가 클론해서 수정중인 lxn/walk 에도 기본적으로 제공을 하고 있는 기능입니다만.. walkmgr 구조에 포함시켜 보았습니다. 원래 윈도의 툴바는 수직 방향으로도 구성이 가능하고 lxn/walk 에서도 파라메터 상으로는 수직을 지정가능하게 되어 있긴 한데 제대로 동작하진 못하는것 같아서 우선 전통적인 툴바에 대해서만 다뤄 보도록 하겠습니다.</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 링크 라벨(Link Label) 추가</title><link>https://modu-print.com/posts/2136/</link><pubDate>Sat, 10 Dec 2022 00:08:00 +0900</pubDate><guid>https://modu-print.com/posts/2136/</guid><description>walkmgr 에 Link Label 을 추가 하였습니다. 쉽게 말해서 URL 링크를 포함하는 텍스트 라벨을 사용할 수 있도록 추가 하였습니다.&#10;walkmgr 에 link_label.go 파일이 추가 되었구요.&#10;Go / *&#9;LinkLabel / func (wm WalkUI) LinkLabel(text string, at …AlignType) walk.LinkLabel { ne, _ := walk.NewLinkLabel(wm.Parent()) ne.SetText(text) if len(at) == 0 { ne.SetAlignment(walk.AlignHVDefault) } else { switch at[0] { case ALIGN_LEFT: ne.SetAlignment(walk.AlignHNearVCenter) case ALIGN_CENTER: ne.SetAlignment(walk.AlignHCenterVCenter) case ALIGN_RIGHT: ne.SetAlignment(walk.AlignHFarVCenter) default: ne.SetAlignment(walk.AlignHVDefault) } } wm.Append(ne) ne.LinkActivated().Attach(func(link *walk.LinkLabelLink) { exec.Command("rundll32.exe", "url.dll,FileProtocolHandler", link.URL()).Start() }) return ne }</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 스크롤뷰(ScrollView) 추가</title><link>https://modu-print.com/posts/2133/</link><pubDate>Tue, 06 Dec 2022 09:40:00 +0900</pubDate><guid>https://modu-print.com/posts/2133/</guid><description>업데이트된 패키지는 walkmgr, walkmgr_example 2개 입니다.&#10;GitHub - pirogom/walkmgr: for easy window native gui programming on go. enhanced pirogom/walk. for easy window native gui programming on go. enhanced pirogom/walk. - GitHub - pirogom/walkmgr: for easy window native gui programming on go. enhanced pirogom/walk. GitHub - pirogom/walkmgr_example: walkmgr example project walkmgr example project . Contribute to pirogom/walkmgr_example development by creating an account on GitHub. 네이티브 GUI 프로그래밍을 하다 보면 .. 한 화면에 매우 많은 UI요소를 배치해야 하는 경우가 있습니다. 보통 일반 사용자용 프로그램을 만들때 보다는 내부에서 사용할 각종 툴(Tool)같은 것들을 만들때에는 사용성 보다는 기능에 집중하는 경우 같은..</description></item><item><title>[Go언어 윈도 GUI] walkmgr에 상태바(StatusBar) 추가</title><link>https://modu-print.com/posts/2130/</link><pubDate>Fri, 02 Dec 2022 12:34:00 +0900</pubDate><guid>https://modu-print.com/posts/2130/</guid><description>오랜만에 Go언어 관련된 글을 작성합니다.&#10;모두의 프린터, 모두의 PDF등을 비롯한 대부분의 프로그램을 lxn/win, lxn/walk 를 클론해서 조금씩 손보고 해가면서 쓰고 있는데요, 관련 코드는 제 깃헙에 공개를 하고 있습니다. 1일1고 카테고리의 글들을 참고하시면 Go언어로 윈도 GUI 프로그래밍을 하는 것과 관련된 여러 글들을 보실 수 있을겁니다.&#10;이번에 추가한 기능은 .. 자주 쓰이진 않지만 특정 목적의 툴을 만들거나 할때에는 은근 유용한 상태바(StatusBar)를 만들어 넣는방법입니다.</description></item><item><title>[Go언어 윈도 GUI] walkmgr 에 ListControl 추가</title><link>https://modu-print.com/posts/2127/</link><pubDate>Thu, 11 Aug 2022 10:37:00 +0900</pubDate><guid>https://modu-print.com/posts/2127/</guid><description>GitHub - pirogom/walk: Walk is a “Windows Application Library Kit” for the Go Programming Language. Clone from lxn/walk. Walk is a "Windows Application Library Kit" for the Go Programming Language. Clone from lxn/walk. - GitHub - pirogom/walk: Walk is a "Windows Application Library Kit" for the Go… GitHub - pirogom/walkmgr: for easy window native gui programming on go. enhanced pirogom/walk. for easy window native gui programming on go. enhanced pirogom/walk. - GitHub - pirogom/walkmgr: for easy window native gui programming on go. enhanced pirogom/walk. GitHub - pirogom/walkmgr_example: walkmgr example project walkmgr example project . Contribute to pirogom/walkmgr_example development by creating an account on GitHub. Go언어로 윈도API를 이용한 GUI 프로그래밍과 관련된 글을 최근에 계속 작성하고 있는데요..</description></item><item><title>[Go언어 윈도 GUI] walkmgr 에 Progress Bar 추가</title><link>https://modu-print.com/posts/2124/</link><pubDate>Wed, 10 Aug 2022 10:38:00 +0900</pubDate><guid>https://modu-print.com/posts/2124/</guid><description>walkmgr 에 progress bar 기능 추가했습니다. walkmgr_example 저장소에도 예제 적용 되었습니다.&#10;설치나 다운로드시에 진행률을 표시할때 사용하기 좋은 기능입니다. walk 에 기본 내장되어 있었으나 제가 사용빈도가 거의 없어서 추가하지 않았던 기능인데.. 필요하시다는 분들이 계셔서 추가 했습니다.&#10;Go package main import ( "testing" "time" "github.com/pirogom/walkmgr" ) // 프로그래스바 테스트 func TestProgressBar(t testing.T) { wm := walkmgr.NewWin("Progressbar 테스트", 640, 480) pb := wm.ProgressBar(0, 100, 0) wm.Starting(func() { go func() { for { currVal := pb.Value() wm.Sync(func() { pb.SetValue(currVal + 1) }) time.Sleep(250 time.Millisecond) if currVal == pb.MaxValue() { return } } }() }) wm.Start() }</description></item><item><title>[Go언어 윈도 GUI] walkmgr 에 라디오 버튼 추가</title><link>https://modu-print.com/posts/2121/</link><pubDate>Fri, 05 Aug 2022 08:44:00 +0900</pubDate><guid>https://modu-print.com/posts/2121/</guid><description>최근에는 lxn/walk, lxn/win 등을 클론해서 따로 필요한 부분을 수정해서 깃헙에 올려두고 있습니다. walk 를 통한 윈도 GUI 프로그래밍을 조금 수월하게 하고자 walkmgr 이라는 패키지를 만들어 쓰고 있구요.. 이와 관련된건 이 1일1고 카테고리의 이전 글들에 간단히 강좌 비슷한 글을 작성해 두었으니 참고 하시구요 ..&#10;이 walkmgr 은 제가 만드는 모두의 프린터, 모두의 PDF등을 비롯한 윈도 GUI 프로그래밍에 모두 사용되고 있는 패키지들 입니다.</description></item><item><title>참고하기 좋은 Go언어 패키지 추천 - Owncast</title><link>https://modu-print.com/posts/2119/</link><pubDate>Wed, 06 Jul 2022 12:15:00 +0900</pubDate><guid>https://modu-print.com/posts/2119/</guid><description>Go언어를 사용하거나 공부하면서 참고하기 좋을 .. 교제(?) 삼기 좋은 패키지 하나 소개해봅니다.&#10;Owncast Owncast is your self-hosted live streaming solution. GitHub - owncast/owncast: Take control over your live stream video by running it yourself. Streaming + chat out of the box. Take control over your live stream video by running it yourself. Streaming + chat out of the box. - GitHub - owncast/owncast: Take control over your live stream video by running it yourself. Stre… 1인용 미디어 스트리밍 서버입니다.. 만.. </description></item><item><title>GO언어 ORM 무엇을 써야하나?</title><link>https://modu-print.com/posts/2117/</link><pubDate>Wed, 06 Jul 2022 09:24:00 +0900</pubDate><guid>https://modu-print.com/posts/2117/</guid><description/></item><item><title>MS윈도 - 알려진 폴더 경로 얻기</title><link>https://modu-print.com/posts/3379/</link><pubDate>Tue, 28 Jun 2022 09:30:00 +0900</pubDate><guid>https://modu-print.com/posts/3379/</guid><description>시스템 프로그래밍을 하다보면 .. 윈도에서 흔히 쓰는 경로들 ..&#10;바탕화면, 다운로드, 폰트 같은 경로들을 얻어 써야 하는 경우가 있습니다.&#10;이중 바탕화면이나 다운로드 같은 경로는.. 보통은 특정 룰을 가지고 생성되지만 &#10;사용자가 경로를 변경해서 쓸수도 있지요 ..&#10;레지스트리를 직접 읽어서 처리하는 방법도 있지만 32비트 64비트 분리해서 처리하고 이래저래 복잡할 수 있습니다.</description></item><item><title>Go 백엔드 프레임워크 - Echo,Gin vs Fiber</title><link>https://modu-print.com/posts/2115/</link><pubDate>Wed, 22 Jun 2022 13:12:00 +0900</pubDate><guid>https://modu-print.com/posts/2115/</guid><description/></item><item><title>[Go언어/윈도GUI] 파일 드래그앤드랍(Drag&amp;amp;Drop) 처리</title><link>https://modu-print.com/posts/2112/</link><pubDate>Wed, 23 Mar 2022 10:39:00 +0900</pubDate><guid>https://modu-print.com/posts/2112/</guid><description>우선 앞서 lxn/walk 와 win 을 제 깃헙으로 클론해서 따로 관리한다고 글 올렸으니 참고하시구요.&#10;Go언어 윈도 GUI 개발관련 win/walk 패키지 분리 창이나 특정 UI 객체에 드래그앤드랍을 통한 파일처리가 필요한 경우가 있습니다. &#10;예를들어 파일리스트에 파일을 드래그앤 드랍으로 던지면 던진 파일들이 추가가 된다던지.. &#10;LineEdit 에 파일을 드래그앤드랍하면 해당 파일의 경로가 채워 진다던지 .. </description></item><item><title>Go언어 윈도 GUI 개발관련 win/walk 패키지 분리</title><link>https://modu-print.com/posts/2109/</link><pubDate>Wed, 23 Mar 2022 09:39:00 +0900</pubDate><guid>https://modu-print.com/posts/2109/</guid><description>기존에 Go언어로 윈도 GUI 개발과 관련하여 lxn/win, lxn/walk 패키지를 이용한 개발 방법을 글로 작성 했었는데요.. 작성한 글중중에도 .. WebView 의 자바스크립트 오류와 관련해서 이 패키지들을 수정해서 쓰는 법등도 다루긴 했습니다. 이래저래 계속 써 가다보니 .. 저 패키지들을 직접 수정을 해야 하거나 윈도 API중 lxn/win 에 포함안된 함수들이 있거나 해서 추가를 해야하는 등의 일이 계속 일어날 것 같아서 ..&#10;귀찮아서 ;; 안만들고 버티던 .. 깃헙계정을 ;; 결국 만들고 쓰게 되네요 ..</description></item><item><title>[GO언어/GOLANG] ed25519 암호화/복호화/서명/검증 알고리즘</title><link>https://modu-print.com/posts/2107/</link><pubDate>Fri, 11 Mar 2022 09:03:00 +0900</pubDate><guid>https://modu-print.com/posts/2107/</guid><description>특정 데이터의 유효성 검증을 위해서 만든 메소드들입니다. 원래 ECDSA 를 사용하는 놈으로 만들었다가 키를 만드는데 사용되는 P256.. 등의 P시리즈 커브들이 이래저래 말들이 많아서 ED25519를 사용하는 방식으로 변경하였습니다.&#10;ED25519 나 ECDSA는 데이터를 암호화하고 복호화하는데 사용되는게 아니라 특정 데이터에 개인키로 서명(Sign)을 하고 공개키로 서명이 유효한지를 검증해주는 방식으로 사용합니다.&#10;예를들어 데이터가 "피로곰"인 경우에 서버에서 "피로곰"에 개인키로 서명을하고 서명되고 암호화된 데이터를 클라이언트에 전송하면 클라이언트에서는 "피로곰"과 서버에서 보내준 서명된 데이터를 가지고 공개키로 검증을 합니다. </description></item><item><title>[Go언어/GOLANG] RSA 암호화/복호화</title><link>https://modu-print.com/posts/2104/</link><pubDate>Fri, 04 Mar 2022 14:09:00 +0900</pubDate><guid>https://modu-print.com/posts/2104/</guid><description>암호화 관련된 자료들은 워낙 찾아보면 많이 나오는 편이라서;; 근데 또 막상 찾아서 쓸라 하면 또 GPL이고 그래서 짜려니 귀찮고 그런경우가 많다 말이죠 ..&#10;그런이유로 -_-;; 간단히 막 짜서 쓸려고 만든것좀 공유해 봅니다.&#10;Go // // Author: PIROGOM // https://modu-print.com // mop.pirogom@gmail.com // MIT License // package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/hex" "encoding/pem" "errors" "io/ioutil" ) type RSAHelper struct { PriKey rsa.PrivateKey PubKey rsa.PublicKey } / * RSA Key 생성 / func (r RSAHelper) GenerateKey(bits int) error { privateKey, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { r.PriKey = nil r.PubKey = nil return err } r.PriKey = privateKey r.PubKey = &amp;privateKey.PublicKey return nil } func (r RSAHelper) GetPrivate() rsa.PrivateKey { return r.PriKey } func (r RSAHelper) GetPublic() rsa.PublicKey { return r.PubKey } /** PrivateToBytePEM *&#9;PrivateToStringPEM / func (r RSAHelper) PrivateToBytePEM() ([]byte, error) { if r.PriKey == nil { return nil, errors.New("private rsa key is nil") } privateKeyBytes := x509.MarshalPKCS1PrivateKey(r.PriKey) privateKeyPEM := pem.EncodeToMemory( &amp;pem.Block{ Type: "RSA PRIVATE KEY", Bytes: privateKeyBytes, }, ) return privateKeyPEM, nil } func (r RSAHelper) PrivateToStringPEM() (string, error) { pemBuf, err := r.PrivateToBytePEM() if err != nil { return "", err } return string(pemBuf), nil } / *&#9;PrivateFromBytePEM *&#9;PrivateFromFilePEM / func (r RSAHelper) PrivateFromBytePEM(privateKeyPEM []byte) error { block, _ := pem.Decode(privateKeyPEM) if block == nil { r.PriKey = nil return errors.New("invalid PEM Block(private key)") } privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { r.PriKey = nil return err } r.PriKey = privateKey return nil } func (r RSAHelper) PrivateFromStringPEM(privateKeyPEM string) error { return r.PrivateFromBytePEM([]byte(privateKeyPEM)) } func (r *RSAHelper) PrivateFromFilePEM(filename string) error { fileBuf, err := ioutil.ReadFile(filename) if err != nil { return err } err = r.PrivateFromBytePEM(fileBuf) return err } / *&#9;PublicToBytePEM * PublicToStringPEM / func (r RSAHelper) PublicToBytePEM() ([]byte, error) { if r.PubKey == nil { return nil, errors.New("public rsa key is nil") } publicKeyBytes, err := x509.MarshalPKIXPublicKey(r.PubKey) if err != nil { return nil, err } publicKeyPEM := pem.EncodeToMemory( &amp;pem.Block{ Type: "RSA PUBLIC KEY", Bytes: publicKeyBytes, }, ) return publicKeyPEM, nil } func (r RSAHelper) PublicToStringPEM() (string, error) { buf, err := r.PublicToBytePEM() if err != nil { return "", err } return string(buf), nil } / *&#9;PublicFromBytePEM / func (r RSAHelper) PublicFromBytePEM(publicKeyPEM []byte) error { block, _ := pem.Decode(publicKeyPEM) if block == nil { r.PubKey = nil return errors.New("invalid PEM Block (public key)") } publicKey, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { r.PubKey = nil return err } switch pub := publicKey.(type) { case rsa.PublicKey: r.PubKey = pub return nil default: return errors.New("invalid key type") } } func (r RSAHelper) PublicFromStringPEM(publicKeyPEM []byte) error { return r.PublicFromBytePEM([]byte(publicKeyPEM)) } func (r RSAHelper) PublicFromFilePEM(filename string) error { fileBuf, err := ioutil.ReadFile(filename) if err != nil { return err } err = r.PublicFromBytePEM(fileBuf) return err } / *&#9;EncryptByte / func (r RSAHelper) EncryptByte(src []byte) ([]byte, error) { if r.PubKey == nil { return nil, errors.New("public key is nil") } ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, r.PubKey, src) if err != nil { return nil, err } return ciphertext, nil } func (r RSAHelper) EncryptString(src string) (string, error) { enc, err := r.EncryptByte([]byte(src)) if err != nil { return "", err } return hex.EncodeToString(enc), nil } / * DecryptByte **/ func (r RSAHelper) DecryptByte(src []byte) ([]byte, error) { if r.PriKey == nil { return nil, errors.New("private key is nil") } plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, r.PriKey, src) if err != nil { return nil, err } return plaintext, nil } func (r RSAHelper) DecryptString(src string) (string, error) { bsrc, err := hex.DecodeString(src) if err != nil { return "", err } dec, err := r.DecryptByte(bsrc) if err != nil { return "", err } return string(dec), nil }</description></item><item><title>[Go언어/GUI] WebView이용시 자바스크립트 오류 문제</title><link>https://modu-print.com/posts/2097/</link><pubDate>Mon, 28 Feb 2022 12:10:00 +0900</pubDate><guid>https://modu-print.com/posts/2097/</guid><description>앞서 Go언어의 lxn/win, lxn/walk 그리고 제가 막 만든(강조합니다 막 만든겁니다) walk_wrap.go 를 이용해서 윈도 GUI 프로그래밍을 할때.. 웹뷰를 추가 가능한데요..&#10;이 웹뷰는 ..&#10;IE기반의 OLE 객체를 끌어다 동작을 하는지라 최신 웹 브라우저에 비해선 기능이 조금 ;; 제한적이긴 합니다. 그중 가장큰 문제는 .. 자바스크립트 오류가 발생시에는 .. &#10;이런식으로 스크립트 오류창이 뜬다는 것이지요. 최신 브라우져들의 경우엔 개발자도구를 지원하기 때문에 이런식으로 자바스크립트 오류가 뜬다해서 메시지 창을 띄워가며 실행을 하네마네를 묻지 않습니다. 이게 상당히 거슬리는데 ..</description></item><item><title>1/1000초, 밀리세컨드, Milliseconds 얻기</title><link>https://modu-print.com/posts/3384/</link><pubDate>Sat, 26 Feb 2022 09:34:00 +0900</pubDate><guid>https://modu-print.com/posts/3384/</guid><description>Go언어에서 일반적으로 시간을 다루는 패키지는 time 이라는 기본 패키지를 사용합니다. 이 패키지를 통해서 time.Now().Unix() 로 Timestamp 값도 얻을수 있곤 합니다만.. &#10;흔히 윈도에서 프로그래밍을 많이 한 분들은 1/1000초 단위.. 그러니까 밀리세컨드 단위의 시간을 다루는걸 더 선호하시는 경우가 많습니다. &#10;하지만 Go언어의 time 패키지에는 직접적으로 밀리세컨드를 얻을 수 있는 함수는 존재하지 않습니다.&#10;Go /** *&#9;timeGetTime **/ func timeGetTime() int64 { return time.Now().UnixNano() / 1000000 } 결론은 .. 나노 세컨드를 나눠서 쓰시면 되겠습니다.. 너무 복잡하고 어렵게 생각 마세요 ㅋㅋ 어짜피 컴퓨터라는 놈의 시간 정확도라는 것은 그리 정확하지 않답니다 ㅋㅋ</description></item><item><title>[Go언어/GUI] WebView 로딩 문제 ..</title><link>https://modu-print.com/posts/2100/</link><pubDate>Tue, 22 Feb 2022 09:21:00 +0900</pubDate><guid>https://modu-print.com/posts/2100/</guid><description>앞서 강좌?? 까진 아니어도 여튼간에.. Go언어에서 윈도 Gui를 구성하는 법에 대한 글들 중 웹뷰를 설명한 적 있는데요. 이 웹뷰를 사용함에 있어서 한 가지 눈에 거슬리는 부분이 생기실겁니다.&#10;보시면.. 창이 뜨고 잠시후에 웹뷰가 표시되는 걸 보실 수 있는데요.. 이건 이 IWebBrowser2라는 놈이 OLE/COM 그러니까 흔히 말하는 OCX로 만들어진 놈이라.. &#10;원래 MFC로 다이얼로그 베이스의 프로그램을 만들거나 할 경우에는 프로그램의 생성자 즈음에 이 OCX객체의 초기화 관련 코드도 진행을 하기 때문에 .. 창이 표시되기 전에 웹뷰 관련 초기화가 이미 진행이 된 상태라 창이 표시되는 시점과 웹뷰가 준비된 시점이 거의 비슷하지만..</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #13</title><link>https://modu-print.com/posts/2092/</link><pubDate>Wed, 16 Feb 2022 10:40:00 +0900</pubDate><guid>https://modu-print.com/posts/2092/</guid><description>앞서 12개의 글을 쓰면서 작성한 예제 코드를 올립니다.&#10;예제코드 다운로드 받기&#10;포함된 파일들에 대해서 설명 드리자면&#10;DEMO.ico, test.ico 아이콘 파일입니다. img0.png, img1.png, img3.png ImageView 예제에서 사용된 이미지 파일입니다. list_model.go, list_sample.go, test_table_cbmodel.go TableView 예제를 포함한 소스파일 main.go main 함수가 존재하고 대부분의 예제에 사용된 함수들이 있습니다. Makefile make 명령을 위한 Makefile walk_wrap.go 피로곰이 막 만든 walk 랩퍼 WALK_WRAP.manifest syso 파일을 만들기 위한 메니페스트 파일 WALK_WARP.syso rsrc 명령으로 만들어진 오브젝트 파일 우선</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #12</title><link>https://modu-print.com/posts/2090/</link><pubDate>Wed, 16 Feb 2022 10:29:00 +0900</pubDate><guid>https://modu-print.com/posts/2090/</guid><description>아마 walk와 제가 대충 만든 walk_wrap.go 를 이용한 윈도 gui 프로그래밍에 대한 글은 이게 마지막? 이지 않을까 싶은데요 응용법이나 그런걸 좀더 세세하게 글을 더 쓸지는 모르겠지만.&#10;이번에 다룰 내용은 특정 GUI요소에 대한게 아니라 Go와 Walk를 가지고 윈도GUI를 함에 있어서 가장 주의해야할 사항을 말씀드리겠습니다.&#10;Go언어의 가장큰 장점은 동시성 프로그래밍이 매우 단순하다는 것이지요..&#10;흔히 윈도 프로그래밍을 할때 스레드(Thread)를 생성할때는 위의 CreateThread나 _beginthread 같은 함수를 사용하는데 인자도 많고 복잡해 보입니다.. </description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #11</title><link>https://modu-print.com/posts/2087/</link><pubDate>Wed, 16 Feb 2022 09:35:00 +0900</pubDate><guid>https://modu-print.com/posts/2087/</guid><description>이번에는 .. 얼마전에 모두의 프린터 업데이트 하면서 추가시킨 웹뷰(WebView)를 다뤄보도록 하겠습니다.&#10;한가지 주의 하실점은 윈도 API에서 지원하는 WebView는 흔히 IWebBrowser2 라고 불리는 COM+로 오랜세월 윈도에 내장된 레거시 브라우져 컴포넌트를 이용하게 됩니다. 그말은 현재 우리가 많이쓰는 HTML5 기반의 크롬이나 엣지나 파이어폭스 같은 브라우저보다 몇세대 전 기술을 사용하는 .. &#10;그냥 쉽게 IE라고 보시면 됩니다. 그렇다 보니 너무 최신의 CSS나 HTML, Javascript 를 사용한 페이지 에서는 스크립트 오류나 기타 여러 증상이 나타날 순 있습니다.</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #10</title><link>https://modu-print.com/posts/2084/</link><pubDate>Fri, 04 Feb 2022 10:31:00 +0900</pubDate><guid>https://modu-print.com/posts/2084/</guid><description>오랜만입니다.. 이래저래 벌린일이 많다보니 ..&#10;이번에는 PushButton 과 ImageView 를 다뤄 보겠습니다.. 푸쉬 버튼의 경우에는 워낙 오만 예제에서 이미 다 등장을 햇던 놈이라 굳이 설명을 하지 않더라도 대충;; 뭔지 아실테지만 .. 간단하게나마 설명하고 넘어가겠습니다.&#10;Go / *&#9;PushButton / func (m WinResMgr) PushButton(text string, clickFunc func()) walk.PushButton { btn, _ := walk.NewPushButton(m.GetParent()) btn.SetText(text) btn.Clicked().Attach(clickFunc) m.addObj(btn) return btn }</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #9</title><link>https://modu-print.com/posts/2081/</link><pubDate>Tue, 11 Jan 2022 22:21:00 +0900</pubDate><guid>https://modu-print.com/posts/2081/</guid><description>이번엔 가장 활용도가 높은 편인 테이블뷰에 대해서 알려드리겠습니다.&#10;우선;; interface{}를 사용해서 조금 고급지게 리스트박스를 위한 모델구조를 잡고 하면 보긴 좋긴 하겠으나 애초에 그냥 막 짜서 적용해서 쓰기 바쁜 와중에 만들어 쓴 코드고.. &#10;lxn/walk 의 샘플 코드에 존재하는 것들을 크게 건드리지 않고 사용하다보니 그닥 맘에 드는 구조는 아니라는 점은 미리 말씀드립니다.&#10;우선 테이블을 구성하기 위해서는 2개의 구조체와 몇가지 메소드를 미리 작성하셔야 합니다.</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #8</title><link>https://modu-print.com/posts/2079/</link><pubDate>Mon, 10 Jan 2022 12:06:00 +0900</pubDate><guid>https://modu-print.com/posts/2079/</guid><description>이번에는 .. 드롭다운박스를 다뤄보도록 하겠습니다.&#10;Go func comboTest1() { mgr, _ := NewWindowMgrNoResize("콤보박스 테스트", 640, 200, GetIcon()) dd1 := mgr.DropDownBox([]string{"1.하하", "2.호호", "3.ㅋㅋ", "4.ㅎㅎ"}) dd1.CurrentIndexChanged().Attach(func() { fmt.Printf("선택된 인덱스 : %d, 선택된 값 : %s\n", dd1.CurrentIndex(), dd1.Text()) }) mgr.StartForeground() }</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #7</title><link>https://modu-print.com/posts/2077/</link><pubDate>Mon, 03 Jan 2022 10:10:00 +0900</pubDate><guid>https://modu-print.com/posts/2077/</guid><description>이번엔 각종 설정창 등을 만드는데 어찌보면 가장 유용하게 사용하는 체크박스(Checkbox)에 대해서 다뤄보도록 하겠습니다.&#10;Go func (m *WinResMgr) CheckBox(text string, checked bool, attachFunc func()) *walk.CheckBox CheckBox 메소드를 사용하시면 되구요. </description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #6</title><link>https://modu-print.com/posts/2073/</link><pubDate>Thu, 23 Dec 2021 18:04:00 +0900</pubDate><guid>https://modu-print.com/posts/2073/</guid><description>이번엔 EditText? EditBox? 여튼;; 텍스트고 숫자고 입력을 받는 놈을 다뤄보겠습니다.&#10;Go func (m *WinResMgr) NumberEdit() *walk.NumberEdit func (m *WinResMgr) LineEdit(ro bool) *walk.LineEdit func (m *WinResMgr) TextEdit(ro bool) *walk.TextEdit func (m *WinResMgr) TextArea(ro bool) *walk.TextEdit 이정도 되겠습니다.. </description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #5</title><link>https://modu-print.com/posts/2069/</link><pubDate>Fri, 17 Dec 2021 11:07:00 +0900</pubDate><guid>https://modu-print.com/posts/2069/</guid><description>이번에는 각 UI구성 요소들에 대한 부분을 진행 해보도록 합시다.&#10;대충 일반적으로 말하는 라벨(Label, Static Text), 에디트박스, 체크박스, 리스트박스, 이미지컨트롤, 콤보박스 이딴 것들에 대해 논해보도록 합니다. 이러한 놈들은 얼찌 배치 할지는 이전 시간에 다뤘으니까 이전글들 참고 하시고요, 그런 부분들은 직접 해보시면 충분할 거구요.. 그정도 코드도 직접 안짜보고 이해할꺼면 개발자 때려 쳐야죠.. 어디 ㅋㅋ 그런 정신 머리로 개발자 나부랭이를 해보겠다고 크앙!&#10;우선 가장 많이 쓰이는 놈중 하나인 라벨을 먼저 갑시다.</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #4</title><link>https://modu-print.com/posts/2065/</link><pubDate>Fri, 10 Dec 2021 11:01:00 +0900</pubDate><guid>https://modu-print.com/posts/2065/</guid><description>Go로 윈도 네이티브 GUI 줘 패기... 4번째 입니다.&#10;이번엔 레이아웃에 대한 부분을 다뤄보도록 합니다.&#10;앞서 C/C++에서 윈도 API를 가지고 GUI 어플리케이션을 만드는게 매우 비효율적인 노가다 개삽질이라는 식의 표현을 한적이 있는데요. 그 이유는 ..&#10;API에서 모든 UI객체는 전부다 윈도입니다. 창도 윈도 버튼도 윈도 에디트 박스도 체크박스도 스크롤바도 스크롤바 안의 상하단 버튼도 죄~~다 윈도입니다. 그 말은 그 하나하나를 다 CreateWindow 를 하고 그 각 객체별로 WndProc 같은 메시지 프로시저를 한땀 한땀 다 등록을 시켜야 한단 소리죠 그래야 키보드 입력이던 마우스 클릭이던 내용을 그리고 지우고 지지고 볶고 .. 가 가능합니다.</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #3</title><link>https://modu-print.com/posts/2058/</link><pubDate>Thu, 09 Dec 2021 12:27:00 +0900</pubDate><guid>https://modu-print.com/posts/2058/</guid><description>Go언어로 윈도GUI .. 3번째 글입니다.&#10;우선 관련 글들을 작성하면서 계속 사용하게될 소스파일 하나 먼저 던져 놓고 시작하겠습니다.&#10;walk_wrap.go&#10;Go // Copyright 2021 PIROGOM // MIT License // https://modu-print.tistory.com package main import ( "container/list" "io/ioutil" "os" "path/filepath" "sync" "github.com/lxn/walk" "github.com/lxn/win" ) const ( walkWinName = "WALK_WRAP" ) / *&#9;tableViewHeader / type tableViewHeader struct { Title string Width int Align string } / *&#9;WinResMgr / type WinResMgr struct { window walk.MainWindow parentList list.List } var ( gIcon walk.Icon iconMutex sync.Mutex ) /** LoadIcon / func LoadIcon(icoBuf []byte, icoName string) { icoFile := filepath.Join(os.TempDir(), icoName) var err error if , err = os.Stat(icoName); os.IsNotExist(err) { if err = ioutil.WriteFile(icoFile, icoBuf, 0644); err != nil { return } } iconMutex.Lock() gIcon, = walk.NewIconFromFile(icoFile) iconMutex.Unlock() } / *&#9;LoadIconFromFile / func LoadIconFromFile(icoPath string) { iconMutex.Lock() defer iconMutex.Unlock() gIcon, _ = walk.NewIconFromFile(icoPath) } / *&#9;GetIcon / func GetIcon() *walk.Icon { iconMutex.Lock() defer iconMutex.Unlock() return gIcon } / *&#9;MsgBox / func MsgBox(msg string, window …*walk.MainWindow) { if len(window) &gt; 0 { walk.MsgBox(window[0], "알림", msg, walk.MsgBoxOK|walk.MsgBoxSetForeground) } else { walk.MsgBox(nil, "알림", msg, walk.MsgBoxOK|walk.MsgBoxSetForeground) } } / *&#9;Confirm / func Confirm(msg string, window …*walk.MainWindow) bool { if len(window) &gt; 0 { if walk.MsgBox(window[0], "알림", msg, walk.MsgBoxYesNo|walk.MsgBoxSetForeground) == win.IDNO { return false } else { return true } } else { if walk.MsgBox(nil, "알림", msg, walk.MsgBoxYesNo|walk.MsgBoxSetForeground) == win.IDNO { return false } else { return true } } return false } / *&#9;NewWindowMgr / func NewWindowMgr(title string, width int, height int, icon walk.Icon) (WinResMgr, *walk.MainWindow) { rd := WinResMgr{} win, _ := walk.NewMainWindowWithName(walkWinName) rd.window = win rd.parentList = list.New() win.SetTitle(title) win.SetLayout(walk.NewVBoxLayout()) win.SetWidth(width) win.SetHeight(height) if icon != nil { win.SetIcon(icon) } return &amp;rd, win } / *&#9;NewWindowMgrNoResize / func NewWindowMgrNoResize(title string, width int, height int, icon walk.Icon) (WinResMgr, *walk.MainWindow) { rd := WinResMgr{} win, _ := walk.NewMainWindowWithName(walkWinName) rd.window = win rd.parentList = list.New() win.SetTitle(title) win.SetLayout(walk.NewVBoxLayout()) win.SetWidth(width) win.SetHeight(height) if icon != nil { win.SetIcon(icon) } win.SetMinMaxSize(walk.Size{Width: width, Height: height}, walk.Size{Width: width, Height: height}) rd.NoResize() return &amp;rd, win } / *&#9;NewWindowMgrNoResizeNoMinMax / func NewWindowMgrNoResizeNoMinMax(title string, width int, height int, icon walk.Icon) (WinResMgr, *walk.MainWindow) { rd := WinResMgr{} win, _ := walk.NewMainWindowWithName(walkWinName) rd.window = win rd.parentList = list.New() win.SetTitle(title) win.SetLayout(walk.NewVBoxLayout()) win.SetWidth(width) win.SetHeight(height) if icon != nil { win.SetIcon(icon) } win.SetMinMaxSize(walk.Size{Width: width, Height: height}, walk.Size{Width: width, Height: height}) rd.NoResize() rd.DisableMinMaxBox(true, true) return &amp;rd, win } / *&#9;NewWindowMgrAds / func NewWindowMgrAds(title string, width int, height int) (WinResMgr, walk.MainWindow) { rd := WinResMgr{} win, _ := walk.NewMainWindowWithName(walkWinName) rd.window = win rd.parentList = list.New() win.SetTitle(title) layout := walk.NewVBoxLayout() margin := walk.Margins{0, 0, 0, 0} layout.SetMargins(margin) layout.SetSpacing(0) win.SetLayout(layout) win.SetWidth(width) win.SetHeight(height) win.SetMinMaxSize(walk.Size{Width: width, Height: height}, walk.Size{Width: width, Height: height}) rd.NoResize() rd.DisableTitleBar() rd.AdsPosition() return &amp;rd, win } / *&#9;HideAndClose / func (m *WinResMgr) HideAndClose() { m.window.Synchronize(func() { m.window.SetVisible(false) m.window.Close() }) } / *&#9;Center / func (m *WinResMgr) Center() { var x, y, width, height int32 var rtDesk, rtWindow win.RECT win.GetWindowRect(win.GetDesktopWindow(), &amp;rtDesk) win.GetWindowRect(m.window.Handle(), &amp;rtWindow) width = rtWindow.Right - rtWindow.Left height = rtWindow.Bottom - rtWindow.Top x = (rtDesk.Right - width) / 2 y = (rtDesk.Bottom - height) / 2 win.MoveWindow(m.window.Handle(), x, y, width, height, true) } / *&#9;AdsPosition / func (m *WinResMgr) AdsPosition() { var x, y, width, height int32 var rtDesk, rtWindow win.RECT win.GetWindowRect(win.GetDesktopWindow(), &amp;rtDesk) win.GetWindowRect(m.window.Handle(), &amp;rtWindow) width = rtWindow.Right - rtWindow.Left height = rtWindow.Bottom - rtWindow.Top x = rtDesk.Right - width y = rtDesk.Bottom - (height + 40) win.MoveWindow(m.window.Handle(), x, y, width, height, true) } / *&#9;Foreground / func (m *WinResMgr) Foreground() { win.SetForegroundWindow(m.window.Handle()) } / *&#9;NoResize / func (m *WinResMgr) NoResize() { defStyle := win.GetWindowLong(m.window.Handle(), win.GWL_STYLE) newStyle := defStyle &amp;^ win.WS_THICKFRAME win.SetWindowLong(m.window.Handle(), win.GWL_STYLE, newStyle) } / *&#9;DisableMinMaxBox / func (m *WinResMgr) DisableMinMaxBox(minBox bool, maxBox bool) { defStyle := win.GetWindowLong(m.window.Handle(), win.GWL_STYLE) newStyle := defStyle if minBox { newStyle = newStyle &amp;^ win.WS_MINIMIZEBOX } if maxBox { newStyle = newStyle &amp;^ win.WS_MAXIMIZEBOX } win.SetWindowLong(m.window.Handle(), win.GWL_STYLE, newStyle) } / *&#9;DisableCloseBox / func (m *WinResMgr) DisableCloseBox() { defStyle := win.GetWindowLong(m.window.Handle(), win.GWL_STYLE) newStyle := defStyle &amp;^ win.WS_SYSMENU win.SetWindowLong(m.window.Handle(), win.GWL_STYLE, newStyle) } / *&#9;DisableTitleBar / func (m *WinResMgr) DisableTitleBar() { defStyle := win.GetWindowLong(m.window.Handle(), win.GWL_STYLE) newStyle := defStyle &amp;^ win.WS_CAPTION win.SetWindowLong(m.window.Handle(), win.GWL_STYLE, newStyle) } / *&#9;HSplit / func (m WinResMgr) HSplit() walk.Splitter { hs, _ := walk.NewHSplitter(m.GetParent()) m.parentList.PushBack(hs) return hs } / *&#9;VSplit / func (m WinResMgr) VSplit() walk.Splitter { vs, _ := walk.NewVSplitter(m.GetParent()) m.parentList.PushBack(vs) return vs } / *&#9;EndSplit / func (m *WinResMgr) EndSplit() { if m.parentList.Len() &gt; 0 { popData := m.parentList.Remove(m.parentList.Back()) parent := m.GetParent() parent.Children().Add(popData.(walk.Widget)) } } / *&#9;GroupBox / func (m WinResMgr) GroupBox(title string, isVertical bool) walk.GroupBox { gb, _ := walk.NewGroupBox(m.GetParent()) gb.SetTitle(title) if !isVertical { gb.SetLayout(walk.NewHBoxLayout()) } else { gb.SetLayout(walk.NewVBoxLayout()) } m.parentList.PushBack(gb) return gb } / *&#9;EndGroupBox / func (m *WinResMgr) EndGroupBox() { if m.parentList.Len() &gt; 0 { popData := m.parentList.Remove(m.parentList.Back()) parent := m.GetParent() parent.Children().Add(popData.(walk.Widget)) } } / *&#9;DefClosing / func (m *WinResMgr) DefClosing() { m.window.Closing().Attach(func(canceled bool, reason walk.CloseReason) { if m.window.Visible() { canceled = true } }) } / *&#9;StartWindow / func (m *WinResMgr) StartWindow() { m.Center() m.window.Show() m.window.Run() } / *&#9;StartForeground / func (m *WinResMgr) StartForeground() { m.Center() m.Foreground() m.window.Show() m.window.Run() } / *&#9;StartAds / func (m *WinResMgr) StartAds() { //m.AdsPosition() m.Foreground() m.window.Show() m.window.Run() } / *&#9;Hide / func (m *WinResMgr) Hide() { m.window.Hide() } / *&#9;ShowForeground / func (m *WinResMgr) ShowForeground() { m.Center() m.Foreground() m.window.Show() } / *&#9;HideStart / func (m *WinResMgr) HideStart() { m.window.Hide() m.window.Run() } / *&#9;addObj / func (m *WinResMgr) addObj(item walk.Widget) { if m.parentList.Len() == 0 { m.window.Children().Add(item) } else { parent := m.parentList.Back().Value.(walk.Container) parent.Children().Add(item) } } / *&#9;GetParent / func (m *WinResMgr) GetParent() walk.Container { if m.parentList.Len() &gt; 0 { parent := m.parentList.Back().Value.(walk.Container) return parent } else { return m.window } } / *&#9;MultiLineLabel / func (m WinResMgr) MultiLineLabel(text string) walk.Label { ne, _ := walk.NewLabelWithStyle(m.GetParent(), win.SS_EDITCONTROL) //|win.SS_CENTER) ne.SetText(text) ne.SetAlignment(walk.AlignHCenterVCenter) ne.SetTextAlignment(walk.AlignCenter) m.addObj(ne) return ne } / *&#9;Label / func (m WinResMgr) Label(text string) walk.Label { ne, _ := walk.NewLabel(m.GetParent()) ne.SetText(text) ne.SetTextAlignment(walk.AlignDefault) m.addObj(ne) return ne } / * LabelCenter / func (m WinResMgr) LabelCenter(text string) walk.Label { ne, _ := walk.NewLabel(m.GetParent()) ne.SetText(text) ne.SetTextAlignment(walk.AlignCenter) m.addObj(ne) return ne } / * LabelRight / func (m WinResMgr) LabelRight(text string) walk.Label { ne, _ := walk.NewLabel(m.GetParent()) ne.SetText(text) ne.SetTextAlignment(walk.AlignFar) m.addObj(ne) return ne } / * LabelLeft / func (m WinResMgr) LabelLeft(text string) walk.Label { ne, _ := walk.NewLabel(m.GetParent()) ne.SetText(text) ne.SetTextAlignment(walk.AlignNear) m.addObj(ne) return ne } / *&#9;CheckBox / func (m WinResMgr) CheckBox(text string, checked bool, attachFunc func()) walk.CheckBox { cb, _ := walk.NewCheckBox(m.GetParent()) cb.SetText(text) cb.SetChecked(checked) cb.CheckStateChanged().Attach(attachFunc) m.addObj(cb) return cb } / *&#9;DropDownBox / func (m WinResMgr) DropDownBox(data []string) walk.ComboBox { cb, _ := walk.NewDropDownBox(m.GetParent()) cb.SetModel(data) cb.SetCurrentIndex(0) m.addObj(cb) return cb } / *&#9;PushButton / func (m WinResMgr) PushButton(text string, clickFunc func()) walk.PushButton { btn, _ := walk.NewPushButton(m.GetParent()) btn.SetText(text) btn.Clicked().Attach(clickFunc) m.addObj(btn) return btn } / *&#9;NumberEdit / func (m WinResMgr) NumberEdit() walk.NumberEdit { ne, _ := walk.NewNumberEdit(m.GetParent()) m.addObj(ne) return ne } / *&#9;NumberEdit / func (m WinResMgr) NumberEditInt(val int) walk.NumberEdit { ne, _ := walk.NewNumberEdit(m.GetParent()) ne.SetValue(float64(val)) m.addObj(ne) return ne } / *&#9;LineEdit / func (m WinResMgr) LineEdit(ro bool) walk.LineEdit { ne, _ := walk.NewLineEdit(m.GetParent()) ne.SetReadOnly(ro) m.addObj(ne) return ne } / *&#9;TextEdit / func (m WinResMgr) TextEdit(ro bool) walk.TextEdit { ne, _ := walk.NewTextEdit(m.GetParent()) ne.SetReadOnly(ro) m.addObj(ne) return ne } / *&#9;TextEdit / func (m WinResMgr) TextEdit2(msg string, ro bool) walk.TextEdit { ne, _ := walk.NewTextEdit(m.GetParent()) ne.SetText(msg) ne.SetReadOnly(ro) m.addObj(ne) return ne } / *&#9;TextArea / func (m WinResMgr) TextArea(ro bool) walk.TextEdit { ne, _ := walk.NewTextEditWithStyle(m.GetParent(), win.WS_VSCROLL) ne.SetReadOnly(ro) m.addObj(ne) return ne } / *&#9;Slider / func (m WinResMgr) Slider(minVal int, maxVal int, defVal int) walk.Slider { ne, _ := walk.NewSlider(m.GetParent()) ne.SetRange(minVal, maxVal) ne.SetValue(defVal) m.addObj(ne) return ne } / *&#9;TableView / func (m WinResMgr) TableView(model interface{}, header []tableViewHeader, checkBox bool, multiSelect bool) walk.TableView { tv, _ := walk.NewTableView(m.GetParent()) tv.SetCheckBoxes(checkBox) tv.SetMultiSelection(multiSelect) tv.SetModel(model) for i := 0; i &lt; len(header); i++ { col := walk.NewTableViewColumn() col.SetTitle(header[i].Title) col.SetWidth(header[i].Width) switch header[i].Align { case "center": col.SetAlignment(walk.AlignCenter) case "right": col.SetAlignment(walk.AlignFar) case "left": col.SetAlignment(walk.AlignNear) } tv.Columns().Add(col) } m.addObj(tv) return tv } / *&#9;ImageViewFromFile / func (m WinResMgr) ImageViewFromFile(imgFile string) walk.ImageView { iv, _ := walk.NewImageView(m.GetParent()) img, imgErr := walk.NewImageFromFile(imgFile) if imgErr == nil { iv.SetImage(img) } m.addObj(iv) return iv } / *&#9;ImageViewFromFile2 / func (m WinResMgr) ImageViewFromFile2(imgFile string, im walk.ImageViewMode) walk.ImageView { iv, _ := walk.NewImageView(m.GetParent()) img, imgErr := walk.NewImageFromFile(imgFile) if imgErr == nil { iv.SetMode(im) iv.SetImage(img) } m.addObj(iv) return iv } / *&#9;ImageView / func (m WinResMgr) ImageView() walk.ImageView { iv, _ := walk.NewImageView(m.GetParent()) m.addObj(iv) return iv } / *&#9;LoadImage / func LoadImage(fileName string) *walk.Image { retImage, retImageErr := walk.NewImageFromFile(fileName) if retImageErr != nil { return nil } return &amp;retImage } / *&#9;SetMultiLineText **/ func MultiLineText(text string, limit int) string { runeText := []rune(text) var res string for { if len(runeText) &lt;= limit { res += string(runeText) break } res += string(runeText[:limit]) + "\n" runeText = runeText[limit:] } return res }</description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #2</title><link>https://modu-print.com/posts/2055/</link><pubDate>Wed, 08 Dec 2021 11:03:00 +0900</pubDate><guid>https://modu-print.com/posts/2055/</guid><description>Go로 윈도 네이티브 GUI 프로그램만들기 2번째 입니다.&#10;앞서 lxn/win, walk 2개 패키지는 go get 하셨을 테구요.. 보통 윈도 API 프로그래밍은 C/C++ 에서도 노가다의 최 정점에 놓여진 그런 놈입니다 ㅋㅋ 그게 싫어서 쓰는게 go 같은 언어들인거고 .. &#10;그런 이유로 이 lxn/walk 의 경우에도 좀더 편하게 GUI를 만들수 있는 방법을 제공하는데요.&#10;그게 lxn/walk 패키지에 포함된 declarative 라는 패키지 입니다. </description></item><item><title>Go로 MS 윈도 네이티브 GUI 프로그램 만들기 #1</title><link>https://modu-print.com/posts/2047/</link><pubDate>Wed, 08 Dec 2021 10:00:00 +0900</pubDate><guid>https://modu-print.com/posts/2047/</guid><description>앞서 크롤러 관련된 강좌를 하다 만게 있는데요.. 요청이 가장 많았어서 시작을 하긴 했는데 아무래도 크롤러가 개발자 입장으론 윤리문제가 좀 있는 영역이고 법적으로도 문제 소지가 발생할 가능성이 매우 큰 영역이라 그걸 대놓고 강좌랍시고 하는 건 좀 ;; 아닌 것 같다는 피드백도 꽤 됐던 지라.. 크롤러 관련된 강좌는 하지 않겠습니다.&#10;저는 Go개발에 MS의 Visual Studio Code를 사용합니다. 관련 사항은 이전 111GO 글을 참고바랍니다.</description></item><item><title>MS VC++ 재배포가능 패키지 존재여부 체크</title><link>https://modu-print.com/posts/3382/</link><pubDate>Sat, 06 Nov 2021 09:32:00 +0900</pubDate><guid>https://modu-print.com/posts/3382/</guid><description>보통 윈도 API를 쓰는 프로그램을 개발해서 배포를할 경우에 .. 적절한 시스템 DLL 이 존재하지 않으면 .. 프로그램이 그냥 죽어버립니다 ㅎㅎ 그래서 많은 프로그램들이 위와같은 .. 재배포가능 패키지를 같이 설치하곤 합니다만 ..&#10;여튼간에 ;; 개발을 하다보면 시스템에 재배포가능 패키지가 존재하는지 안하는지를 ;; 버전 상관 없이 ..&#10;한놈만 있음 되는 그런 상황이 오게 되지요 ..</description></item><item><title>Go 윈도 프로그래밍시 실행파일에 리소스정보 적용</title><link>https://modu-print.com/posts/3743/</link><pubDate>Mon, 18 Oct 2021 12:05:00 +0900</pubDate><guid>https://modu-print.com/posts/3743/</guid><description>우선 Walk를 쓰던 뭘 하던 윈도용 프로그램을 만드는 경우에는 .. 프로그램의 아이콘을 지정하고 싶기도 하고 .. &#10;프로그램의 기본 아이콘과 보통 윈도 프로그래밍에서 말하는 메니페스트(Manifest)의 적용은 rsrc 라는 패키지를 통해 합니다.&#10;GitHub - akavel/rsrc: Tool for embedding .ico &amp; manifest resources in Go programs for Windows. Tool for embedding .ico &amp; manifest resources in Go programs for Windows. - GitHub - akavel/rsrc: Tool for embedding .ico &amp; manifest resources in Go programs for Windows. 요 패키지를 go get ( 최근 go에서는 go install ) 해서 우선 설치하시면 되구요.</description></item><item><title>폴더 복사하기</title><link>https://modu-print.com/posts/3389/</link><pubDate>Tue, 07 Sep 2021 09:45:00 +0900</pubDate><guid>https://modu-print.com/posts/3389/</guid><description>Go에서 파일의 복사도 그렇지만 폴더를 복사하는건 .. 일일이 폴더명 따져서 생성을 시키고 파일도 따로따로 복사해대고 하는걸 반복해야 하는 작업입니다.&#10;특정폴더를 다른 위치로 복사하고 싶을때 사용하시면 됩니다.&#10;Go package main import ( "fmt" "io" "io/ioutil" "os" "path/filepath" ) / *&#9;CopyFile / func CopyFile(src, dst string) (err error) { in, err := os.Open(src) if err != nil { return } defer in.Close() out, err := os.Create(dst) if err != nil { return } defer func() { if e := out.Close(); e != nil { err = e } }() , err = io.Copy(out, in) if err != nil { return } err = out.Sync() if err != nil { return } si, err := os.Stat(src) if err != nil { return } err = os.Chmod(dst, si.Mode()) if err != nil { return } return } / *&#9;CopyDir / func CopyDir(src string, dst string) (err error) { src = filepath.Clean(src) dst = filepath.Clean(dst) si, err := os.Stat(src) if err != nil { return err } if !si.IsDir() { return fmt.Errorf("source is not a directory") } , err = os.Stat(dst) if err != nil &amp;&amp; !os.IsNotExist(err) { return } if err == nil { return fmt.Errorf("destination already exists") } err = os.MkdirAll(dst, si.Mode()) if err != nil { return } entries, err := ioutil.ReadDir(src) if err != nil { return } for _, entry := range entries { srcPath := filepath.Join(src, entry.Name()) dstPath := filepath.Join(dst, entry.Name()) if entry.IsDir() { err = CopyDir(srcPath, dstPath) if err != nil { return } } else { // Skip symlinks. if entry.Mode()&amp;os.ModeSymlink != 0 { continue } err = CopyFile(srcPath, dstPath) if err != nil { return } } } return }</description></item><item><title>Go언어에서 ShellExcute, ShellExcuteEx 함수 사용하기</title><link>https://modu-print.com/posts/3866/</link><pubDate>Mon, 06 Sep 2021 13:19:00 +0900</pubDate><guid>https://modu-print.com/posts/3866/</guid><description>Go언어에 exec 패키지를 통해 exec.Command().Run 이나 Start등으로 외부 명령을 실행할 수 있으나 이 함수들의 단점은 CreateProcess 기반인데다 부가적인 옵션이 거의 존재하지 않습니다. 예를들면 Run 함수의 경우에는 실행시킨 명령이 종료되기 전까진 대기를 해야 하지만 콘솔 어플리케이션이 아닌 윈도 어플리케이션을 호출하는 경우 일반적으로 콘솔기준에선 바로 실행이 끝난것으로 넘어오기 때문에 .. 조금 맞지 않는 부분이 생기구요..&#10;예를들어 윈도 프로그래밍에선 ShellExcuteEx 를 사용한뒤에 WaitForSingleEvent 같은 함수로 해당 프로세스의 종료까지 대기가 가능하고 명령어를 open 이 아닌 runAs 같은걸 지정하면 관리자권한으로 실행등의 부가적인 효과를 얻을 수 있습니다.</description></item><item><title>현재 윈도가 32비트인지 64비트 인지 확인</title><link>https://modu-print.com/posts/3864/</link><pubDate>Mon, 06 Sep 2021 13:17:00 +0900</pubDate><guid>https://modu-print.com/posts/3864/</guid><description>Go언어는 개발하는 컴퓨터의 OS나 아키택처 상관 없이 다양한 플랫폼을 대상으로 실행파일 빌드가 가능합니다만. runtime 패키지의 GOARCH나 GOOS 등은 컴파일시에 해당 바이너리가 타겟으로 잡은 정보가 나올뿐 실제 현 시스템에 대한 정보를 대변하진 않습니다.&#10;예를들어 64비트 윈도에서 32비트 실행파일을 실행이 가능한데 runtime.GOARCH 정보를 보면 386 으로 뜨게 되지요..&#10;이런 경우 실제 OS의 CPU 아키텍처 정보를 얻으려면 시스템 정보를 얻어와야 합니다.</description></item><item><title>특정 경로의 총 파일 사이즈, 폴더 갯수, 파일 갯수 얻기</title><link>https://modu-print.com/posts/3375/</link><pubDate>Sat, 26 Jun 2021 00:01:00 +0900</pubDate><guid>https://modu-print.com/posts/3375/</guid><description>지정한 경로내의 총 파일 크기의 합과 폴더, 파일의 갯수를 리턴해주는 함수입니다.&#10;관리자 대시보드등에서 특정 경로의 사용용량등을 표시하는데 쓰시면 되겠습니다.&#10;Go / *&#9;dirUsage / func dirUsage(currentPath string, info os.FileInfo, fileCnt int64, dirCnt int64) int64 { size := info.Size() if !info.IsDir() { return size } dir, err := os.Open(currentPath) if err != nil { return 0 } defer dir.Close() fis, err := dir.Readdir(-1) if err != nil { return 0 } for _, fi := range fis { if fi.Name() == "." || fi.Name() == ".." { continue } if fi.IsDir() { dirCnt++ } else { fileCnt++ } size += dirUsage(currentPath+"/"+fi.Name(), fi, fileCnt, dirCnt) } return size } / *&#9;getDirectorySize / func getDirectorySize(path string) (int64, int64, int64, error) { info, err := os.Lstat(path) if err != nil { return 0, 0, 0, err } var dirCnt int64 var fileCnt int64 size := dirUsage(path, info, &amp;fileCnt, &amp;dirCnt) return size, fileCnt, dirCnt, nil }</description></item><item><title>Go언어로 윈도 서비스 어플리케이션 만들기</title><link>https://modu-print.com/posts/3881/</link><pubDate>Fri, 23 Apr 2021 13:32:00 +0900</pubDate><guid>https://modu-print.com/posts/3881/</guid><description>최근에는 MS의 Visual Studio도 기본적으로 무료로 사용가능하지만.. 무료버전으로는 서비스 어플리케이션은 개발할 수가 없습니다. ( 물론 Professional 버전 등에서 관련 리소스들을 복사해와서 꼼수로 개발환경을 구성가능하기도 하지만 ㅎㅎ )&#10;여튼 ..&#10;Go로도 윈도 서비스 어플리케이션 개발이 가능합니다.&#10;example command - golang.org/x/sys/windows/svc/example - Go Packages Example service program that beeps. 참고하시면 되겠습니다 ㅎ</description></item><item><title>파일복사 함수</title><link>https://modu-print.com/posts/3935/</link><pubDate>Fri, 09 Apr 2021 16:25:00 +0900</pubDate><guid>https://modu-print.com/posts/3935/</guid><description>기본적으로 파일을 이동시키거나 삭제하는 함수는 제공되고 있지만 복사의 경우 따로 구현을 해야 합니다. Go / * 파일 복사 함수 / func copyFile(srcFile string, destFile string) error { // 기존 파일이 있으면 삭제 if , err := os.Stat(destFile); os.IsNotExist(err) == false { os.Remove(destFile) } // from, err := os.Open(srcFile) if err != nil { return err } defer from.Close() to, err := os.OpenFile(destFile, os.O_RDWR|os.O_CREATE, 0666) if err != nil { return err } defer to.Close() , err = io.Copy(to, from) if err != nil { return err } return nil }</description></item><item><title>프로그램 실행경로를 실행파일 위치로 고정</title><link>https://modu-print.com/posts/3932/</link><pubDate>Fri, 09 Apr 2021 16:22:00 +0900</pubDate><guid>https://modu-print.com/posts/3932/</guid><description>간혹 프로그램을 어디서 실행했느냐 따라서 .. 상대경로로 지정된 코드들이 파일을 못찾는 경우가 생깁니다. 이럴경우 실행파일의 위치로 실행경로를 조정해주면 됩니다.&#10;Go&#9;if err != nil { return } exPath := filepath.Dir(ex) currDir, cdErr := os.Getwd() if cdErr != nil { return } if currDir != exPath { os.Chdir(exPath) }</description></item><item><title>올바른 이메일 주소, 알파벳, 숫자 체크(Regexp)</title><link>https://modu-print.com/posts/3930/</link><pubDate>Fri, 09 Apr 2021 16:21:00 +0900</pubDate><guid>https://modu-print.com/posts/3930/</guid><description>Goa-zA-Z0-9?(?:\.a-zA-Z0-9?)$") return er.MatchString(email) }&#10;/**&#10;알파뱃 , 숫자 체크 / func isAlphaNumString(str string) bool { match, _ := regexp.MatchString("^[a-zA-Z0-9$]+$", str) return match }" style=“color:#d8dee9ff;display:none” aria-label=“Copy” class=“code-block-pro-copy-button”&gt; package main import ( "fmt" "regexp" ) func main() { testMail := "example@example.com" if isValidEmail(testMail) { fmt.Println("올바른 이메일 주소") } else { fmt.Println("잘못된 이메일 주소") } } // 이메일 검사 func isValidEmail(email string) bool { er := regexp.MustCompile("^[a-zA-Z0-9.!#$%&amp;'+\/=?^_`{|}~-]+@a-zA-Z0-9?(?:\.a-zA-Z0-9?)$") return er.MatchString(email) } / * 알파뱃 , 숫자 체크 **/ func isAlphaNumString(str string) bool { match, _ := regexp.MatchString("^[a-zA-Z0-9$]+$", str) return match }</description></item><item><title>간단한 파일 다운로드(HTTP GET)</title><link>https://modu-print.com/posts/3927/</link><pubDate>Fri, 09 Apr 2021 16:20:00 +0900</pubDate><guid>https://modu-print.com/posts/3927/</guid><description>프로그래밍을 하다보면 HTTP GET방식으로 파일을 다운받아 저장해야할 일이 종종 있습니다. 그런떄 사용가능한 GET 방식의 간단한 파일 다운로드 예제입니다.&#10;Go func downloadFile(filepath string, url string) error { // Create the file out, err := os.Create(filepath) if err != nil { return err } defer out.Close() // Request 객체 생성 req, err := http.NewRequest("GET", url, nil) if err != nil { return err } //필요시 헤더 추가 가능 req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36") // Client객체에서 Request 실행 client := &amp;http.Client{} rep, err := client.Do(req) if err != nil { return err } defer func() { rep.Body.Close() }() // Write the body to file _, err = io.Copy(out, rep.Body) if err != nil { return err } return nil }</description></item><item><title>윈도 API를 이용한 wav 사운드 파일 재생</title><link>https://modu-print.com/posts/3911/</link><pubDate>Fri, 09 Apr 2021 16:11:00 +0900</pubDate><guid>https://modu-print.com/posts/3911/</guid><description>간단히 소리로 무언가를 알려야 할경우에 유용한 코드입니다. 구글링 중에 얻은 코드인지 깃헙 돌아다니다 발췌한 코드인지 기억이 가물가물해서 출처가 애매하네요 ;; &#10;Go package main import ( "syscall" "unsafe" ) const ( SND_SYNC uint = 0x0000 /* play synchronously (default) / SND_ASYNC uint = 0x0001 / play asynchronously / SND_NODEFAULT uint = 0x0002 / silence (!default) if sound not found / SND_MEMORY uint = 0x0004 / pszSound points to a memory file / SND_LOOP uint = 0x0008 / loop the sound until next sndPlaySound / SND_NOSTOP uint = 0x0010 / don't stop any currently playing sound / SND_NOWAIT uint = 0x00002000 / don't wait if the driver is busy / SND_ALIAS uint = 0x00010000 / name is a registry alias / SND_ALIAS_ID uint = 0x00110000 / alias is a predefined ID / SND_FILENAME uint = 0x00020000 / name is file name / SND_RESOURCE uint = 0x00040004 / name is resource name or atom / SND_PURGE uint = 0x0040 / purge non-static events for task / SND_APPLICATION uint = 0x0080 / look for application specific association / SND_SENTRY uint = 0x00080000 / Generate a SoundSentry event with this sound / SND_RING uint = 0x00100000 / Treat this as a "ring" from a communications app - don't duck me / SND_SYSTEM uint = 0x00200000 / Treat this as a system sound / SND_ALIAS_START uint = 0 / alias base */ ) var ( mmsystem = syscall.MustLoadDLL("winmm.dll") playSound = mmsystem.MustFindProc("PlaySound") sndPlaySoundA = mmsystem.MustFindProc("sndPlaySoundA") sndPlaySoundW = mmsystem.MustFindProc("sndPlaySoundW") ) // PlaySound play sound in Windows func PlaySound(sound string, hmod int, flags uint) { if playSound == nil { return } s16, := syscall.UTF16PtrFromString(sound) playSound.Call(uintptr(unsafe.Pointer(s16)), uintptr(hmod), uintptr(flags)) } // SndPlaySoundA play sound file in Windows func SndPlaySoundA(sound string, flags uint) { if sndPlaySoundA == nil { return } b := append([]byte(sound), 0) sndPlaySoundA.Call(uintptr(unsafe.Pointer(&amp;b[0])), uintptr(flags)) } // SndPlaySoundW play sound file in Windows func SndPlaySoundW(sound string, flags uint) { if SndPlaySoundW == nil { return } s16, := syscall.UTF16PtrFromString(sound) sndPlaySoundW.Call(uintptr(unsafe.Pointer(s16)), uintptr(flags)) }</description></item><item><title>현재 날짜, 시간 구하기</title><link>https://modu-print.com/posts/3909/</link><pubDate>Fri, 09 Apr 2021 16:10:00 +0900</pubDate><guid>https://modu-print.com/posts/3909/</guid><description>Go / * 현재 날짜 및 시간 문자열로 얻기 / func currDateTimeStr() string { t := time.Now() return fmt.Sprintf("%04d%02d%02d_%02d%02d%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()) } / *&#9;currDateTimeSplit / func currDateTimeSplit() (year string, month string, day string, hour string, min string, second string) { t := time.Now() sy := fmt.Sprintf("%04d", t.Year()) smon := fmt.Sprintf("%02d", t.Month()) sd := fmt.Sprintf("%02d", t.Day()) sh := fmt.Sprintf("%02d", t.Hour()) sm := fmt.Sprintf("%02d", t.Minute()) ss := fmt.Sprintf("%02d", t.Second()) return sy, smon, sd, sh, sm, ss }</description></item><item><title>CP949 &lt;-&gt; UTF-8 변환</title><link>https://modu-print.com/posts/3905/</link><pubDate>Fri, 09 Apr 2021 16:07:00 +0900</pubDate><guid>https://modu-print.com/posts/3905/</guid><description>Go언어는 기본적으로 UTF-8을 인코딩으로 사용합니다만. 윈도의 경우 기본적으로 CP949 또는 UTF-16입니다. 한글 윈도를 설치한 경우에는 많은 경우에 CP949가 기본 인코딩인 경우가 대부분이라 exec 패키지 등으로 콘솔 명령어를 실행하고 결과를 받아서 사용하는 등의 경우에 한글문자가 깨지는 문제를 겪을 수 있습니다.&#10;이때 사용할수 있는 인코딩 변환 코드입니다.&#10;Go import ( "golang.org/x/text/encoding/korean" "golang.org/x/text/transform" ) / * ansi string을 utf8로 변환 / func ansiToUni(src []byte) []byte { got, , := transform.String(korean.EUCKR.NewDecoder(), string(src)) return []byte(got) } func ansiToUniString(src string) string { got, , := transform.String(korean.EUCKR.NewDecoder(), src) return got } / *&#9;uniToAnsi / func uniToAnsi(src []byte) []byte { got, , := transform.String(korean.EUCKR.NewEncoder(), string(src)) return []byte(got) }</description></item><item><title>파일, 폴더 존재여부 체크</title><link>https://modu-print.com/posts/3902/</link><pubDate>Fri, 09 Apr 2021 16:05:00 +0900</pubDate><guid>https://modu-print.com/posts/3902/</guid><description>Go / *&#9;isExistFile / func isExistFile(fname string) bool { if _, err := os.Stat(fname); os.IsNotExist(err) { return false } return true } / *&#9;isExistFileWithSize / func isExistFileWithSize(fname string) bool { fi, err := os.Stat(fname) if os.IsNotExist(err) { return false } if fi.Size() &gt; 0 { return true } return false }</description></item><item><title>MS윈도 파일또는 폴더를 휴지통으로 버리기</title><link>https://modu-print.com/posts/3898/</link><pubDate>Fri, 09 Apr 2021 16:01:00 +0900</pubDate><guid>https://modu-print.com/posts/3898/</guid><description>윈도에서 프로그래밍을 하다보면 파일을 바로 삭제하는게 아닌 휴지통으로 이동시켜야 하는 경우가 생깁니다. os.Remove 같은 메소드를 이용하여 파일자체를 영구 삭제하는거야 매우 편하지만 ..&#10;사용자를 대상으로 배포할 프로그램을 만드는 경우에는 가능하면 사용자의 실수도 감안하여 바로 삭제하는게 아닌 휴지통으로 이동을 시켜야 할 경우가 생깁니다.&#10;이는 Go언어가 아닌 MFC나 Win32 API를 가지고 개발을 하더라도 결국 MS에서 제공하는 시스템 함수를 가지고서 다뤄야 하는 문제라 ..</description></item><item><title>TCP/IP 안쓰는 포트 얻기 - freeport</title><link>https://modu-print.com/posts/3895/</link><pubDate>Fri, 09 Apr 2021 16:00:00 +0900</pubDate><guid>https://modu-print.com/posts/3895/</guid><description>서버 프로그램을 만들다 보면 가변포트를 사용해야 할 경우가 있습니다. 이런경우 시스템에 사용하고 있지 않은 포트를 얻어야 할때가 있는데요, 그런경우 사용가능한 패키지 입니다.&#10;GitHub - phayes/freeport: Get a free and open tcp port that is ready to use Get a free and open tcp port that is ready to use. Contribute to phayes/freeport development by creating an account on GitHub. Bash go get github.com/phayes/freeport Go package main import "github.com/phayes/freeport" func main() { port, err := freeport.GetFreePort() if err != nil { log.Fatal(err) } // port is ready to listen on }</description></item><item><title>JSON to GO</title><link>https://modu-print.com/posts/3889/</link><pubDate>Fri, 09 Apr 2021 13:38:00 +0900</pubDate><guid>https://modu-print.com/posts/3889/</guid><description>Go로 JSON 데이터를 다루다 보면 .. map 을 이용해 Unmarshal 등을 해도 상관은 없지만. 이래저래 불편합니다. 그래서 보통은 구조체를 생성해서 처리를 합니다. 이때 JSON 구조가 단순하다면야 직접 struct 를 잡아서 작성하면 되지만 복잡한 구조의 JSON 데이터의 경우 구조체 만드는것도 여간 귀찮은 일이 아니지요..&#10;그럴때 사용하기 좋은 사이트가 있습니다.&#10;JSON-to-Go: Convert JSON to Go instantly This tool instantly converts JSON into a Go type definition. Paste a JSON structure on the left and the equivalent Go type will be generated to the right, which you can paste into your program. The script has to make some assumptions, so double-check the output! JSON { "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"] }, "GlossSee": "markup" } } } } } 위 JSON 데이터는 json.org 의 JSON Example 중 하나입니다. 이런 JSON 데이터를 입력하면.</description></item><item><title>XML to GO</title><link>https://modu-print.com/posts/3886/</link><pubDate>Fri, 09 Apr 2021 13:36:00 +0900</pubDate><guid>https://modu-print.com/posts/3886/</guid><description>JSON에 비해 XML의 경우 좀더 파싱이 복잡한 편이긴 합니다만. Go에서는 XML의 Marshal, Unmarshal도 지원을 하고 있습니다. 앞서 작성한 JSON to GO와 마찬가지로 XML의 경우도 구조체를 통해 처리하는 것이 여러모로 관리가 편합니다.&#10;xmltogo 이 사이트를 이용하시면 매우 편리하구요 ㅎㅎ&#10;XML &lt;breakfast_menu&gt; &lt;food&gt; &lt;name&gt;Belgian Waffles&lt;/name&gt; &lt;price&gt;$5.95&lt;/price&gt; &lt;description&gt;Two of our famous Belgian Waffles with plenty of real maple syrup&lt;/description&gt; &lt;calories&gt;650&lt;/calories&gt; &lt;/food&gt; &lt;food&gt; &lt;name&gt;Strawberry Belgian Waffles&lt;/name&gt; &lt;price&gt;$7.95&lt;/price&gt; &lt;description&gt;Light Belgian waffles covered with strawberries and whipped cream&lt;/description&gt; &lt;calories&gt;900&lt;/calories&gt; &lt;/food&gt; &lt;food&gt; &lt;name&gt;Berry-Berry Belgian Waffles&lt;/name&gt; &lt;price&gt;$8.95&lt;/price&gt; &lt;description&gt;Light Belgian waffles covered with an assortment of fresh berries and whipped cream&lt;/description&gt; &lt;calories&gt;900&lt;/calories&gt; &lt;/food&gt; &lt;food&gt; &lt;name&gt;French Toast&lt;/name&gt; &lt;price&gt;$4.50&lt;/price&gt; &lt;description&gt;Thick slices made from our homemade sourdough bread&lt;/description&gt; &lt;calories&gt;600&lt;/calories&gt; &lt;/food&gt; &lt;food&gt; &lt;name&gt;Homestyle Breakfast&lt;/name&gt; &lt;price&gt;$6.95&lt;/price&gt; &lt;description&gt;Two eggs, bacon or sausage, toast, and our ever-popular hash browns&lt;/description&gt; &lt;calories&gt;950&lt;/calories&gt; &lt;/food&gt; &lt;/breakfast_menu&gt; 이런 XML 을 입력하면. ( 출처 : www.w3schools.com/xml/simple.xml ) </description></item><item><title>파일 읽기, 파일을 한줄씩 읽기</title><link>https://modu-print.com/posts/3883/</link><pubDate>Fri, 09 Apr 2021 13:33:00 +0900</pubDate><guid>https://modu-print.com/posts/3883/</guid><description>Go if err != nil { log.Fatal(err) } fmt.Println( string(rbuf) )</description></item><item><title>윈도 API를 이용한 중복실행방지 ( feat. mutex )</title><link>https://modu-print.com/posts/3924/</link><pubDate>Thu, 08 Apr 2021 16:19:00 +0900</pubDate><guid>https://modu-print.com/posts/3924/</guid><description>윈도용 프로그램을 Go로 개발하다보면 중복실행을 원치 않을 경우가 있습니다. 이런때 윈도 API 의 뮤텍스 관련 함수를 이용하면 같은 프로그램의 중복실행을 방지할 수 있습니다.&#10;Bash go get github.com/rodolfoag/gow32 위 패키지 설치가 필요합니다.</description></item><item><title>외부 명령 실행하기( feat exec.Command )</title><link>https://modu-print.com/posts/3921/</link><pubDate>Thu, 08 Apr 2021 16:17:00 +0900</pubDate><guid>https://modu-print.com/posts/3921/</guid><description>프로그래밍 하다보면 .. command line 명령으로 외부 파일을 실행해야할때가 있습니다. 그런때 exe.Command 를 사용하는데요 약간의 추가적인 부분 몇가지를 적어봅니다.&#10;Go / *&#9;execCommandStart / func execCommandStart(name string, arg …string) error { cmd := exec.Command(name, arg…) err := cmd.Start() return err } / *&#9;execCommandRun / func execCommandRun(name string, arg …string) error { cmd := exec.Command(name, arg…) err := cmd.Run() return err } / *&#9;execCommandOutput **/ func execCommandOutput(name string, arg …string) (string, error) { cmd := exec.Command(name, arg…) output, err := cmd.CombinedOutput() return string(output), err }</description></item><item><title>주사위 함수 (Dice, Random)</title><link>https://modu-print.com/posts/3918/</link><pubDate>Thu, 08 Apr 2021 16:15:00 +0900</pubDate><guid>https://modu-print.com/posts/3918/</guid><description>구 CircleMud 현 tbaMud의 C로 작성된 dice 함수를 Go언어 코드로 작성한 함수입니다. tbaMud 라이선스는 아래 링크를 참고 바랍니다.&#10;LICENSE.md 과거에는 GPL 비슷한 라이선스로 봤었는데.. 일부 소스를 타 언어로 포팅한다던지 하는 경우에 오픈소스여야 한다던가 하는 조항이 어디갔는지를 모르겠네요 ;; &#10;여튼 참고만 하시고 상용 프로젝트나 라이선스에 민감한 케이스에는 사용을 자제하시기 바랍니다.</description></item><item><title>윈도 서비스 컨트롤</title><link>https://modu-print.com/posts/3914/</link><pubDate>Thu, 08 Apr 2021 16:13:00 +0900</pubDate><guid>https://modu-print.com/posts/3914/</guid><description>윈도의 실행중인 여러 서비스를 중지시키거나 실행시키거나 하는 .. 서비스를 컨트롤 하는 함수입니다.&#10;모두의 프린터를 만들면서 사용한 코드입니다.&#10;Bash go get golang.org/x/sys/windows/svc go get golang.org/x/sys/windows/svc/mgr 이 두놈이 필요하구요 go get .. 고고</description></item><item><title>실행파일명으로 윈도 프로세스 찾기</title><link>https://modu-print.com/posts/3372/</link><pubDate>Thu, 08 Apr 2021 00:00:00 +0900</pubDate><guid>https://modu-print.com/posts/3372/</guid><description>구글링중 찾은 코드를 조금 손봤습니다. 프로세스명(실행파일명)으로 프로세스가 있는지를 체크하는 함수와 프로세스를 죽이는 함수인데.. os.FindProcess 로 Kill 하는게 윈도서도 제대로 될진 모르겠네요 ㅎㅎ&#10;findProcessByName 까진 정상동작 확인했습니다.&#10;Go package main import ( "os" "strings" "syscall" "unsafe" "golang.org/x/sys/windows" ) const TH32CS_SNAPPROCESS = 0x00000002 type WindowsProcess struct { ProcessID int ParentProcessID int Exe string } / *&#9;processes / func processes() ([]WindowsProcess, error) { handle, err := windows.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) if err != nil { return nil, err } defer windows.CloseHandle(handle) var entry windows.ProcessEntry32 entry.Size = uint32(unsafe.Sizeof(entry)) &lt;em&gt;// get the first process&lt;/em&gt; err = windows.Process32First(handle, &amp;entry) if err != nil { return nil, err } results := make([]WindowsProcess, 0, 50) for { results = append(results, newWindowsProcess(&amp;entry)) err = windows.Process32Next(handle, &amp;entry) if err != nil { &lt;em&gt;// windows sends ERROR_NO_MORE_FILES on last process&lt;/em&gt; if err == syscall.ERROR_NO_MORE_FILES { return results, nil } return nil, err } } } / *&#9;findProcessByName / func findProcessByName(name string) WindowsProcess { processes, perr := processes() if perr != nil { return nil } for _, p := range processes { if strings.ToLower(p.Exe) == strings.ToLower(name) { return &amp;p } } return nil } /** newWindowsProcess / func newWindowsProcess(e *windows.ProcessEntry32) WindowsProcess { &lt;em&gt;// Find when the string ends for decoding&lt;/em&gt; end := 0 for { if e.ExeFile[end] == 0 { break } end++ } return WindowsProcess{ ProcessID: int(e.ProcessID), ParentProcessID: int(e.ParentProcessID), Exe: syscall.UTF16ToString(e.ExeFile[:end]), } } / *&#9;killProcess **/ func killProcess(name string) { pn := findProcessByName(name) if pn != nil { p, perr := os.FindProcess(pn.ProcessID) if perr == nil { p.Kill() } } }</description></item><item><title>윈도API, ShellExcute를 이용한 관리자권한으로 명령어 실행</title><link>https://modu-print.com/posts/3391/</link><pubDate>Sun, 14 Mar 2021 09:47:00 +0900</pubDate><guid>https://modu-print.com/posts/3391/</guid><description>Go import ( "golang.org/x/sys/windows" "path/filepath" ) / *&#9;runAsCommand / func runAsCommand(exe string, runArg string, showCmd int32) error { verb := "runas" cwd := filepath.Dir(exe) verbPtr, := syscall.UTF16PtrFromString(verb) exePtr, := syscall.UTF16PtrFromString(exe) cwdPtr, := syscall.UTF16PtrFromString(cwd) argPtr, := syscall.UTF16PtrFromString(runArg) err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) if err != nil { return err } return nil }</description></item><item><title>Go로 웹크롤러 만들기 #2</title><link>https://modu-print.com/posts/2041/</link><pubDate>Tue, 24 Nov 2020 16:13:00 +0900</pubDate><guid>https://modu-print.com/posts/2041/</guid><description>1편에 이어서 진행해 보겠습니다. 우선 적당한 위치에 폴더하나를 만드시구요.  저는 GOWEB이라고 만들었습니다.&#10;생성한 폴더를 선택후 우클릭 -&gt; Code(으)로 열기하여 VSCode로 프로젝트를 엽니다.&#10;main.go 파일을 하나 생성 하십시요.&#10;package main func main(){ }</description></item><item><title>Go로 웹크롤러 만들기 #1</title><link>https://modu-print.com/posts/2036/</link><pubDate>Tue, 17 Nov 2020 13:20:00 +0900</pubDate><guid>https://modu-print.com/posts/2036/</guid><description>원래 유튭 영상으로만 어떻게 해보려고 몇 번 녹화도 해보고 라이브도 진행해보고 했으나.. 영상보단 글로써 전달하는 게 효율적이란 생각이 들어서 .. 영상 대본 등을 이용해서 먼저 글을 올립니다. 영상은 포스트 작성후 이 글의 내용에 대해 간단히 설명하는 정도로 넘어가도록 하겠습니다.&#10;유튜브 피로곰TV채널의 구독자와 시청시간이 충족돼서 광고도 달수 있게 되고 커뮤니티 기능도 사용 가능해지면서 전부터 생각하던 대리코딩과 관련한 글을 작성했고 한분께서 크롤링과 관련된 문의를 하셨습니다. 솔직히 별로 하고 싶지 않은 류의 프로그램이라 대리코딩 콘텐츠를 할까 말까 고민한 가장 큰 이유 중 하나가 이놈 때문인데 그래도 요청이 왔으니 진행을 해보겠습니다.</description></item><item><title>프로그램 아이콘을 변경하자GO!</title><link>https://modu-print.com/posts/2032/</link><pubDate>Sat, 30 May 2020 23:09:00 +0900</pubDate><guid>https://modu-print.com/posts/2032/</guid><description>사용된 예제 코드는 아래 링크에서 받으십시요.&#10;예제코드 다운로드&#10;1일1GO 10번째 시간에서 작업한 프로젝트 파일은&#10;위 압축파일을 다운로드 받으시면 됩니다.&#10;추가된 파일은 &#10;baseapp.png&#10;baseapp_icon.ico</description></item><item><title>윈도 트레이 메뉴 추가</title><link>https://modu-print.com/posts/1874/</link><pubDate>Sun, 17 May 2020 01:24:00 +0900</pubDate><guid>https://modu-print.com/posts/1874/</guid><description>9번째 시간 윈도 트레이 메뉴(아이콘)을 추가하는&#10;방법에 대한 영상입니다.&#10;사용된 패키지의 github 주소 입니다&#10;GitHub - tadvi/systray: Go package for Windows Systray icon, menu and notifications Go package for Windows Systray icon, menu and notifications - GitHub - tadvi/systray: Go package for Windows Systray icon, menu and notifications go get github.com/tadvi/systray 콘솔에서 위 명령으로 시스템에 추가 가능합니다.</description></item><item><title>웹페이지 생성,호출</title><link>https://modu-print.com/posts/1870/</link><pubDate>Sat, 09 May 2020 04:47:00 +0900</pubDate><guid>https://modu-print.com/posts/1870/</guid><description>아래는 예제로 사용된 코드들 입니다. 같은 파일명으로 파일들 생성 하셔서 복붙 하시면 되겠습니다.&#10;main.go package main import ( "fmt" "github.com/phayes/freeport" ) var ( gWebServerPort int ) func main() { port, portErr := freeport.GetFreePort() if portErr != nil { fmt.Println(portErr.Error()) return } gWebServerPort = port webServ("127.0.0.1", gWebServerPort) }</description></item><item><title>Go 프로그래밍 환경구성</title><link>https://modu-print.com/posts/1807/</link><pubDate>Fri, 24 Apr 2020 23:36:00 +0900</pubDate><guid>https://modu-print.com/posts/1807/</guid><description>오래전부터 프로그래밍에 관심을 가지는 분들에게 강좌 같은 걸 해볼까 하고 고민을 하긴 했습니다만. 유튜브나 블로그등에 좋은 강좌들은 꽤 많은지라 원론적인 부분 빼고 2~3년 전부터 매우 애정하고 모두의 프린터, 모두의 자막, 모두의 플러그 등을 비롯 최근에 만든 많은 프로그램들의 개발 언어인 Go라는 언어를 가지고 특정 프로그램을 만들기 위한것 보다는 함수 하나, 기능 하나들 위주로 "이러이러한 기능을 만들고 싶으면 요래 하면 됩니다!" 그냥 따라 하거나 복붙 하거나 하면 되는 그 과정에서 필요한 지식을 전달하고 가능하면 C/C++, 자바 등의 다른 언어에 대한 이야기도 풀어 갈 수 있는 영상을 작업해보려 합니다.</description></item><item><title>Go 개발 환경 설정</title><link>https://modu-print.com/posts/1685/</link><pubDate>Fri, 06 Sep 2019 09:20:00 +0900</pubDate><guid>https://modu-print.com/posts/1685/</guid><description>이런저런 강좌 시작하기 합서 제가 애정해 마지 않는 Go 라는 언어의 개발환경 설정에 대한 글을 작성해 봅니다.&#10;우선 Go 를 설치 하셔야 겠지요 일단 윈도 사용자를 기준으로 설명합니다. The Go Programming Language Go is an open source programming language that makes it simple to build secure, scalable systems. 저 페이지 가시면 첫 화면에 큼지막 하게 Download Go 라고 있습니다. 클릭!! 고고고!</description></item></channel></rss>