반응형

회사 동료 PC에서 파일명을 일괄 변경시켜줘야 하는 일이 발생했습니다. 예를들면 앞부분에 특정 구문을 붙인다던지, 뒷부분에 날짜를 일괄 붙인다는지 하는 식으로 말이죠. 검색해보면 여러가지 툴/방법이 있긴 합니다만 오랫만에 직접 프로그램을 짜서 도움을 줘볼까 합니다. 그래서 이번엔 쉽게 실행파일 생성이 가능한 Go언어를 이용해서 만들어보기로 했습니다. Java나 C#은 가상머신 세팅에서 약간의 까다로움이 발생하거나 괜히 덩치만 커질 수도 있었고, Python은 친구 PC에 Python을 굳이(개발자도 아닌데) 깔아야 하는 번거로움이 있고, Javascript는...음....?? 

 

Go언어 설치나 세팅 부분은 다른 글들에도 많으니까 패스하도록 하겠습니다.

 

src 폴더 하위에 신규 폴더하나를 생성하고, 파일명은 test.go로 하여 아래와 같이 작성하였습니다.

 

<test.go>

 

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func main() {
	// fmt.Println("Hello, World!")
	targetDir := "./temp"
	files, err := ioutil.ReadDir(targetDir)
	if err != nil {
		fmt.Println(err)
		return
	}
	for _, file := range files {
		
		fmt.Println(file.Name())  // 파일명 확인
		file_name := file.Name()  // 단순파일명
		file_fullname := targetDir + "/" + file_name  // 전체 파일명

		new_name := strings.Replace(file_name, "CMM_ROOM_", "2022", 1) //원본 문자열, 바꿀문자열, 신규문자열, 바꿀횟수
		new_fullname := targetDir + "/" + new_name  // 신규 파일명(경로포함)

		os.Rename(file_fullname, new_fullname) // 변경
	}
}

 

테스트를 위해 현재 프로젝트 폴더 하위에 temp폴더를 생성하고, 내부에 몇개의 파일들을 생성해보도록 하겠습니다.

 

이 프로그램의 목적은 파일명의 "CMM_ROOM_" 부분을 "2022"로 일괄 변환하는 것입니다. 프로그램을 실행해보면..

go run test.go

잘 변환되네요..

이제 이걸 배포파일로 만들어주면 오늘의 작업 끝~~

go buil test.go

반응형
반응형

 

Go언어로 다른 프로그램을 실행시키는 방법을 알아보겠습니다. 이번에도 역시 webview로 GUI를 구성하고, 버튼이 클릭되면 whale 브라우저를 실행하도록 해보겠습니다.

기존에 Webview가 설치되어있다면 다른 라이브러리 설치는 필요 없습니다. 단 os.exec 라이브러리를 사용하므로 임포트..정도는 필요합니다.

 

<main.go>

package main

import (
	"os/exec"

	"github.com/webview/webview"
)

func main() {
	w := webview.New(true)
	defer w.Destroy()
	w.SetSize(600, 200, webview.HintNone)
	// Create a GoLang function callable from JS
	w.Bind("hello", func() string { return "World!" })
	w.Bind("gorun", gorun)

	// Create UI with data URI
	w.Navigate(`data:text/html,
	 <!doctype html>
	 <html>
		<head><title>Hello</title></head>
		<body><h1>Run Servers!</h1></body>
		<button onclick="gorun();">RUN</button>
		<script> hello().then((x) => { console.log(x) }) </script>
	 </html>`)

	w.Run()
}

func gorun() {
	cmd := exec.Command("C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe", "www.google.com")
	cmd.Start()
}

 

빨리 Gin 프로그램을 붙여 돌려봐야겠네요..^^

반응형
반응형

이번에는 Webview 라이브러리를 사용하면서 HTML 파일을 별도로 분리하는 방법을 알아보겠습니다. 그리고, 좀더 보기좋은 GUI 구성을 위해 부트스트랩도 함께 적용하도록 하겠습니다. 사실 이부분은...CSS 파일을 별도로 인식시켰으면 좋겠지만, 아직까지 별도의 CSS파일을 적용시키는 것은 안되는 것 같습니다. 

 

1. 라이브러리 설치

라이브러리 설치는 이전 강좌를 참고하세요.

 

2. main.go 파일 작성

main.go 파일에 전체 프로그램 구동을 구현합니다. 아울러, 버튼을 클릭했을 때 동작할 함수(go_hello)를 작성하고, 바인딩해줍니다. Webview라이브러리를 활용하면, go에서 javascript를 실행할 수도 있고, html파일(javascript 포함)에서 go언어를 실행할 수도 있습니다. 그러나 프로그램 가독성을 위해, Bind 한줄이 더 들어가더라도, 함수구현은 go에서 하도록 하겠습니다.

