m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

golangでtemplate(html)の確認

ページを表示する際はテンプレートを使用する

標準では"text/template"と"html/template"が存在する
※他にもあるかもしれないけどあとでやる

シンプルなテンプレート

構造
$ tree
.
├── main.go
└── templates
    └── index.tpl

$
templates/index.tpl
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>golang template test</title>
</head>
<body>
    <h1>Golang Template Sample</h1>
    <p>Title --[{{.Title}}]</p>
    <p>Message--[{{.Message}}] </p>
    <div>
        <h3>Items</h3>
        {{range .List}}
        <p>{{.}}</p>
        {{end}}
    </div>
    <div>
        Link: {{.Link}}
    </div>
</body>
</html>

※テンプレートは中括弧("{}")で挟むようです

main.go
package main

import (
	"fmt"
	"net/http"
	"html/template"
	"time"
)

func main(){
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(time.Now().Format("2006/01/02 15:04:05") + " " + r.URL.Path)

		// テンプレート用のファイルを読み込む
		tpl, err1 := template.ParseFiles("templates/index.tpl")
		if err1 != nil {
			panic(err1)
		}

		// テンプレートを出力
		err2 := tpl.Execute(w, struct {
			Title string
			Message string
			List []string
			Link string
		}{
			Title: "Hello",
			Message: "World",
			List: []string{
				"Item1",
				"Item2",
				"Item3",
			},
			Link: "<a href=\"/\">hoge</a>",
		})
		if err2 != nil {
			panic(err2)
		}

	})
	http.ListenAndServe(":9001", nil)
}
ページをひらくとこうなる

f:id:m_shige1979:20160126223113p:plain

一部のデータを加工する

templates/index.tpl
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>golang template test</title>
</head>
<body>
	<h1>Golang Template Sample</h1>
	<p>Title --[{{.Title}}]</p>
	<p>Message--[{{.Message}}] </p>
	<div>
		<h3>Items</h3>
		{{range .List}}
		<p>{{.}}</p>
		{{end}}
	</div>
	<div>
		Link: {{.Link | safe}}
	</div>
	<div>
        Link: {{.Link | lock}}
    </div>
</body>
</html>
main.go
package main

import (
	"fmt"
	"net/http"
	"html/template"
	"time"
)

func main(){
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(time.Now().Format("2006/01/02 15:04:05") + " " + r.URL.Path)

		// 独自関数でエスケープを解除
		funcMap := template.FuncMap{
			"safe": func(text string) template.HTML { return template.HTML(text) },
			"lock": func(text string) string { return "@@[" + text + "]@@" },
		}

		// テンプレート用のファイルを読み込む
		tpl, _:= template.New("index.tpl").Funcs(funcMap).ParseFiles("templates/index.tpl")

		// テンプレートを出力
		err2 := tpl.Execute(w, struct {
			Title string
			Message string
			List []string
			Link string
		}{
			Title: "Hello",
			Message: "World",
			List: []string{
				"Item1",
				"Item2",
				"Item3",
			},
			Link: "<a href=\"/\">hoge</a>",
		})
		if err2 != nil {
			panic(err2)
		}

	})
	http.ListenAndServe(":9001", nil)
}
結果

f:id:m_shige1979:20160126225319p:plain

複数のテンプレートをファイルを使用する

構成
.
├── main.go
└── templates
    ├── base.tpl
    └── contents.tpl
templates/base.tpl
{{ define "base" }}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>golang template test</title>
</head>
<body>
    <h1>Golang Template Sample</h1>
    <p>Title --[{{.Title}}]</p>
    <p>Message--[{{.Message}}] </p>
    <div>
        {{ template "contents" . }}
    </div>
</body>
</html>
{{ end }}
templates/contents.tpl
{{ define "contents" }}
    <div>
        <h3>Items</h3>
        {{range .List}}
        <p>{{.}}</p>
        {{end}}
    </div>
    <div>
        Link: {{.Link | safe}}
    </div>
    <div>
        Link: {{.Link | lock}}
    </div>
{{ end }}
main.go
package main

import (
	"fmt"
	"net/http"
	"html/template"
	"time"
)

func main(){
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(time.Now().Format("2006/01/02 15:04:05") + " " + r.URL.Path)

		// 独自関数でエスケープを解除
		funcMap := template.FuncMap{
			"safe": func(text string) template.HTML { return template.HTML(text) },
			"lock": func(text string) string { return "@@[" + text + "]@@" },
		}

		// テンプレート用のファイルを読み込む
		tpl := template.Must(template.New("hoge").Funcs(funcMap).ParseFiles("templates/base.tpl", "templates/contents.tpl"))

		// テンプレートを出力
		err2 := tpl.ExecuteTemplate(w, "base", struct {
			Title string
			Message string
			List []string
			Link string
		}{
			Title: "Hello",
			Message: "World",
			List: []string{
				"Item1",
				"Item2",
				"Item3",
			},
			Link: "<a href=\"/\">hoge</a>",
		})
		if err2 != nil {
			panic(err2)
		}

	})
	http.ListenAndServe(":9001", nil)
}

頭パンクしそう(´・ω・`)

所感

やり方自体はパターンがあるからそのうち理解出来ていくと思うけどgo言語の書き方に慣れていないことや日本語のマニュアルがないのかエラーの意味をうまく理解できていないことがある。
いろいろ参考になりそうなソースがネットで検索したら出てくるので参考にしながらやっていくしかない

golangで超簡単なサーバ

フレームワークもあるけどまずはこちらから

単純なAPIなどが欲しかったりする場合などはこちらのほうがいいかもしれないので…

実装

sample
package main

import (
    "fmt"
    "net/http"
)

func main(){
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
        fmt.Fprint(w, "Golang Http Server")
    })
    http.ListenAndServe(":8080", nil)
}


f:id:m_shige1979:20160119234155p:plain

こんだけ

所感

やり方はnodejsと同じイメージかな…
jsonとかを扱う方法とかもちょっと調べておく

golangの学習(time)

日時に関する情報を制御する

timeパッケージを使用する

現在日時を取得する

sample
package main

import (
    "fmt"
    "time"
)

func main(){
    _now := time.Now()
    fmt.Println(_now)
}

$ go run time1.go
2016-01-19 22:46:07.181469119 +0900 JST
$

日時を任意のフォーマットで表示する

https://golang.org/src/time/format.go
※フォーマットの指定値がややこしいので気をつけないといけない

sample
package main

import (
    "fmt"
    "time"
)

func main(){
    // 現在日時を取得
    _now := time.Now()

    // format
    const YYYYMMDDHHMISS1 = "2006/01/02 15:04:05"
    const YYYYMMDDHHMISS2 = "06-1-2 3:4:5"

    fmt.Println(_now.Format(YYYYMMDDHHMISS1))
    fmt.Println(_now.Format(YYYYMMDDHHMISS2))
    fmt.Println(_now.Format(time.RFC3339))
}

$ go run time2.go
2016/01/19 22:56:21
16-1-19 10:56:21
2016-01-19T22:56:21+09:00
$

Unixタイムスタンプの秒数を取得

ちょっと意味は違うかも…

sanmple
package main

import (
    "fmt"
    "time"
)

func main(){
    _now := time.Now()
    fmt.Println(_now.Unix())
    fmt.Println(_now.UnixNano())
}

$ go run time3.go
1453212000
1453212000553662868
$

日付加算

日数、月数、年数を指定して加算、減算を行う

sample
package main

import (
    "fmt"
    "time"
)

func main(){
    // 現在の日時を取得
    _now := time.Now()
    fmt.Println(_now)
    fmt.Println("")

    // 日付計算
    fmt.Println(_now.AddDate(0, 0, 10).Format(time.RFC3339))
    fmt.Println(_now.AddDate(0, 2, 0).Format(time.RFC3339))
    fmt.Println(_now.AddDate(5, 0, 0).Format(time.RFC3339))

    fmt.Println("")

    fmt.Println(_now.AddDate(0, 0, -10).Format(time.RFC3339))
    fmt.Println(_now.AddDate(0, -2, 0).Format(time.RFC3339))
    fmt.Println(_now.AddDate(-5, 0, 0).Format(time.RFC3339))
}

$ go run time5.go
2016-01-19 23:06:58.719504358 +0900 JST

2016-01-29T23:06:58+09:00
2016-03-19T23:06:58+09:00
2021-01-19T23:06:58+09:00

2016-01-09T23:06:58+09:00
2015-11-19T23:06:58+09:00
2011-01-19T23:06:58+09:00
$

時間加算

時間を指定して加算、減算を行う

sample
package main

import (
    "fmt"
    "time"
)

func main(){
    // 現在の日時を取得
    _now := time.Now()
    fmt.Println(_now)
    fmt.Println("")

    // 日付計算
    fmt.Println(_now.Add(time.Duration(25) * time.Second).Format(time.RFC3339))
    fmt.Println(_now.Add(time.Duration(12) * time.Minute).Format(time.RFC3339))
    fmt.Println(_now.Add(time.Duration(05) * time.Hour).Format(time.RFC3339))

    fmt.Println("")

    fmt.Println(_now.Add(time.Duration(-25) * time.Second).Format(time.RFC3339))
    fmt.Println(_now.Add(time.Duration(-12) * time.Minute).Format(time.RFC3339))
    fmt.Println(_now.Add(time.Duration(-05) * time.Hour).Format(time.RFC3339))
}

$ go run time6.go
2016-01-19 23:13:56.686245405 +0900 JST

2016-01-19T23:14:21+09:00
2016-01-19T23:25:56+09:00
2016-01-20T04:13:56+09:00

2016-01-19T23:13:31+09:00
2016-01-19T23:01:56+09:00
2016-01-19T18:13:56+09:00
$

文字列を任意のレイアウトより日付に変換

sample
package main

import (
    "fmt"
    "time"
)

func main(){
    _date, _err := time.Parse("2006-01-02 15:04:05", "2001-10-23 15:54:20")
    if _err != nil {
        panic(_err)
    }
    fmt.Println(_date)
}

$ go run time7.go
2001-10-23 15:54:20 +0000 UTC
$

2つの日時より差を取得する

sample
package main

import (
    "fmt"
    "time"
)

func main(){
    // 2つの日時を設定
    _date1, _ := time.Parse("2006-01-02 15:04:05", "2001-10-23 15:54:20")
    _date2, _ := time.Parse("2006-01-02 15:04:05", "2002-10-23 15:54:20")

    // 差を取得する
    _d := _date2.Sub(_date1)

    // 差を出力する
    fmt.Println(_d)
}

$ go run time8.go
8760h0m0s
$

まあ、こんな感じ

所感

使いそうなものをとりあえず、調べてみた。
日付のフォーマットでちょっとつまづきそうだけど基本は抑えた感じ…多分
基本、手続き型言語の仕事が多すぎた分、慣れるのがちょっと大変かも

golangでExcelのファイルへ書き込み

使用するパッケージ

https://github.com/tealeg/xlsx

サンプルコード

package main

import (
    "fmt"
    "github.com/tealeg/xlsx"
)

func main(){
    // ファイル
    var file *xlsx.File
    // シート
    var sheet *xlsx.Sheet
    //
    var row *xlsx.Row
    var cell *xlsx.Cell
    var err error

    var fileName = "テストファイル.xlsx"

    file = xlsx.NewFile()
    sheet, err = file.AddSheet("サンプル1")
    if err != nil {
        fmt.Printf(err.Error())
    }

    for i:=0;i < 10;i++ {
        row = sheet.AddRow()
        for j:=0;j<10;j++ {
            cell = row.AddCell()
            cell.Value = fmt.Sprintf("%d行目,%d列目", i, j)
        }
    }

    // ファイルを保存
    err = file.Save(fileName)
    if err != nil {
        fmt.Printf(err.Error())
    }

}

macの環境にはOfficeがないので他のやつで開いた

f:id:m_shige1979:20160117011047p:plain
f:id:m_shige1979:20160117011651p:plain

セルのデータやシートも日本語で書き込みができてた
なんとか使えそう

goでライブラリのテストを試す

” testing”パッケージがある

これを使用してテストすることができるみたい

テスト対象

$ tree $GOPATH/src/github.com/mshige1979/
$GOPATH/src/github.com/mshige1979/
├── compute
│   └── add.go
└── hello
    └── hello.go

2 directories, 2 files
$

※computeとかいうサンプルライブラリ

テストコード

add_test.go
package compute

import (
    "testing"
)

func TestAdd(t *testing.T){
    const in1 = 10
    const in2 = 20
    const out = 30

    x := Add(in1, in2)
    if x != out {
        t.Error("Add(%d, %d) = %d\n Error!!!", in1, in2, x)
    }
}

※ファイル名に"_test"を付与するらしい

テスト
$ go test
PASS
ok  	github.com/mshige1979/compute	0.009s
$
テストちょっと詳しく
$ go test -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok  	github.com/mshige1979/compute	0.008s
$

こんな感じらしい

GOPATHを使用してgo installとかする

実行環境?

macです。ディスク容量がやばいのでもうそろそろ家のやつはminiに移行しようかと考え中

GOPATHってなん

go言語で使用する際のworkディレクトリみたいなものパッケージを取得する場合などやフレームワークを使いたい場合は必須

どこに作成するのか?

基本的に制限はないらしい
一般的にはgocodeとか別途バージョン番号とかで分けたりしていることもあるらしいけど

ディレクトリ構成は?

こうなった

$ tree
.
├── bin
├── pkg
└── src
    └── github.com
        └── mshige1979

5 directories, 0 files
$

bin:go installした際に配置される場所
pkg:中間ビルドされた時のファイルなどが配置されている感じ
src:ソースコードを置く

※go getコマンドで実行した際もここのディレクトリをベースに配置されるとのこと

サンプルになんかを作成する

hello的なやる

ディレクトリ作成
$ cd src/github.com/mshige1979/
$ mkdir hello
$ cd hello/
hello.go
package main

import (
    "fmt"
)

func main(){
    fmt.Printf("Hello, World!\n")
}
スクリプト実行
$ go run hello.go
Hello, World!
$
go install
$ go install
$ tree $GOPATH/bin
$GOPATH/bin
└── hello

0 directories, 1 file
$

※作成されていること

実行
$ $GOPATH/bin/hello
Hello, World!
$

ライブラリを作成する

computeとか…

ディレクトリ作成
$ mkdir compute
 cd compute/
add.go
package compute

func Add(a int, b int) int {
    return a + b
}

※まあ、超適当で…

さっきのhello.goを修正する
package main

import (
    "fmt"
    "github.com/mshige1979/compute"
)

func main(){
    fmt.Printf("Hello, World!\n")

    a := 10
    b := 20
    c := compute.Add(a, b)
    fmt.Printf("%d + %d = %d\n!", a, b, c)
}
インストールして実行
$ go install
$ $GOPATH/bin/hello
Hello, World!
10 + 20 = 30
$
pkgの中身
$ tree $GOPATH/pkg
$GOPATH/pkg
└── darwin_amd64
    └── github.com
        └── mshige1979
            └── compute.a

3 directories, 1 file
$

所感

goは使っていない変数とかパッケージの名前がおかしいと警告や想定案みたいなものをだすので原因をそこそこ見つけやすい
ちょっとテスト方法とかも調べてみる

SonarQubeをJenkinsで実行

以下の続き

m-shige1979.hatenablog.com

Jenkinsインストール

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins -y
sudo chkconfig jenkins on
sudo service jenkins start

プラグインとか初期設定は適当にする

f:id:m_shige1979:20160107230727p:plain

Jenkinsの「Jenkinsの管理」→「システム設定」を開き、SonarQubeの設定を確認する

Runner

f:id:m_shige1979:20160107232629p:plain

Server

f:id:m_shige1979:20160107233855p:plain

ジョブを設定

プロジェクトの作成

f:id:m_shige1979:20160108010925p:plain

ビルドの「Invoke Standalone SonarQube Analysis」を選択

f:id:m_shige1979:20160108011127p:plain

パラメータを指定

f:id:m_shige1979:20160108011515p:plain

ビルド結果

f:id:m_shige1979:20160108011657p:plain

おわり

所感

コマンドで実行する場合とjenkinsで実行する方法はまあなんとかこれでいい感じ。
除外するデータなどはパラメータを調べてから除外していく。
ルール自体はまあそのうち見てみよう。覚えるのがキツイのでちょっと後回し