package main

import (
	"fmt"
	"os"

	"github.com/webview/webview"
)

var w webview.WebView

func main() {
	w = webview.New(true)
	defer w.Destroy()
	w.SetSize(600, 600, webview.HintNone) // Create a GoLang function callable from JS
	w.Bind("go_hello", go_hello)	// Go_hello 함수 구현과 html에서 호출하는 go_hello를 Bind해줍니다. 

	// Create UI with data URI
	dir, _ := os.Getwd()
	fmt.Println(dir)
	w.Navigate("file:" + dir + "/hi.html")

	w.Run()
}

// 함수 실행 시, javascript로 팝업 알람을 실행해서 데이터를 보여줍니다.
// HTML문서에서 보여주는 부분만큼은...javascript로..ㅠㅠ
func go_hello() {
	name := "You"
	w.Eval(`alert("Hello` + name + `");`)
}

데이터를 처리하는 것은 go 함수구현에서 할 수 있지만, 마지막으로 데이터를 HTML로 보내서 보여주는 부분은 Javascript로 할 수밖에 없겠네요..^^;;

 

3. hi.html

HTML로 뷰를 구현합니다. 서두에서 말했듯이 CSS 적용이 힘든 관계로 Bootstrap을 CDN으로 불러와 적용시키겠습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

    <title>My App</title>
</head>
<body>
    <!--Header Section-->
    <div class="box-padding-big">
      <nav class="navbar navbar-expand-sm navbar-dark bg-dark">
        <div class="collapse navbar-collapse">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
              <a class="nav-link" href="#" id=navbardrop" data-toggle="dropdown">File</a>
              <div class="dropdown-menu">
              <a class="dropdown-item" href="#" onclick="go_hello()">Sub1</a>
              <a class="dropdown-item" href="#">Sub2</a>
              <a class="dropdown-item" href="#">Sub3</a>
              </div>
            </li>
            <li class="hav-item">
            	<a class="nav-link" href="#">Edit</a>
            </li>
            <li class="hav-item">
            	<a class="nav-link" href="#">View</a>
            </li>
            <li class="hav-item">
            	<a class="nav-link" href="#">Info</a>
            </li>
          </ul>
        </div>
      </nav>
    </div>

  <!--Main Section-->
  <div style="margin: 20px;">
  	<div style="font-size: 36px; color:chartreuse;font-weight:700">
      <div>GO-Webview HTML View Test <br/>
      with Bootstrap
      </div>
    </div>
    <p class="text-primary" style="margin-top:20px;">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eget magna eros. Cras sit amet nulla dignissim, pretium justo sit amet, vulputate orci. Curabitur in aliquam lorem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Morbi quis pulvinar nunc, sed posuere enim. In hac habitasse platea dictumst. Ut sodales augue eu elit bibendum, ut malesuada felis auctor. Sed mattis ipsum malesuada sem feugiat ultricies. Fusce ultrices vel est id pretium. Sed vel congue augue, non tincidunt tellus. Vivamus facilisis mollis tellus ac vulputate. 
    </p>
  </div>
</body>
</html>

 

4. 결과

아래 명령으로 결과를 확인합니다.

go run main.go

File - Sub1을 클릭하면...

알람 팝업이 잘 나옵니다.

 

이상으로 webview를 이용하여 html 파일과 bootstrap을 적용하는 방법을 알아봤습니다. 너무 쉽게 구현이 가능한데, 성능은 어느정도일지, 어떤 점이 부족할지 계속 알아봐야겠습니다.

 

~~~끝~~~

반응형
반응형

Go언어 GUI 라이브러리 중 Webview를 사용해서 데스크탑 앱을 만들어보도록 하겠습니다. Webview는 HTML로 레이아웃을 구성할 수 있어서 간단한 앱은 쉽게 만들 수 있습니다.

 

1. 라이브러리 설치

이번엔 리눅스환경에서(우분투 20.04) 라이브러리를 설치하겠습니다. 

sudo apt-get install libgtk-3-dev
sudo apt-get install libwebkit2gtk-4.0-dev

go get github.com/webview/webview

2. Sample Project

다음으로 간단히 main.go 파일을 생성하고, 아래와 같이 작성해줍니다.

package main

import "github.com/webview/webview"

func main() {
	w := webview.New(true)
	defer w.Destroy()
	w.SetSize(600, 200, webview.HintNone) // Create a GoLang function callable from JS
	w.Bind("hello", func() string { return "World!" })

	// Create UI with data URI
	w.Navigate(`data:text/html,
	 <!doctype html>
	 <html>
	  <head><title>Hello</title></head>
	  <body><h1>Hello, world!</h1></body>
	  <script> hello().then((x) => { console.log(x) }) </script>
	 </html>`)

	w.Run()
}

 

3. 실행

터미널에서 아래와 같이 명령하면..

go run main.go

이쁜 앱이 나타났습니다. 라이브러리만 설치하면 프로그램 작성은 정말 쉽게 할 수 있네요.

 

이상으로  Golang에서 Webview 라이브러리를 이용한 GUI개발을 알아봤습니다. 

다음번엔 HTML 파일을 분리하여 작성하는 방법을 알아보겠습니다.

 

~~~끝~~~

반응형
반응형

오늘은 웹 크롤링에 대해 알아보겠습니다.

go언어에서의 웹 크롤링에도 selenium과 chrome webdvier를 사용하는 방법이 있지만, selenium 개발하신 분이 현재는 관리를 중단한 상태라고 합니다. 대신 chromedp를 주로 사용한다고 합니다. 간략하게 chromedp를 알아보겠습니다.

 

우선 설치는 일반적인 go 라이브러리들과 마찬가지로 go get 명령으로 설치합니다. (깃헙링크)

go get -u github.com/chromedp/chromedp

그리고 예제는 여기링크로 가면 여러가지를 확인할 수 있습니다만, 천천히 살펴보시고

주요 method에 대한 예시로 아래 코드를 남겨놓겠습니다. (아래 코드는 실행되지는 않습니다. 추후 간단한 실행가능 예시로 업데이트 하겠습니다.)

 
package main

import (
	"context"
	"fmt"
	_ "log"
	"time"

	"github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/chromedp"
)

func main() {

	// chrome 실행 옵션 설정
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.DisableGPU,		
		chromedp.Flag("headless", false),	//headless를 false로 하면 브라우저가 뜨고, true로 하면 브라우저가 뜨지않는 headless 모드로 실행됨. 기본값은 true.
	)

	contextVar, cancelFunc := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancelFunc()

	contextVar, cancelFunc = chromedp.NewContext(contextVar)
	defer cancelFunc()

	// setting 필요 없이 headless 모드로 실행할 경우 아래의 코드로 대체 가능
	// contextVar, cancelFunc := chromedp.NewContext(
	// 	context.Background(),
	// 	chromedp.WithLogf(log.Printf),
	// )
	//defer cancelFunc()

	contextVar, cancelFunc = context.WithTimeout(contextVar, 50*time.Second)	// timeout 값을 설정 
	defer cancelFunc()

	var strVar string
	err := chromedp.Run(contextVar,

		chromedp.Navigate(`https://www.google.com/`),	// 시작 URL
		chromedp.WaitVisible(`body`),		//body 요소를 모두 불러들일 때까지 대기
		chromedp.InnerHTML(`pre`, &strVar),	// pre 태그의 내부 텍스트를 strVar변수에 입력
        	chromedp.OuterHTML(`div.srch_employees__list`, &strVar),	// 태크와 그 내부 텍스트를 함께 strVar변수에 입력
		chromedp.Click(`.employees-open`, chromedp.NodeVisible),	// .employees-open 클래스의 요소를 클릭
		chromedp.Sleep(10*time.Second),		//10초간 대기
		chromedp.SetAttributeValue(`input#empSearchKeyWord`, "value", "홍길동", chromedp.NodeVisible),	//input의 value에 '홍길동'을 입력 
		chromedp.SetAttributes(`input#empSearchKeyWord`, map[string]string{"value": "12345678"}, chromedp.NodeVisible), //input에 value 속성을 추가하고 값을 대입함 
		chromedp.SendKeys(`input#empSearchKeyWord`, "a"),	//키 입력
		chromedp.Evaluate(`window.open('www.naver.com')`, &strVar),	//javascript 실행
		chromedp.Value(`div#executiveStatusPop > div.dialog__contents > div.srch_employees > div.srch_employees__container > div.employees__srch > div._fr > div.board-search > input#empSearchKeyWord label`, &strVar),	// 해당 요소의 텍스트값을 취하여 strVar변수에 대입 
	)
	if err != nil {
		panic(err)
	}
}

 

그럼 이만~~

 

 
 
 
반응형
반응형

Fyne tutorial에 있는 timer 예제입니다.

 

1. main.go

package main

import (
	"time"

	"fyne.io/fyne/app"
	"fyne.io/fyne/widget"
)

func showTime(clock *widget.Label) {
	formatted := time.Now().Format("03:04:05")	//현재시각을 포멧에 따라 출력한다.
	clock.SetText(formatted)
}

func main() {
	a := app.New()
	w := a.NewWindow("Clock")

	clock := widget.NewLabel("")
	showTime(clock)

	w.SetContent(clock)
	go func() {
		t := time.NewTicker(time.Second) //매 초마다 메시지(시간)를 전송하는 채널 t생성 

		for range t.C {			//채널 C로 time값을 받아 순서대로 처리한다. 
			showTime(clock)		//매 초마다 시간을 출력한다. 
		}
	}()

	w.ShowAndRun()	//앱을 보여주고 실행한다. 
}
 

 

<결과>

 

 

~~끝~~

 
반응형
반응형

1. icon.png 이미지 파일을 준비합니다.

 

2. fyne 패키징 툴을 다운받습니다.

go get fyne.io/fyne/cmd/fyne

3. icon.png파일을 실행파일의 이미지로 패키징합니다.

fyne package -icon icon.png

 

 

반응형
반응형

Fyne를 이용해 GUI를 만들던 중 한글 출력이 안된다는 것을 뒤늦게 알게 되었네요.(아래 화면 참조). 오늘은 한글 설정하는 방법에 대해 알아보겠습니다. 샘플로 간단한 메모장 앱을 만들어보겠습니다.

 

 

1. main.go

위 샘플로 만든 앱의 코드는 아래와 같습니다.

package main

import (
	"fmt"
	"image/color"
	_ "unicode/utf8"

	"fyne.io/fyne"
	"fyne.io/fyne/app"
	"fyne.io/fyne/canvas"
	"fyne.io/fyne/layout"
	"fyne.io/fyne/theme"
	"fyne.io/fyne/widget"
)

func main() {
	f := app.New()
	//f.Settings().SetTheme(theme.LightTheme())
	f.Settings().SetTheme(theme.DarkTheme())
	w := f.NewWindow("")

	//상단에 넣을 위젯 및 레이아웃 - NewFormLayout
	qry := widget.NewEntry()
	btn_go := widget.NewButton("New Memo", New_btn)

	text := canvas.NewText("Text Object", color.White)
	text.Alignment = fyne.TextAlignTrailing
	text.TextStyle = fyne.TextStyle{Italic: true}

	ret := fyne.NewContainerWithLayout(layout.NewFormLayout())
	ret.AddObject(btn_go)
	ret.AddObject(qry)

	//하단에 넣을 위젯 및 전체 레이아웃 구성 - NewBorderLayout
	label2 := widget.NewLabel("Simple Memo")
	labox2 := fyne.NewContainerWithLayout(layout.NewCenterLayout(), label2)

	b1 := widget.NewButton("Go1", func() { fmt.Println("Go1 Button") })
	b1.ExtendBaseWidget(b1)

	b2 := widget.NewButton("Go2", func() { fmt.Println("Go2 Button") })
	b2.ExtendBaseWidget(b2)

	out_entry := widget.NewMultiLineEntry()
	out_entry.SetPlaceHolder("결과...")
	out_entry.ExtendBaseWidget(out_entry)

	frm := fyne.NewContainerWithLayout(layout.NewBorderLayout(ret, labox2, nil, nil)) //상, 하, 좌(없음), 우(없음)
	frm.AddObject(ret)                                                                //상단
	frm.AddObject(labox2)                                                             //하단
	frm.AddObject(out_entry)                                                          //좌-우가 없으므로 5번째에(center) 추가됨

	w.SetContent(frm)
	w.Resize(fyne.Size{Height: 640, Width: 480})
	w.ShowAndRun()

}

2. 한글 폰트파일 다운로드

네이버에서 '나눔고딕 다운' 으로 검색하면 무료로 다운받을 수 있는 폰트 링크들이 나타납니다.

 

 

 

기본이 되는 폰트를 다운받아서 현재의 프로젝트 폴더에 위치시킵니다.

 

 

 

3. IDELite 환경설정

다음으로 환경설정에 변수를 추가해주도록 하겠습니다. Tools -> Edit current environment 메뉴로 가서..

 

 

FYNE_FONT=NanumGothic.ttf 라고 한줄을 추가해 넣습니다.

 

 

 

비교적 간단하네요. 이렇게 설정하고 실행해봅시다.

 

 

네,,,잘~ 나옵니다.

그럼 모두 건승하세요~

 

~~끝~~

반응형

+ Recent posts